1 /**
2  * Forms the symbols available to all D programs. Includes Object, which is
3  * the root of the class object hierarchy.  This module is implicitly
4  * imported.
5  *
6  * Copyright: Copyright Digital Mars 2000 - 2011.
7  * License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
8  * Authors:   Walter Bright, Sean Kelly
9  */
10 
11 module object;
12 
13 // NOTE: For some reason, this declaration method doesn't work
14 //       in this particular file (and this file only).  It must
15 //       be a DMD thing.
16 //alias typeof(int.sizeof)                    size_t;
17 //alias typeof(cast(void*)0 - cast(void*)0)   ptrdiff_t;
18 
19 version (D_LP64)
20 {
21     alias size_t = ulong;
22     alias ptrdiff_t = long;
23 }
24 else
25 {
26     alias size_t = uint;
27     alias ptrdiff_t = int;
28 }
29 
30 alias sizediff_t = ptrdiff_t; //For backwards compatibility only.
31 
32 alias hash_t = size_t; //For backwards compatibility only.
33 alias equals_t = bool; //For backwards compatibility only.
34 
35 alias string  = immutable(char)[];
36 alias wstring = immutable(wchar)[];
37 alias dstring = immutable(dchar)[];
38 
39 version (D_ObjectiveC) public import core.attribute : selector;
40 
41 int __cmp(T)(scope const T[] lhs, scope const T[] rhs) @trusted
42     if (__traits(isScalar, T))
43 {
44     // Compute U as the implementation type for T
45     static if (is(T == ubyte) || is(T == void) || is(T == bool))
46         alias U = char;
47     else static if (is(T == wchar))
48         alias U = ushort;
49     else static if (is(T == dchar))
50         alias U = uint;
51     else static if (is(T == ifloat))
52         alias U = float;
53     else static if (is(T == idouble))
54         alias U = double;
55     else static if (is(T == ireal))
56         alias U = real;
57     else
58         alias U = T;
59 
60     static if (is(U == char))
61     {
62         import core.internal..string : dstrcmp;
63         return dstrcmp(cast(char[]) lhs, cast(char[]) rhs);
64     }
65     else static if (!is(U == T))
66     {
67         // Reuse another implementation
68         return __cmp(cast(U[]) lhs, cast(U[]) rhs);
69     }
70     else
71     {
72         version (BigEndian)
73         static if (__traits(isUnsigned, T) ? !is(T == __vector) : is(T : P*, P))
74         {
75             if (!__ctfe)
76             {
77                 import core.stdc..string : memcmp;
78                 int c = memcmp(lhs.ptr, rhs.ptr, (lhs.length <= rhs.length ? lhs.length : rhs.length) * T.sizeof);
79                 if (c)
80                     return c;
81                 static if (size_t.sizeof <= uint.sizeof && T.sizeof >= 2)
82                     return cast(int) lhs.length - cast(int) rhs.length;
83                 else
84                     return int(lhs.length > rhs.length) - int(lhs.length < rhs.length);
85             }
86         }
87 
88         immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length;
89         foreach (const u; 0 .. len)
90         {
91             static if (__traits(isFloating, T))
92             {
93                 immutable a = lhs.ptr[u], b = rhs.ptr[u];
94                 static if (is(T == cfloat) || is(T == cdouble)
95                     || is(T == creal))
96                 {
97                     // Use rt.cmath2._Ccmp instead ?
98                     auto r = (a.re > b.re) - (a.re < b.re);
99                     if (!r) r = (a.im > b.im) - (a.im < b.im);
100                 }
101                 else
102                 {
103                     const r = (a > b) - (a < b);
104                 }
105                 if (r) return r;
106             }
107             else if (lhs.ptr[u] != rhs.ptr[u])
108                 return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1;
109         }
110         return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length);
111     }
112 }
113 
114     // Compare class and interface objects for ordering.
115     private int __cmp(Obj)(Obj lhs, Obj rhs)
116     if (is(Obj : Object))
117     {
118         if (lhs is rhs)
119             return 0;
120         // Regard null references as always being "less than"
121         if (!lhs)
122             return -1;
123         if (!rhs)
124             return 1;
125         return lhs.opCmp(rhs);
126     }
127 
128     // This function is called by the compiler when dealing with array
129     // comparisons in the semantic analysis phase of CmpExp. The ordering
130     // comparison is lowered to a call to this template.
131     int __cmp(T1, T2)(T1[] s1, T2[] s2)
132     if (!__traits(isScalar, T1) && !__traits(isScalar, T2))
133     {
134         import core.internal.traits : Unqual;
135         alias U1 = Unqual!T1;
136         alias U2 = Unqual!T2;
137 
138         static if (is(U1 == void) && is(U2 == void))
139             static @trusted ref inout(ubyte) at(inout(void)[] r, size_t i) { return (cast(inout(ubyte)*) r.ptr)[i]; }
140         else
141             static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
142 
143         // All unsigned byte-wide types = > dstrcmp
144         immutable len = s1.length <= s2.length ? s1.length : s2.length;
145 
146         foreach (const u; 0 .. len)
147         {
148             static if (__traits(compiles, __cmp(at(s1, u), at(s2, u))))
149             {
150                 auto c = __cmp(at(s1, u), at(s2, u));
151                 if (c != 0)
152                     return c;
153             }
154             else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u))))
155             {
156                 auto c = at(s1, u).opCmp(at(s2, u));
157                 if (c != 0)
158                     return c;
159             }
160             else static if (__traits(compiles, at(s1, u) < at(s2, u)))
161             {
162                 if (at(s1, u) != at(s2, u))
163                     return at(s1, u) < at(s2, u) ? -1 : 1;
164             }
165             else
166             {
167                 // TODO: fix this legacy bad behavior, see
168                 // https://issues.dlang.org/show_bug.cgi?id=17244
169                 static assert(is(U1 == U2), "Internal error.");
170                 import core.stdc..string : memcmp;
171                 auto c = (() @trusted => memcmp(&at(s1, u), &at(s2, u), U1.sizeof))();
172                 if (c != 0)
173                     return c;
174             }
175         }
176         return s1.length < s2.length ? -1 : (s1.length > s2.length);
177     }
178 
179     // integral types
180     @safe unittest
181     {
182         void compareMinMax(T)()
183         {
184             T[2] a = [T.max, T.max];
185             T[2] b = [T.min, T.min];
186 
187             assert(__cmp(a, b) > 0);
188             assert(__cmp(b, a) < 0);
189         }
190 
191         compareMinMax!int;
192         compareMinMax!uint;
193         compareMinMax!long;
194         compareMinMax!ulong;
195         compareMinMax!short;
196         compareMinMax!ushort;
197         compareMinMax!byte;
198         compareMinMax!dchar;
199         compareMinMax!wchar;
200     }
201 
202     // char types (dstrcmp)
203     @safe unittest
204     {
205         void compareMinMax(T)()
206         {
207             T[2] a = [T.max, T.max];
208             T[2] b = [T.min, T.min];
209 
210             assert(__cmp(a, b) > 0);
211             assert(__cmp(b, a) < 0);
212         }
213 
214         compareMinMax!ubyte;
215         compareMinMax!bool;
216         compareMinMax!char;
217         compareMinMax!(const char);
218 
219         string s1 = "aaaa";
220         string s2 = "bbbb";
221         assert(__cmp(s2, s1) > 0);
222         assert(__cmp(s1, s2) < 0);
223     }
224 
225     // fp types
226     @safe unittest
227     {
228         void compareMinMax(T)()
229         {
230             T[2] a = [T.max, T.max];
231             T[2] b = [T.min_normal, T.min_normal];
232             T[2] c = [T.max, T.min_normal];
233             T[1] d = [T.max];
234 
235             assert(__cmp(a, b) > 0);
236             assert(__cmp(b, a) < 0);
237             assert(__cmp(a, c) > 0);
238             assert(__cmp(a, d) > 0);
239             assert(__cmp(d, c) < 0);
240             assert(__cmp(c, c) == 0);
241         }
242 
243         compareMinMax!real;
244         compareMinMax!float;
245         compareMinMax!double;
246         compareMinMax!ireal;
247         compareMinMax!ifloat;
248         compareMinMax!idouble;
249         compareMinMax!creal;
250         //compareMinMax!cfloat;
251         compareMinMax!cdouble;
252 
253         // qualifiers
254         compareMinMax!(const real);
255         compareMinMax!(immutable real);
256     }
257 
258     // void[]
259     @safe unittest
260     {
261         void[] a;
262         const(void)[] b;
263 
264         (() @trusted
265         {
266             a = cast(void[]) "bb";
267             b = cast(const(void)[]) "aa";
268         })();
269 
270         assert(__cmp(a, b) > 0);
271         assert(__cmp(b, a) < 0);
272     }
273 
274     // arrays of arrays with mixed modifiers
275     @safe unittest
276     {
277         // https://issues.dlang.org/show_bug.cgi?id=17876
278         bool less1(immutable size_t[][] a, size_t[][] b) { return a < b; }
279         bool less2(const void[][] a, void[][] b) { return a < b; }
280         bool less3(inout size_t[][] a, size_t[][] b) { return a < b; }
281 
282         immutable size_t[][] a = [[1, 2], [3, 4]];
283         size_t[][] b = [[1, 2], [3, 5]];
284         assert(less1(a, b));
285         assert(less3(a, b));
286 
287         auto va = [cast(immutable void[])a[0], a[1]];
288         auto vb = [cast(void[])b[0], b[1]];
289         assert(less2(va, vb));
290     }
291 
292     // objects
293     @safe unittest
294     {
295         class C
296         {
297             int i;
298             this(int i) { this.i = i; }
299 
300             override int opCmp(Object c) const @safe
301             {
302                 return i - (cast(C)c).i;
303             }
304         }
305 
306         auto c1 = new C(1);
307         auto c2 = new C(2);
308         assert(__cmp(c1, null) > 0);
309         assert(__cmp(null, c1) < 0);
310         assert(__cmp(c1, c1) == 0);
311         assert(__cmp(c1, c2) < 0);
312         assert(__cmp(c2, c1) > 0);
313 
314         assert(__cmp([c1, c1][], [c2, c2][]) < 0);
315         assert(__cmp([c2, c2], [c1, c1]) > 0);
316     }
317 
318     // structs
319     @safe unittest
320     {
321         struct C
322         {
323             ubyte i;
324             this(ubyte i) { this.i = i; }
325         }
326 
327         auto c1 = C(1);
328         auto c2 = C(2);
329 
330         assert(__cmp([c1, c1][], [c2, c2][]) < 0);
331         assert(__cmp([c2, c2], [c1, c1]) > 0);
332         assert(__cmp([c2, c2], [c2, c1]) > 0);
333     }
334 
335 // `lhs == rhs` lowers to `__equals(lhs, rhs)` for dynamic arrays
336 bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
337 {
338     import core.internal.traits : Unqual;
339     alias U1 = Unqual!T1;
340     alias U2 = Unqual!T2;
341 
342     static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
343     static @trusted R trustedCast(R, S)(S[] r) { return cast(R) r; }
344 
345     if (lhs.length != rhs.length)
346         return false;
347 
348     if (lhs.length == 0 && rhs.length == 0)
349         return true;
350 
351     static if (is(U1 == void) && is(U2 == void))
352     {
353         return __equals(trustedCast!(ubyte[])(lhs), trustedCast!(ubyte[])(rhs));
354     }
355     else static if (is(U1 == void))
356     {
357         return __equals(trustedCast!(ubyte[])(lhs), rhs);
358     }
359     else static if (is(U2 == void))
360     {
361         return __equals(lhs, trustedCast!(ubyte[])(rhs));
362     }
363     else static if (!is(U1 == U2))
364     {
365         // This should replace src/object.d _ArrayEq which
366         // compares arrays of different types such as long & int,
367         // char & wchar.
368         // Compiler lowers to __ArrayEq in dmd/src/opover.d
369         foreach (const u; 0 .. lhs.length)
370         {
371             if (at(lhs, u) != at(rhs, u))
372                 return false;
373         }
374         return true;
375     }
376     else static if (__traits(isIntegral, U1))
377     {
378 
379         if (!__ctfe)
380         {
381             import core.stdc..string : memcmp;
382             return () @trusted { return memcmp(cast(void*)lhs.ptr, cast(void*)rhs.ptr, lhs.length * U1.sizeof) == 0; }();
383         }
384         else
385         {
386             foreach (const u; 0 .. lhs.length)
387             {
388                 if (at(lhs, u) != at(rhs, u))
389                     return false;
390             }
391             return true;
392         }
393     }
394     else
395     {
396         foreach (const u; 0 .. lhs.length)
397         {
398             static if (__traits(compiles, __equals(at(lhs, u), at(rhs, u))))
399             {
400                 if (!__equals(at(lhs, u), at(rhs, u)))
401                     return false;
402             }
403             else static if (__traits(isFloating, U1))
404             {
405                 if (at(lhs, u) != at(rhs, u))
406                     return false;
407             }
408             else static if (is(U1 : Object) && is(U2 : Object))
409             {
410                 if (!(cast(Object)at(lhs, u) is cast(Object)at(rhs, u)
411                     || at(lhs, u) && (cast(Object)at(lhs, u)).opEquals(cast(Object)at(rhs, u))))
412                     return false;
413             }
414             else static if (__traits(hasMember, U1, "opEquals"))
415             {
416                 if (!at(lhs, u).opEquals(at(rhs, u)))
417                     return false;
418             }
419             else static if (is(U1 == delegate))
420             {
421                 if (at(lhs, u) != at(rhs, u))
422                     return false;
423             }
424             else static if (is(U1 == U11*, U11))
425             {
426                 if (at(lhs, u) != at(rhs, u))
427                     return false;
428             }
429             else static if (__traits(isAssociativeArray, U1))
430             {
431                 if (at(lhs, u) != at(rhs, u))
432                     return false;
433             }
434             else
435             {
436                 if (at(lhs, u).tupleof != at(rhs, u).tupleof)
437                     return false;
438             }
439         }
440 
441         return true;
442     }
443 }
444 
445 unittest {
446     assert(__equals([], []));
447     assert(!__equals([1, 2], [1, 2, 3]));
448 }
449 
450 unittest
451 {
452     struct A
453     {
454         int a;
455     }
456 
457     auto arr1 = [A(0), A(2)];
458     auto arr2 = [A(0), A(1)];
459     auto arr3 = [A(0), A(1)];
460 
461     assert(arr1 != arr2);
462     assert(arr2 == arr3);
463 }
464 
465 unittest
466 {
467     struct A
468     {
469         int a;
470         int b;
471 
472         bool opEquals(const A other)
473         {
474             return this.a == other.b && this.b == other.a;
475         }
476     }
477 
478     auto arr1 = [A(1, 0), A(0, 1)];
479     auto arr2 = [A(1, 0), A(0, 1)];
480     auto arr3 = [A(0, 1), A(1, 0)];
481 
482     assert(arr1 != arr2);
483     assert(arr2 == arr3);
484 }
485 
486 // https://issues.dlang.org/show_bug.cgi?id=18252
487 unittest
488 {
489     string[int][] a1, a2;
490     assert(__equals(a1, a2));
491     assert(a1 == a2);
492     a1 ~= [0: "zero"];
493     a2 ~= [0: "zero"];
494     assert(__equals(a1, a2));
495     assert(a1 == a2);
496     a2[0][1] = "one";
497     assert(!__equals(a1, a2));
498     assert(a1 != a2);
499 }
500 
501 /**
502 Destroys the given object and optionally resets to initial state. It's used to
503 _destroy an object, calling its destructor or finalizer so it no longer
504 references any other objects. It does $(I not) initiate a GC cycle or free
505 any GC memory.
506 If `initialize` is supplied `false`, the object is considered invalid after
507 destruction, and should not be referenced.
508 */
509 void destroy(bool initialize = true, T)(ref T obj) if (is(T == struct))
510 {
511     _destructRecurse(obj);
512 
513     static if (initialize)
514     {
515         // We need to re-initialize `obj`.  Previously, an immutable static
516         // and memcpy were used to hold an initializer. With improved unions, this is no longer
517         // needed.
518         union UntypedInit
519         {
520             T dummy;
521         }
522         static struct UntypedStorage
523         {
524             align(T.alignof) void[T.sizeof] dummy;
525         }
526 
527         () @trusted {
528             *cast(UntypedStorage*) &obj = cast(UntypedStorage) UntypedInit.init;
529         } ();
530     }
531 }
532 
533 @safe unittest
534 {
535     struct A { string s = "A";  }
536     A a = {s: "B"};
537     assert(a.s == "B");
538     a.destroy;
539     assert(a.s == "A");
540 }
541 
542 private void _destructRecurse(S)(ref S s)
543     if (is(S == struct))
544 {
545     static if (__traits(hasMember, S, "__xdtor") &&
546             // Bugzilla 14746: Check that it's the exact member of S.
547             __traits(isSame, S, __traits(parent, s.__xdtor)))
548         s.__xdtor();
549 }
550 
551 nothrow @safe @nogc unittest
552 {
553     {
554         struct A { string s = "A";  }
555         A a;
556         a.s = "asd";
557         destroy!false(a);
558         assert(a.s == "asd");
559         destroy(a);
560         assert(a.s == "A");
561     }
562     {
563         static int destroyed = 0;
564         struct C
565         {
566             string s = "C";
567             ~this() nothrow @safe @nogc
568             {
569                 destroyed ++;
570             }
571         }
572 
573         struct B
574         {
575             C c;
576             string s = "B";
577             ~this() nothrow @safe @nogc
578             {
579                 destroyed ++;
580             }
581         }
582         B a;
583         a.s = "asd";
584         a.c.s = "jkl";
585         destroy!false(a);
586         assert(destroyed == 2);
587         assert(a.s == "asd");
588         assert(a.c.s == "jkl" );
589         destroy(a);
590         assert(destroyed == 4);
591         assert(a.s == "B");
592         assert(a.c.s == "C" );
593     }
594 }
595 
596 
597     /// ditto
598     void destroy(bool initialize = true, T)(T obj) if (is(T == class))
599     {
600         static if (__traits(getLinkage, T) == "C++")
601         {
602             obj.__xdtor();
603 
604             static if (initialize)
605             {
606                 enum classSize = __traits(classInstanceSize, T);
607                 (cast(void*)obj)[0 .. classSize] = typeid(T).initializer[];
608             }
609         }
610         else
611             rt_finalize(cast(void*)obj);
612     }
613 
614     /// ditto
615     void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
616     {
617         static assert(__traits(getLinkage, T) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage, T) ~ ") interface");
618 
619         destroy!initialize(cast(Object)obj);
620     }
621 
622     /// Reference type demonstration
623     unittest
624     {
625         class C
626         {
627             struct Agg
628             {
629                 static int dtorCount;
630 
631                 int x = 10;
632                 ~this() { dtorCount++; }
633             }
634 
635             static int dtorCount;
636 
637             string s = "S";
638             Agg a;
639             ~this() { dtorCount++; }
640         }
641 
642         C c = new C();
643         assert(c.dtorCount == 0);   // destructor not yet called
644         assert(c.s == "S");         // initial state `c.s` is `"S"`
645         assert(c.a.dtorCount == 0); // destructor not yet called
646         assert(c.a.x == 10);        // initial state `c.a.x` is `10`
647         c.s = "T";
648         c.a.x = 30;
649         assert(c.s == "T");         // `c.s` is `"T"`
650         destroy(c);
651         assert(c.dtorCount == 1);   // `c`'s destructor was called
652         assert(c.s == "S");         // `c.s` is back to its inital state, `"S"`
653         assert(c.a.dtorCount == 1); // `c.a`'s destructor was called
654         assert(c.a.x == 10);        // `c.a.x` is back to its inital state, `10`
655 
656         // check C++ classes work too!
657         extern (C++) class CPP
658         {
659             struct Agg
660             {
661                 __gshared int dtorCount;
662 
663                 int x = 10;
664                 ~this() { dtorCount++; }
665             }
666 
667             __gshared int dtorCount;
668 
669             string s = "S";
670             Agg a;
671             ~this() { dtorCount++; }
672         }
673 
674         CPP cpp = new CPP();
675         assert(cpp.dtorCount == 0);   // destructor not yet called
676         assert(cpp.s == "S");         // initial state `cpp.s` is `"S"`
677         assert(cpp.a.dtorCount == 0); // destructor not yet called
678         assert(cpp.a.x == 10);        // initial state `cpp.a.x` is `10`
679         cpp.s = "T";
680         cpp.a.x = 30;
681         assert(cpp.s == "T");         // `cpp.s` is `"T"`
682         destroy!false(cpp);           // destroy without initialization
683         assert(cpp.dtorCount == 1);   // `cpp`'s destructor was called
684         assert(cpp.s == "T");         // `cpp.s` is not initialized
685         assert(cpp.a.dtorCount == 1); // `cpp.a`'s destructor was called
686         assert(cpp.a.x == 30);        // `cpp.a.x` is not initialized
687         destroy(cpp);
688         assert(cpp.dtorCount == 2);   // `cpp`'s destructor was called again
689         assert(cpp.s == "S");         // `cpp.s` is back to its inital state, `"S"`
690         assert(cpp.a.dtorCount == 2); // `cpp.a`'s destructor was called again
691         assert(cpp.a.x == 10);        // `cpp.a.x` is back to its inital state, `10`
692     }
693 
694     /// Value type demonstration
695     unittest
696     {
697         int i;
698         assert(i == 0);           // `i`'s initial state is `0`
699         i = 1;
700         assert(i == 1);           // `i` changed to `1`
701         destroy!false(i);
702         assert(i == 1);           // `i` was not initialized
703         destroy(i);
704         assert(i == 0);           // `i` is back to its initial state `0`
705     }
706 
707     unittest
708     {
709         // class with an `alias this`
710         class A
711         {
712             static int dtorCount;
713             ~this()
714             {
715                 dtorCount++;
716             }
717         }
718 
719         class B
720         {
721             A a;
722             alias a this;
723             this()
724             {
725                 a = new A;
726             }
727             static int dtorCount;
728             ~this()
729             {
730                 dtorCount++;
731             }
732         }
733         auto b = new B;
734         assert(A.dtorCount == 0);
735         assert(B.dtorCount == 0);
736         destroy(b);
737         assert(A.dtorCount == 0);
738         assert(B.dtorCount == 1);
739     }
740 
741     unittest
742     {
743         interface I { }
744         {
745             class A: I { string s = "A"; this() {} }
746             auto a = new A, b = new A;
747             a.s = b.s = "asd";
748             destroy(a);
749             assert(a.s == "A");
750 
751             I i = b;
752             destroy(i);
753             assert(b.s == "A");
754         }
755         {
756             static bool destroyed = false;
757             class B: I
758             {
759                 string s = "B";
760                 this() {}
761                 ~this()
762                 {
763                     destroyed = true;
764                 }
765             }
766             auto a = new B, b = new B;
767             a.s = b.s = "asd";
768             destroy(a);
769             assert(destroyed);
770             assert(a.s == "B");
771 
772             destroyed = false;
773             I i = b;
774             destroy(i);
775             assert(destroyed);
776             assert(b.s == "B");
777         }
778         // this test is invalid now that the default ctor is not run after clearing
779         version (none)
780         {
781             class C
782             {
783                 string s;
784                 this()
785                 {
786                     s = "C";
787                 }
788             }
789             auto a = new C;
790             a.s = "asd";
791             destroy(a);
792             assert(a.s == "C");
793         }
794     }
795 
796     nothrow @safe @nogc unittest
797     {
798         {
799             struct A { string s = "A";  }
800             A a;
801             a.s = "asd";
802             destroy!false(a);
803             assert(a.s == "asd");
804             destroy(a);
805             assert(a.s == "A");
806         }
807         {
808             static int destroyed = 0;
809             struct C
810             {
811                 string s = "C";
812                 ~this() nothrow @safe @nogc
813                 {
814                     destroyed ++;
815                 }
816             }
817 
818             struct B
819             {
820                 C c;
821                 string s = "B";
822                 ~this() nothrow @safe @nogc
823                 {
824                     destroyed ++;
825                 }
826             }
827             B a;
828             a.s = "asd";
829             a.c.s = "jkl";
830             destroy!false(a);
831             assert(destroyed == 2);
832             assert(a.s == "asd");
833             assert(a.c.s == "jkl" );
834             destroy(a);
835             assert(destroyed == 4);
836             assert(a.s == "B");
837             assert(a.c.s == "C" );
838         }
839     }
840 
841     /// ditto
842     void destroy(bool initialize = true, T : U[n], U, size_t n)(ref T obj) if (!is(T == struct))
843     {
844         foreach_reverse (ref e; obj[])
845             destroy!initialize(e);
846     }
847 
848     unittest
849     {
850         int[2] a;
851         a[0] = 1;
852         a[1] = 2;
853         destroy!false(a);
854         assert(a == [ 1, 2 ]);
855         destroy(a);
856         assert(a == [ 0, 0 ]);
857     }
858 
859     unittest
860     {
861         static struct vec2f {
862             float[2] values;
863             alias values this;
864         }
865 
866         vec2f v;
867         destroy!(true, vec2f)(v);
868     }
869 
870     unittest
871     {
872         // Bugzilla 15009
873         static string op;
874         static struct S
875         {
876             int x;
877             this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; }
878             this(this)  { op ~= "P" ~ cast(char)('0'+x); }
879             ~this()     { op ~= "D" ~ cast(char)('0'+x); }
880         }
881 
882         {
883             S[2] a1 = [S(1), S(2)];
884             op = "";
885         }
886         assert(op == "D2D1");   // built-in scope destruction
887         {
888             S[2] a1 = [S(1), S(2)];
889             op = "";
890             destroy(a1);
891             assert(op == "D2D1");   // consistent with built-in behavior
892         }
893 
894         {
895             S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
896             op = "";
897         }
898         assert(op == "D4D3D2D1");
899         {
900             S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
901             op = "";
902             destroy(a2);
903             assert(op == "D4D3D2D1", op);
904         }
905     }
906 
907     /// ditto
908     void destroy(bool initialize = true, T)(ref T obj)
909         if (!is(T == struct) && !is(T == interface) && !is(T == class) && !_isStaticArray!T)
910     {
911         static if (initialize)
912             obj = T.init;
913     }
914 
915     template _isStaticArray(T : U[N], U, size_t N)
916     {
917         enum bool _isStaticArray = true;
918     }
919 
920     template _isStaticArray(T)
921     {
922         enum bool _isStaticArray = false;
923     }
924 
925     unittest
926     {
927         {
928             int a = 42;
929             destroy!false(a);
930             assert(a == 42);
931             destroy(a);
932             assert(a == 0);
933         }
934         {
935             float a = 42;
936             destroy!false(a);
937             assert(a == 42);
938             destroy(a);
939             assert(a != a); // isnan
940         }
941     }
942 
943 
944 private
945 {
946     extern (C) Object _d_newclass(const TypeInfo_Class ci);
947     extern (C) void rt_finalize(void *data, bool det=true);
948 }
949 
950 public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
951 
952 /**
953  * All D class objects inherit from Object.
954  */
955 class Object
956 {
957     /**
958      * Convert Object to a human readable string.
959      */
960     string toString()
961     {
962         return typeid(this).name;
963     }
964 
965     /**
966      * Compute hash function for Object.
967      */
968     size_t toHash() @trusted nothrow
969     {
970         // BUG: this prevents a compacting GC from working, needs to be fixed
971         size_t addr = cast(size_t) cast(void*) this;
972         // The bottom log2((void*).alignof) bits of the address will always
973         // be 0. Moreover it is likely that each Object is allocated with a
974         // separate call to malloc. The alignment of malloc differs from
975         // platform to platform, but rather than having special cases for
976         // each platform it is safe to use a shift of 4. To minimize
977         // collisions in the low bits it is more important for the shift to
978         // not be too small than for the shift to not be too big.
979         return addr ^ (addr >>> 4);
980     }
981 
982     /**
983      * Compare with another Object obj.
984      * Returns:
985      *  $(TABLE
986      *  $(TR $(TD this &lt; obj) $(TD &lt; 0))
987      *  $(TR $(TD this == obj) $(TD 0))
988      *  $(TR $(TD this &gt; obj) $(TD &gt; 0))
989      *  )
990      */
991     int opCmp(Object o)
992     {
993         // BUG: this prevents a compacting GC from working, needs to be fixed
994         //return cast(int)cast(void*)this - cast(int)cast(void*)o;
995 
996         throw new Exception("need opCmp for class " ~ typeid(this).name);
997         //return this !is o;
998     }
999 
1000     /**
1001      * Test whether $(D this) is equal to $(D o).
1002      * The default implementation only compares by identity (using the $(D is) operator).
1003      * Generally, overrides for $(D opEquals) should attempt to compare objects by their contents.
1004      */
1005     bool opEquals(Object o)
1006     {
1007         return this is o;
1008     }
1009 
1010     interface Monitor
1011     {
1012         void lock();
1013         void unlock();
1014     }
1015 
1016     /**
1017      * Create instance of class specified by the fully qualified name
1018      * classname.
1019      * The class must either have no constructors or have
1020      * a default constructor.
1021      * Returns:
1022      *   null if failed
1023      * Example:
1024      * ---
1025      * module foo.bar;
1026      *
1027      * class C
1028      * {
1029      *     this() { x = 10; }
1030      *     int x;
1031      * }
1032      *
1033      * void main()
1034      * {
1035      *     auto c = cast(C)Object.factory("foo.bar.C");
1036      *     assert(c !is null && c.x == 10);
1037      * }
1038      * ---
1039      */
1040     static Object factory(string classname)
1041     {
1042         auto ci = TypeInfo_Class.find(classname);
1043         if (ci)
1044         {
1045             return ci.create();
1046         }
1047         return null;
1048     }
1049 }
1050 
1051 bool opEquals(Object lhs, Object rhs)
1052 {
1053     // If aliased to the same object or both null => equal
1054     if (lhs is rhs) return true;
1055 
1056     // If either is null => non-equal
1057     if (lhs is null || rhs is null) return false;
1058 
1059     // If same exact type => one call to method opEquals
1060     if (typeid(lhs) is typeid(rhs) ||
1061         !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
1062             /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
1063             (issue 7147). But CTFE also guarantees that equal TypeInfos are
1064             always identical. So, no opEquals needed during CTFE. */
1065     {
1066         return lhs.opEquals(rhs);
1067     }
1068 
1069     // General case => symmetric calls to method opEquals
1070     return lhs.opEquals(rhs) && rhs.opEquals(lhs);
1071 }
1072 
1073 /************************
1074 * Returns true if lhs and rhs are equal.
1075 */
1076 bool opEquals(const Object lhs, const Object rhs)
1077 {
1078     // A hack for the moment.
1079     return opEquals(cast()lhs, cast()rhs);
1080 }
1081 
1082 /// If aliased to the same object or both null => equal
1083 @system unittest
1084 {
1085     class F { int flag; this(int flag) { this.flag = flag; } }
1086 
1087     F f;
1088     assert(f == f); // both null
1089     f = new F(1);
1090     assert(f == f); // both aliased to the same object
1091 }
1092 
1093 /// If either is null => non-equal
1094 @system unittest
1095 {
1096     class F { int flag; this(int flag) { this.flag = flag; } }
1097     F f;
1098     assert(!(new F(0) == f));
1099     assert(!(f == new F(0)));
1100 }
1101 
1102 /// If same exact type => one call to method opEquals
1103 @system unittest
1104 {
1105     class F
1106     {
1107         int flag;
1108 
1109         this(int flag)
1110         {
1111             this.flag = flag;
1112         }
1113 
1114         override bool opEquals(const Object o)
1115         {
1116             return flag == (cast(F) o).flag;
1117         }
1118     }
1119 
1120     F f;
1121     assert(new F(0) == new F(0));
1122     assert(!(new F(0) == new F(1)));
1123 }
1124 
1125 /// General case => symmetric calls to method opEquals
1126 @system unittest
1127 {
1128     int fEquals, gEquals;
1129 
1130     class Base
1131     {
1132         int flag;
1133         this(int flag)
1134         {
1135             this.flag = flag;
1136         }
1137     }
1138 
1139     class F : Base
1140     {
1141         this(int flag) { super(flag); }
1142 
1143         override bool opEquals(const Object o)
1144         {
1145             fEquals++;
1146             return flag == (cast(Base) o).flag;
1147         }
1148     }
1149 
1150     class G : Base
1151     {
1152         this(int flag) { super(flag); }
1153 
1154         override bool opEquals(const Object o)
1155         {
1156             gEquals++;
1157             return flag == (cast(Base) o).flag;
1158         }
1159     }
1160 
1161     assert(new F(1) == new G(1));
1162     assert(fEquals == 1);
1163     assert(gEquals == 1);
1164 }
1165 
1166 private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
1167 
1168 void setSameMutex(shared Object ownee, shared Object owner)
1169 {
1170     _d_setSameMutex(ownee, owner);
1171 }
1172 
1173 /**
1174  * Information about an interface.
1175  * When an object is accessed via an interface, an Interface* appears as the
1176  * first entry in its vtbl.
1177  */
1178 struct Interface
1179 {
1180     TypeInfo_Class   classinfo;  /// .classinfo for this interface (not for containing class)
1181     void*[]     vtbl;
1182     size_t      offset;     /// offset to Interface 'this' from Object 'this'
1183 }
1184 
1185 /**
1186  * Array of pairs giving the offset and type information for each
1187  * member in an aggregate.
1188  */
1189 struct OffsetTypeInfo
1190 {
1191     size_t   offset;    /// Offset of member from start of object
1192     TypeInfo ti;        /// TypeInfo for this member
1193 }
1194 
1195 /**
1196  * Runtime type information about a type.
1197  * Can be retrieved for any type using a
1198  * $(GLINK2 expression,TypeidExpression, TypeidExpression).
1199  */
1200 class TypeInfo
1201 {
1202     override string toString() const pure @safe nothrow
1203     {
1204         return typeid(this).name;
1205     }
1206 
1207     override size_t toHash() @trusted const nothrow
1208     {
1209         return hashOf(this.toString());
1210     }
1211 
1212     override int opCmp(Object o)
1213     {
1214         import core.internal..string : dstrcmp;
1215 
1216         if (this is o)
1217             return 0;
1218         TypeInfo ti = cast(TypeInfo)o;
1219         if (ti is null)
1220             return 1;
1221         return dstrcmp(this.toString(), ti.toString());
1222     }
1223 
1224     override bool opEquals(Object o)
1225     {
1226         /* TypeInfo instances are singletons, but duplicates can exist
1227          * across DLL's. Therefore, comparing for a name match is
1228          * sufficient.
1229          */
1230         if (this is o)
1231             return true;
1232         auto ti = cast(const TypeInfo)o;
1233         return ti && this.toString() == ti.toString();
1234     }
1235 
1236     /**
1237      * Computes a hash of the instance of a type.
1238      * Params:
1239      *    p = pointer to start of instance of the type
1240      * Returns:
1241      *    the hash
1242      * Bugs:
1243      *    fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
1244      */
1245     size_t getHash(scope const void* p) @trusted nothrow const
1246     {
1247         return hashOf(p);
1248     }
1249 
1250     /// Compares two instances for equality.
1251     bool equals(in void* p1, in void* p2) const { return p1 == p2; }
1252 
1253     /// Compares two instances for &lt;, ==, or &gt;.
1254     int compare(in void* p1, in void* p2) const { return _xopCmp(p1, p2); }
1255 
1256     /// Returns size of the type.
1257     @property size_t tsize() nothrow pure const @safe @nogc { return 0; }
1258 
1259     /// Swaps two instances of the type.
1260     void swap(void* p1, void* p2) const
1261     {
1262         immutable size_t n = tsize;
1263         for (size_t i = 0; i < n; i++)
1264         {
1265             byte t = (cast(byte *)p1)[i];
1266             (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
1267             (cast(byte*)p2)[i] = t;
1268         }
1269     }
1270 
1271     /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
1272     null if none. */
1273     @property inout(TypeInfo) next() nothrow pure inout @nogc { return null; }
1274 
1275     /**
1276      * Return default initializer.  If the type should be initialized to all
1277      * zeros, an array with a null ptr and a length equal to the type size will
1278      * be returned. For static arrays, this returns the default initializer for
1279      * a single element of the array, use `tsize` to get the correct size.
1280      */
1281     abstract const(void)[] initializer() nothrow pure const @safe @nogc;
1282 
1283     /** Get flags for type: 1 means GC should scan for pointers,
1284     2 means arg of this type is passed in XMM register */
1285     @property uint flags() nothrow pure const @safe @nogc { return 0; }
1286 
1287     /// Get type information on the contents of the type; null if not available
1288     const(OffsetTypeInfo)[] offTi() const { return null; }
1289     /// Run the destructor on the object and all its sub-objects
1290     void destroy(void* p) const {}
1291     /// Run the postblit on the object and all its sub-objects
1292     void postblit(void* p) const {}
1293 
1294 
1295     /// Return alignment of type
1296     @property size_t talign() nothrow pure const @safe @nogc { return tsize; }
1297 
1298     /** Return internal info on arguments fitting into 8byte.
1299      * See X86-64 ABI 3.2.3
1300      */
1301     version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
1302     {
1303         arg1 = this;
1304         return 0;
1305     }
1306 
1307     /** Return info used by the garbage collector to do precise collection.
1308      */
1309     @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return rtinfoHasPointers; } // better safe than sorry
1310 }
1311 
1312 class TypeInfo_Enum : TypeInfo
1313 {
1314     override string toString() const { return name; }
1315 
1316     override bool opEquals(Object o)
1317     {
1318         if (this is o)
1319             return true;
1320         auto c = cast(const TypeInfo_Enum)o;
1321         return c && this.name == c.name &&
1322                     this.base == c.base;
1323     }
1324 
1325     override size_t getHash(scope const void* p) const { return base.getHash(p); }
1326     override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
1327     override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
1328     override @property size_t tsize() nothrow pure const { return base.tsize; }
1329     override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
1330 
1331     override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
1332     override @property uint flags() nothrow pure const { return base.flags; }
1333 
1334     override const(void)[] initializer() const
1335     {
1336         return m_init.length ? m_init : base.initializer();
1337     }
1338 
1339     override @property size_t talign() nothrow pure const { return base.talign; }
1340 
1341     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1342     {
1343         return base.argTypes(arg1, arg2);
1344     }
1345 
1346     override @property immutable(void)* rtInfo() const { return base.rtInfo; }
1347 
1348     TypeInfo base;
1349     string   name;
1350     void[]   m_init;
1351 }
1352 
1353 unittest // issue 12233
1354 {
1355     static assert(is(typeof(TypeInfo.init) == TypeInfo));
1356     assert(TypeInfo.init is null);
1357 }
1358 
1359 
1360 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
1361 class TypeInfo_Pointer : TypeInfo
1362 {
1363     override string toString() const { return m_next.toString() ~ "*"; }
1364 
1365     override bool opEquals(Object o)
1366     {
1367         if (this is o)
1368             return true;
1369         auto c = cast(const TypeInfo_Pointer)o;
1370         return c && this.m_next == c.m_next;
1371     }
1372 
1373     override size_t getHash(scope const void* p) @trusted const
1374     {
1375         size_t addr = cast(size_t) *cast(const void**)p;
1376         return addr ^ (addr >> 4);
1377     }
1378 
1379     override bool equals(in void* p1, in void* p2) const
1380     {
1381         return *cast(void**)p1 == *cast(void**)p2;
1382     }
1383 
1384     override int compare(in void* p1, in void* p2) const
1385     {
1386         if (*cast(void**)p1 < *cast(void**)p2)
1387             return -1;
1388         else if (*cast(void**)p1 > *cast(void**)p2)
1389             return 1;
1390         else
1391             return 0;
1392     }
1393 
1394     override @property size_t tsize() nothrow pure const
1395     {
1396         return (void*).sizeof;
1397     }
1398 
1399     override const(void)[] initializer() const @trusted
1400     {
1401         return (cast(void *)null)[0 .. (void*).sizeof];
1402     }
1403 
1404     override void swap(void* p1, void* p2) const
1405     {
1406         void* tmp = *cast(void**)p1;
1407         *cast(void**)p1 = *cast(void**)p2;
1408         *cast(void**)p2 = tmp;
1409     }
1410 
1411     override @property inout(TypeInfo) next() nothrow pure inout { return m_next; }
1412     override @property uint flags() nothrow pure const { return 1; }
1413 
1414     TypeInfo m_next;
1415 }
1416 
1417 class TypeInfo_Array : TypeInfo
1418 {
1419     override string toString() const { return value.toString() ~ "[]"; }
1420 
1421     override bool opEquals(Object o)
1422     {
1423         if (this is o)
1424             return true;
1425         auto c = cast(const TypeInfo_Array)o;
1426         return c && this.value == c.value;
1427     }
1428 
1429     override size_t getHash(scope const void* p) @trusted const
1430     {
1431         void[] a = *cast(void[]*)p;
1432         return getArrayHash(value, a.ptr, a.length);
1433     }
1434 
1435     override bool equals(in void* p1, in void* p2) const
1436     {
1437         void[] a1 = *cast(void[]*)p1;
1438         void[] a2 = *cast(void[]*)p2;
1439         if (a1.length != a2.length)
1440             return false;
1441         size_t sz = value.tsize;
1442         for (size_t i = 0; i < a1.length; i++)
1443         {
1444             if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
1445                 return false;
1446         }
1447         return true;
1448     }
1449 
1450     override int compare(in void* p1, in void* p2) const
1451     {
1452         void[] a1 = *cast(void[]*)p1;
1453         void[] a2 = *cast(void[]*)p2;
1454         size_t sz = value.tsize;
1455         size_t len = a1.length;
1456 
1457         if (a2.length < len)
1458             len = a2.length;
1459         for (size_t u = 0; u < len; u++)
1460         {
1461             immutable int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
1462             if (result)
1463                 return result;
1464         }
1465         return cast(int)a1.length - cast(int)a2.length;
1466     }
1467 
1468     override @property size_t tsize() nothrow pure const
1469     {
1470         return (void[]).sizeof;
1471     }
1472 
1473     override const(void)[] initializer() const @trusted
1474     {
1475         return (cast(void *)null)[0 .. (void[]).sizeof];
1476     }
1477 
1478     override void swap(void* p1, void* p2) const
1479     {
1480         void[] tmp = *cast(void[]*)p1;
1481         *cast(void[]*)p1 = *cast(void[]*)p2;
1482         *cast(void[]*)p2 = tmp;
1483     }
1484 
1485     TypeInfo value;
1486 
1487     override @property inout(TypeInfo) next() nothrow pure inout
1488     {
1489         return value;
1490     }
1491 
1492     override @property uint flags() nothrow pure const { return 1; }
1493 
1494     override @property size_t talign() nothrow pure const
1495     {
1496         return (void[]).alignof;
1497     }
1498 
1499     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1500     {
1501         arg1 = typeid(size_t);
1502         arg2 = typeid(void*);
1503         return 0;
1504     }
1505 
1506     override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(void[]); }
1507 }
1508 
1509 class TypeInfo_StaticArray : TypeInfo
1510 {
1511     override string toString() const
1512     {
1513         import core.internal..string : unsignedToTempString;
1514 
1515         char[20] tmpBuff = void;
1516         return value.toString() ~ "[" ~ unsignedToTempString(len, tmpBuff, 10) ~ "]";
1517     }
1518 
1519     override bool opEquals(Object o)
1520     {
1521         if (this is o)
1522             return true;
1523         auto c = cast(const TypeInfo_StaticArray)o;
1524         return c && this.len == c.len &&
1525                     this.value == c.value;
1526     }
1527 
1528     override size_t getHash(scope const void* p) @trusted const
1529     {
1530         return getArrayHash(value, p, len);
1531     }
1532 
1533     override bool equals(in void* p1, in void* p2) const
1534     {
1535         size_t sz = value.tsize;
1536 
1537         for (size_t u = 0; u < len; u++)
1538         {
1539             if (!value.equals(p1 + u * sz, p2 + u * sz))
1540                 return false;
1541         }
1542         return true;
1543     }
1544 
1545     override int compare(in void* p1, in void* p2) const
1546     {
1547         size_t sz = value.tsize;
1548 
1549         for (size_t u = 0; u < len; u++)
1550         {
1551             immutable int result = value.compare(p1 + u * sz, p2 + u * sz);
1552             if (result)
1553                 return result;
1554         }
1555         return 0;
1556     }
1557 
1558     override @property size_t tsize() nothrow pure const
1559     {
1560         return len * value.tsize;
1561     }
1562 
1563     override void swap(void* p1, void* p2) const
1564     {
1565         import core.memory;
1566         import core.stdc..string : memcpy;
1567 
1568         void* tmp;
1569         size_t sz = value.tsize;
1570         ubyte[16] buffer;
1571         void* pbuffer;
1572 
1573         if (sz < buffer.sizeof)
1574             tmp = buffer.ptr;
1575         else
1576             tmp = pbuffer = (new void[sz]).ptr;
1577 
1578         for (size_t u = 0; u < len; u += sz)
1579         {
1580             size_t o = u * sz;
1581             memcpy(tmp, p1 + o, sz);
1582             memcpy(p1 + o, p2 + o, sz);
1583             memcpy(p2 + o, tmp, sz);
1584         }
1585         if (pbuffer)
1586             GC.free(pbuffer);
1587     }
1588 
1589     override const(void)[] initializer() nothrow pure const
1590     {
1591         return value.initializer();
1592     }
1593 
1594     override @property inout(TypeInfo) next() nothrow pure inout { return value; }
1595     override @property uint flags() nothrow pure const { return value.flags; }
1596 
1597     override void destroy(void* p) const
1598     {
1599         immutable sz = value.tsize;
1600         p += sz * len;
1601         foreach (i; 0 .. len)
1602         {
1603             p -= sz;
1604             value.destroy(p);
1605         }
1606     }
1607 
1608     override void postblit(void* p) const
1609     {
1610         immutable sz = value.tsize;
1611         foreach (i; 0 .. len)
1612         {
1613             value.postblit(p);
1614             p += sz;
1615         }
1616     }
1617 
1618     TypeInfo value;
1619     size_t   len;
1620 
1621     override @property size_t talign() nothrow pure const
1622     {
1623         return value.talign;
1624     }
1625 
1626     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1627     {
1628         arg1 = typeid(void*);
1629         return 0;
1630     }
1631 
1632     // just return the rtInfo of the element, we have no generic type T to run RTInfo!T on
1633     override @property immutable(void)* rtInfo() nothrow pure const @safe { return value.rtInfo(); }
1634 }
1635 
1636 class TypeInfo_AssociativeArray : TypeInfo
1637 {
1638     override string toString() const
1639     {
1640         return value.toString() ~ "[" ~ key.toString() ~ "]";
1641     }
1642 
1643     override bool opEquals(Object o)
1644     {
1645         if (this is o)
1646             return true;
1647         auto c = cast(const TypeInfo_AssociativeArray)o;
1648         return c && this.key == c.key &&
1649                     this.value == c.value;
1650     }
1651 
1652     override bool equals(in void* p1, in void* p2) @trusted const
1653     {
1654         return !!_aaEqual(this, *cast(const void**) p1, *cast(const void**) p2);
1655     }
1656 
1657     override hash_t getHash(scope const void* p) nothrow @trusted const
1658     {
1659         return _aaGetHash(cast(void*)p, this);
1660     }
1661 
1662     // BUG: need to add the rest of the functions
1663 
1664     override @property size_t tsize() nothrow pure const
1665     {
1666         return (char[int]).sizeof;
1667     }
1668 
1669     override const(void)[] initializer() const @trusted
1670     {
1671         return (cast(void *)null)[0 .. (char[int]).sizeof];
1672     }
1673 
1674     override @property inout(TypeInfo) next() nothrow pure inout { return value; }
1675     override @property uint flags() nothrow pure const { return 1; }
1676 
1677     TypeInfo value;
1678     TypeInfo key;
1679 
1680     override @property size_t talign() nothrow pure const
1681     {
1682         return (char[int]).alignof;
1683     }
1684 
1685     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1686     {
1687         arg1 = typeid(void*);
1688         return 0;
1689     }
1690 }
1691 
1692 class TypeInfo_Vector : TypeInfo
1693 {
1694     override string toString() const { return "__vector(" ~ base.toString() ~ ")"; }
1695 
1696     override bool opEquals(Object o)
1697     {
1698         if (this is o)
1699             return true;
1700         auto c = cast(const TypeInfo_Vector)o;
1701         return c && this.base == c.base;
1702     }
1703 
1704     override size_t getHash(scope const void* p) const { return base.getHash(p); }
1705     override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
1706     override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
1707     override @property size_t tsize() nothrow pure const { return base.tsize; }
1708     override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
1709 
1710     override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
1711     override @property uint flags() nothrow pure const { return base.flags; }
1712 
1713     override const(void)[] initializer() nothrow pure const
1714     {
1715         return base.initializer();
1716     }
1717 
1718     override @property size_t talign() nothrow pure const { return 16; }
1719 
1720     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1721     {
1722         return base.argTypes(arg1, arg2);
1723     }
1724 
1725     TypeInfo base;
1726 }
1727 
1728 class TypeInfo_Function : TypeInfo
1729 {
1730     override string toString() const
1731     {
1732         import core.demangle : demangleType;
1733 
1734         alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
1735         SafeDemangleFunctionType demangle = ( () @trusted => cast(SafeDemangleFunctionType)(&demangleType) ) ();
1736 
1737         return (() @trusted => cast(string)(demangle(deco))) ();
1738     }
1739 
1740     override bool opEquals(Object o)
1741     {
1742         if (this is o)
1743             return true;
1744         auto c = cast(const TypeInfo_Function)o;
1745         return c && this.deco == c.deco;
1746     }
1747 
1748     // BUG: need to add the rest of the functions
1749 
1750     override @property size_t tsize() nothrow pure const
1751     {
1752         return 0;       // no size for functions
1753     }
1754 
1755     override const(void)[] initializer() const @safe
1756     {
1757         return null;
1758     }
1759 
1760     override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
1761 
1762     TypeInfo next;
1763 
1764     /**
1765     * Mangled function type string
1766     */
1767     string deco;
1768 }
1769 
1770 unittest
1771 {
1772     abstract class C
1773     {
1774        void func();
1775        void func(int a);
1776        int func(int a, int b);
1777     }
1778 
1779     alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func"));
1780     assert(typeid(functionTypes[0]).toString() == "void function()");
1781     assert(typeid(functionTypes[1]).toString() == "void function(int)");
1782     assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
1783 }
1784 
1785 class TypeInfo_Delegate : TypeInfo
1786 {
1787     override string toString() const
1788     {
1789         return cast(string)(next.toString() ~ " delegate()");
1790     }
1791 
1792     override bool opEquals(Object o)
1793     {
1794         if (this is o)
1795             return true;
1796         auto c = cast(const TypeInfo_Delegate)o;
1797         return c && this.deco == c.deco;
1798     }
1799 
1800     override size_t getHash(scope const void* p) @trusted const
1801     {
1802         return hashOf(*cast(void delegate()*)p);
1803     }
1804 
1805     override bool equals(in void* p1, in void* p2) const
1806     {
1807         auto dg1 = *cast(void delegate()*)p1;
1808         auto dg2 = *cast(void delegate()*)p2;
1809         return dg1 == dg2;
1810     }
1811 
1812     override int compare(in void* p1, in void* p2) const
1813     {
1814         auto dg1 = *cast(void delegate()*)p1;
1815         auto dg2 = *cast(void delegate()*)p2;
1816 
1817         if (dg1 < dg2)
1818             return -1;
1819         else if (dg1 > dg2)
1820             return 1;
1821         else
1822             return 0;
1823     }
1824 
1825     override @property size_t tsize() nothrow pure const
1826     {
1827         alias dg = int delegate();
1828         return dg.sizeof;
1829     }
1830 
1831     override const(void)[] initializer() const @trusted
1832     {
1833         return (cast(void *)null)[0 .. (int delegate()).sizeof];
1834     }
1835 
1836     override @property uint flags() nothrow pure const { return 1; }
1837 
1838     TypeInfo next;
1839     string deco;
1840 
1841     override @property size_t talign() nothrow pure const
1842     {
1843         alias dg = int delegate();
1844         return dg.alignof;
1845     }
1846 
1847     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1848     {
1849         arg1 = typeid(void*);
1850         arg2 = typeid(void*);
1851         return 0;
1852     }
1853 
1854     override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(int delegate()); }
1855 }
1856 
1857 /**
1858  * Runtime type information about a class.
1859  * Can be retrieved from an object instance by using the
1860  * $(DDSUBLINK spec/property,classinfo, .classinfo) property.
1861  */
1862 class TypeInfo_Class : TypeInfo
1863 {
1864     override string toString() const { return info.name; }
1865 
1866     override bool opEquals(Object o)
1867     {
1868         if (this is o)
1869             return true;
1870         auto c = cast(const TypeInfo_Class)o;
1871         return c && this.info.name == c.info.name;
1872     }
1873 
1874     override size_t getHash(scope const void* p) @trusted const
1875     {
1876         auto o = *cast(Object*)p;
1877         return o ? o.toHash() : 0;
1878     }
1879 
1880     override bool equals(in void* p1, in void* p2) const
1881     {
1882         Object o1 = *cast(Object*)p1;
1883         Object o2 = *cast(Object*)p2;
1884 
1885         return (o1 is o2) || (o1 && o1.opEquals(o2));
1886     }
1887 
1888     override int compare(in void* p1, in void* p2) const
1889     {
1890         Object o1 = *cast(Object*)p1;
1891         Object o2 = *cast(Object*)p2;
1892         int c = 0;
1893 
1894         // Regard null references as always being "less than"
1895         if (o1 !is o2)
1896         {
1897             if (o1)
1898             {
1899                 if (!o2)
1900                     c = 1;
1901                 else
1902                     c = o1.opCmp(o2);
1903             }
1904             else
1905                 c = -1;
1906         }
1907         return c;
1908     }
1909 
1910     override @property size_t tsize() nothrow pure const
1911     {
1912         return Object.sizeof;
1913     }
1914 
1915     override const(void)[] initializer() nothrow pure const @safe
1916     {
1917         return m_init;
1918     }
1919 
1920     override @property uint flags() nothrow pure const { return 1; }
1921 
1922     override @property const(OffsetTypeInfo)[] offTi() nothrow pure const
1923     {
1924         return m_offTi;
1925     }
1926 
1927     @property auto info() @safe nothrow pure const { return this; }
1928     @property auto typeinfo() @safe nothrow pure const { return this; }
1929 
1930     byte[]      m_init;         /** class static initializer
1931                                  * (init.length gives size in bytes of class)
1932                                  */
1933     string      name;           /// class name
1934     void*[]     vtbl;           /// virtual function pointer table
1935     Interface[] interfaces;     /// interfaces this class implements
1936     TypeInfo_Class   base;           /// base class
1937     void*       destructor;
1938     void function(Object) classInvariant;
1939     enum ClassFlags : uint
1940     {
1941         isCOMclass = 0x1,
1942         noPointers = 0x2,
1943         hasOffTi = 0x4,
1944         hasCtor = 0x8,
1945         hasGetMembers = 0x10,
1946         hasTypeInfo = 0x20,
1947         isAbstract = 0x40,
1948         isCPPclass = 0x80,
1949         hasDtor = 0x100,
1950     }
1951     ClassFlags m_flags;
1952     void*       deallocator;
1953     OffsetTypeInfo[] m_offTi;
1954     void function(Object) defaultConstructor;   // default Constructor
1955 
1956     immutable(void)* m_RTInfo;        // data for precise GC
1957     override @property immutable(void)* rtInfo() const { return m_RTInfo; }
1958 
1959     /**
1960      * Search all modules for TypeInfo_Class corresponding to classname.
1961      * Returns: null if not found
1962      */
1963     static const(TypeInfo_Class) find(in char[] classname)
1964     {
1965         foreach (m; ModuleInfo)
1966         {
1967             if (m)
1968             {
1969                 //writefln("module %s, %d", m.name, m.localClasses.length);
1970                 foreach (c; m.localClasses)
1971                 {
1972                     if (c is null)
1973                         continue;
1974                     //writefln("\tclass %s", c.name);
1975                     if (c.name == classname)
1976                         return c;
1977                 }
1978             }
1979         }
1980         return null;
1981     }
1982 
1983     /**
1984      * Create instance of Object represented by 'this'.
1985      */
1986     Object create() const
1987     {
1988         if (m_flags & 8 && !defaultConstructor)
1989             return null;
1990         if (m_flags & 64) // abstract
1991             return null;
1992         Object o = _d_newclass(this);
1993         if (m_flags & 8 && defaultConstructor)
1994         {
1995             defaultConstructor(o);
1996         }
1997         return o;
1998     }
1999 }
2000 
2001 alias ClassInfo = TypeInfo_Class;
2002 
2003 unittest
2004 {
2005     // Bugzilla 14401
2006     static class X
2007     {
2008         int a;
2009     }
2010 
2011     assert(typeid(X).initializer is typeid(X).m_init);
2012     assert(typeid(X).initializer.length == typeid(const(X)).initializer.length);
2013     assert(typeid(X).initializer.length == typeid(shared(X)).initializer.length);
2014     assert(typeid(X).initializer.length == typeid(immutable(X)).initializer.length);
2015 }
2016 
2017 class TypeInfo_Interface : TypeInfo
2018 {
2019     override string toString() const { return info.name; }
2020 
2021     override bool opEquals(Object o)
2022     {
2023         if (this is o)
2024             return true;
2025         auto c = cast(const TypeInfo_Interface)o;
2026         return c && this.info.name == typeid(c).name;
2027     }
2028 
2029     override size_t getHash(scope const void* p) @trusted const
2030     {
2031         if (!*cast(void**)p)
2032         {
2033             return 0;
2034         }
2035         Interface* pi = **cast(Interface ***)*cast(void**)p;
2036         Object o = cast(Object)(*cast(void**)p - pi.offset);
2037         assert(o);
2038         return o.toHash();
2039     }
2040 
2041     override bool equals(in void* p1, in void* p2) const
2042     {
2043         Interface* pi = **cast(Interface ***)*cast(void**)p1;
2044         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
2045         pi = **cast(Interface ***)*cast(void**)p2;
2046         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
2047 
2048         return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
2049     }
2050 
2051     override int compare(in void* p1, in void* p2) const
2052     {
2053         Interface* pi = **cast(Interface ***)*cast(void**)p1;
2054         Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
2055         pi = **cast(Interface ***)*cast(void**)p2;
2056         Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
2057         int c = 0;
2058 
2059         // Regard null references as always being "less than"
2060         if (o1 != o2)
2061         {
2062             if (o1)
2063             {
2064                 if (!o2)
2065                     c = 1;
2066                 else
2067                     c = o1.opCmp(o2);
2068             }
2069             else
2070                 c = -1;
2071         }
2072         return c;
2073     }
2074 
2075     override @property size_t tsize() nothrow pure const
2076     {
2077         return Object.sizeof;
2078     }
2079 
2080     override const(void)[] initializer() const @trusted
2081     {
2082         return (cast(void *)null)[0 .. Object.sizeof];
2083     }
2084 
2085     override @property uint flags() nothrow pure const { return 1; }
2086 
2087     TypeInfo_Class info;
2088 }
2089 
2090 class TypeInfo_Struct : TypeInfo
2091 {
2092     override string toString() const { return name; }
2093 
2094     override bool opEquals(Object o)
2095     {
2096         if (this is o)
2097             return true;
2098         auto s = cast(const TypeInfo_Struct)o;
2099         return s && this.name == s.name &&
2100                     this.initializer().length == s.initializer().length;
2101     }
2102 
2103     override size_t getHash(scope const void* p) @trusted pure nothrow const
2104     {
2105         assert(p);
2106         if (xtoHash)
2107         {
2108             return (*xtoHash)(p);
2109         }
2110         else
2111         {
2112             return hashOf(p[0 .. initializer().length]);
2113         }
2114     }
2115 
2116     override bool equals(in void* p1, in void* p2) @trusted pure nothrow const
2117     {
2118         import core.stdc..string : memcmp;
2119 
2120         if (!p1 || !p2)
2121             return false;
2122         else if (xopEquals)
2123             return (*xopEquals)(p1, p2);
2124         else if (p1 == p2)
2125             return true;
2126         else
2127             // BUG: relies on the GC not moving objects
2128             return memcmp(p1, p2, initializer().length) == 0;
2129     }
2130 
2131     override int compare(in void* p1, in void* p2) @trusted pure nothrow const
2132     {
2133         import core.stdc..string : memcmp;
2134 
2135         // Regard null references as always being "less than"
2136         if (p1 != p2)
2137         {
2138             if (p1)
2139             {
2140                 if (!p2)
2141                     return true;
2142                 else if (xopCmp)
2143                     return (*xopCmp)(p2, p1);
2144                 else
2145                     // BUG: relies on the GC not moving objects
2146                     return memcmp(p1, p2, initializer().length);
2147             }
2148             else
2149                 return -1;
2150         }
2151         return 0;
2152     }
2153 
2154     override @property size_t tsize() nothrow pure const
2155     {
2156         return initializer().length;
2157     }
2158 
2159     override const(void)[] initializer() nothrow pure const @safe
2160     {
2161         return m_init;
2162     }
2163 
2164     override @property uint flags() nothrow pure const { return m_flags; }
2165 
2166     override @property size_t talign() nothrow pure const { return m_align; }
2167 
2168     final override void destroy(void* p) const
2169     {
2170         if (xdtor)
2171         {
2172             if (m_flags & StructFlags.isDynamicType)
2173                 (*xdtorti)(p, this);
2174             else
2175                 (*xdtor)(p);
2176         }
2177     }
2178 
2179     override void postblit(void* p) const
2180     {
2181         if (xpostblit)
2182             (*xpostblit)(p);
2183     }
2184 
2185     string name;
2186     void[] m_init;      // initializer; m_init.ptr == null if 0 initialize
2187 
2188   @safe pure nothrow
2189   {
2190     size_t   function(in void*)           xtoHash;
2191     bool     function(in void*, in void*) xopEquals;
2192     int      function(in void*, in void*) xopCmp;
2193     string   function(in void*)           xtoString;
2194 
2195     enum StructFlags : uint
2196     {
2197         hasPointers = 0x1,
2198         isDynamicType = 0x2, // built at runtime, needs type info in xdtor
2199     }
2200     StructFlags m_flags;
2201   }
2202     union
2203     {
2204         void function(void*)                xdtor;
2205         void function(void*, const TypeInfo_Struct ti) xdtorti;
2206     }
2207     void function(void*)                    xpostblit;
2208 
2209     uint m_align;
2210 
2211     override @property immutable(void)* rtInfo() nothrow pure const @safe { return m_RTInfo; }
2212 
2213     version (X86_64)
2214     {
2215         override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2216         {
2217             arg1 = m_arg1;
2218             arg2 = m_arg2;
2219             return 0;
2220         }
2221         TypeInfo m_arg1;
2222         TypeInfo m_arg2;
2223     }
2224     immutable(void)* m_RTInfo;                // data for precise GC
2225 }
2226 
2227 unittest
2228 {
2229     struct S
2230     {
2231         bool opEquals(ref const S rhs) const
2232         {
2233             return false;
2234         }
2235     }
2236     S s;
2237     assert(!typeid(S).equals(&s, &s));
2238 }
2239 
2240 class TypeInfo_Tuple : TypeInfo
2241 {
2242     TypeInfo[] elements;
2243 
2244     override string toString() const
2245     {
2246         string s = "(";
2247         foreach (i, element; elements)
2248         {
2249             if (i)
2250                 s ~= ',';
2251             s ~= element.toString();
2252         }
2253         s ~= ")";
2254         return s;
2255     }
2256 
2257     override bool opEquals(Object o)
2258     {
2259         if (this is o)
2260             return true;
2261 
2262         auto t = cast(const TypeInfo_Tuple)o;
2263         if (t && elements.length == t.elements.length)
2264         {
2265             for (size_t i = 0; i < elements.length; i++)
2266             {
2267                 if (elements[i] != t.elements[i])
2268                     return false;
2269             }
2270             return true;
2271         }
2272         return false;
2273     }
2274 
2275     override size_t getHash(scope const void* p) const
2276     {
2277         assert(0);
2278     }
2279 
2280     override bool equals(in void* p1, in void* p2) const
2281     {
2282         assert(0);
2283     }
2284 
2285     override int compare(in void* p1, in void* p2) const
2286     {
2287         assert(0);
2288     }
2289 
2290     override @property size_t tsize() nothrow pure const
2291     {
2292         assert(0);
2293     }
2294 
2295     override const(void)[] initializer() const @trusted
2296     {
2297         assert(0);
2298     }
2299 
2300     override void swap(void* p1, void* p2) const
2301     {
2302         assert(0);
2303     }
2304 
2305     override void destroy(void* p) const
2306     {
2307         assert(0);
2308     }
2309 
2310     override void postblit(void* p) const
2311     {
2312         assert(0);
2313     }
2314 
2315     override @property size_t talign() nothrow pure const
2316     {
2317         assert(0);
2318     }
2319 
2320     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2321     {
2322         assert(0);
2323     }
2324 }
2325 
2326 class TypeInfo_Const : TypeInfo
2327 {
2328     override string toString() const
2329     {
2330         return cast(string) ("const(" ~ base.toString() ~ ")");
2331     }
2332 
2333     //override bool opEquals(Object o) { return base.opEquals(o); }
2334     override bool opEquals(Object o)
2335     {
2336         if (this is o)
2337             return true;
2338 
2339         if (typeid(this) != typeid(o))
2340             return false;
2341 
2342         auto t = cast(TypeInfo_Const)o;
2343         return base.opEquals(t.base);
2344     }
2345 
2346     override size_t getHash(scope const void *p) const { return base.getHash(p); }
2347     override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); }
2348     override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); }
2349     override @property size_t tsize() nothrow pure const { return base.tsize; }
2350     override void swap(void *p1, void *p2) const { return base.swap(p1, p2); }
2351 
2352     override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
2353     override @property uint flags() nothrow pure const { return base.flags; }
2354 
2355     override const(void)[] initializer() nothrow pure const
2356     {
2357         return base.initializer();
2358     }
2359 
2360     override @property size_t talign() nothrow pure const { return base.talign; }
2361 
2362     version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2363     {
2364         return base.argTypes(arg1, arg2);
2365     }
2366 
2367     TypeInfo base;
2368 }
2369 
2370 class TypeInfo_Invariant : TypeInfo_Const
2371 {
2372     override string toString() const
2373     {
2374         return cast(string) ("immutable(" ~ base.toString() ~ ")");
2375     }
2376 }
2377 
2378 class TypeInfo_Shared : TypeInfo_Const
2379 {
2380     override string toString() const
2381     {
2382         return cast(string) ("shared(" ~ base.toString() ~ ")");
2383     }
2384 }
2385 
2386 class TypeInfo_Inout : TypeInfo_Const
2387 {
2388     override string toString() const
2389     {
2390         return cast(string) ("inout(" ~ base.toString() ~ ")");
2391     }
2392 }
2393 
2394 // Contents of Moduleinfo._flags
2395 enum
2396 {
2397     MIctorstart  = 0x1,   // we've started constructing it
2398     MIctordone   = 0x2,   // finished construction
2399     MIstandalone = 0x4,   // module ctor does not depend on other module
2400                         // ctors being done first
2401     MItlsctor    = 8,
2402     MItlsdtor    = 0x10,
2403     MIctor       = 0x20,
2404     MIdtor       = 0x40,
2405     MIxgetMembers = 0x80,
2406     MIictor      = 0x100,
2407     MIunitTest   = 0x200,
2408     MIimportedModules = 0x400,
2409     MIlocalClasses = 0x800,
2410     MIname       = 0x1000,
2411 }
2412 
2413 /*****************************************
2414  * An instance of ModuleInfo is generated into the object file for each compiled module.
2415  *
2416  * It provides access to various aspects of the module.
2417  * It is not generated for betterC.
2418  */
2419 struct ModuleInfo
2420 {
2421     uint _flags; // MIxxxx
2422     uint _index; // index into _moduleinfo_array[]
2423 
2424     version (all)
2425     {
2426         deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
2427         void opAssign(in ModuleInfo m) { _flags = m._flags; _index = m._index; }
2428     }
2429     else
2430     {
2431         @disable this();
2432     }
2433 
2434 const:
2435     private void* addrOf(int flag) nothrow pure @nogc
2436     in
2437     {
2438         assert(flag >= MItlsctor && flag <= MIname);
2439         assert(!(flag & (flag - 1)) && !(flag & ~(flag - 1) << 1));
2440     }
2441     do
2442     {
2443         import core.stdc..string : strlen;
2444 
2445         void* p = cast(void*)&this + ModuleInfo.sizeof;
2446 
2447         if (flags & MItlsctor)
2448         {
2449             if (flag == MItlsctor) return p;
2450             p += typeof(tlsctor).sizeof;
2451         }
2452         if (flags & MItlsdtor)
2453         {
2454             if (flag == MItlsdtor) return p;
2455             p += typeof(tlsdtor).sizeof;
2456         }
2457         if (flags & MIctor)
2458         {
2459             if (flag == MIctor) return p;
2460             p += typeof(ctor).sizeof;
2461         }
2462         if (flags & MIdtor)
2463         {
2464             if (flag == MIdtor) return p;
2465             p += typeof(dtor).sizeof;
2466         }
2467         if (flags & MIxgetMembers)
2468         {
2469             if (flag == MIxgetMembers) return p;
2470             p += typeof(xgetMembers).sizeof;
2471         }
2472         if (flags & MIictor)
2473         {
2474             if (flag == MIictor) return p;
2475             p += typeof(ictor).sizeof;
2476         }
2477         if (flags & MIunitTest)
2478         {
2479             if (flag == MIunitTest) return p;
2480             p += typeof(unitTest).sizeof;
2481         }
2482         if (flags & MIimportedModules)
2483         {
2484             if (flag == MIimportedModules) return p;
2485             p += size_t.sizeof + *cast(size_t*)p * typeof(importedModules[0]).sizeof;
2486         }
2487         if (flags & MIlocalClasses)
2488         {
2489             if (flag == MIlocalClasses) return p;
2490             p += size_t.sizeof + *cast(size_t*)p * typeof(localClasses[0]).sizeof;
2491         }
2492         if (true || flags & MIname) // always available for now
2493         {
2494             if (flag == MIname) return p;
2495             p += strlen(cast(immutable char*)p);
2496         }
2497         assert(0);
2498     }
2499 
2500     @property uint index() nothrow pure @nogc { return _index; }
2501 
2502     @property uint flags() nothrow pure @nogc { return _flags; }
2503 
2504     /************************
2505      * Returns:
2506      *  module constructor for thread locals, `null` if there isn't one
2507      */
2508     @property void function() tlsctor() nothrow pure @nogc
2509     {
2510         return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null;
2511     }
2512 
2513     /************************
2514      * Returns:
2515      *  module destructor for thread locals, `null` if there isn't one
2516      */
2517     @property void function() tlsdtor() nothrow pure @nogc
2518     {
2519         return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null;
2520     }
2521 
2522     /*****************************
2523      * Returns:
2524      *  address of a module's `const(MemberInfo)[] getMembers(string)` function, `null` if there isn't one
2525      */
2526     @property void* xgetMembers() nothrow pure @nogc
2527     {
2528         return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null;
2529     }
2530 
2531     /************************
2532      * Returns:
2533      *  module constructor, `null` if there isn't one
2534      */
2535     @property void function() ctor() nothrow pure @nogc
2536     {
2537         return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null;
2538     }
2539 
2540     /************************
2541      * Returns:
2542      *  module destructor, `null` if there isn't one
2543      */
2544     @property void function() dtor() nothrow pure @nogc
2545     {
2546         return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null;
2547     }
2548 
2549     /************************
2550      * Returns:
2551      *  module order independent constructor, `null` if there isn't one
2552      */
2553     @property void function() ictor() nothrow pure @nogc
2554     {
2555         return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null;
2556     }
2557 
2558     /*************
2559      * Returns:
2560      *  address of function that runs the module's unittests, `null` if there isn't one
2561      */
2562     @property void function() unitTest() nothrow pure @nogc
2563     {
2564         return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null;
2565     }
2566 
2567     /****************
2568      * Returns:
2569      *  array of pointers to the ModuleInfo's of modules imported by this one
2570      */
2571     @property immutable(ModuleInfo*)[] importedModules() nothrow pure @nogc
2572     {
2573         if (flags & MIimportedModules)
2574         {
2575             auto p = cast(size_t*)addrOf(MIimportedModules);
2576             return (cast(immutable(ModuleInfo*)*)(p + 1))[0 .. *p];
2577         }
2578         return null;
2579     }
2580 
2581     /****************
2582      * Returns:
2583      *  array of TypeInfo_Class references for classes defined in this module
2584      */
2585     @property TypeInfo_Class[] localClasses() nothrow pure @nogc
2586     {
2587         if (flags & MIlocalClasses)
2588         {
2589             auto p = cast(size_t*)addrOf(MIlocalClasses);
2590             return (cast(TypeInfo_Class*)(p + 1))[0 .. *p];
2591         }
2592         return null;
2593     }
2594 
2595     /********************
2596      * Returns:
2597      *  name of module, `null` if no name
2598      */
2599     @property string name() nothrow pure @nogc
2600     {
2601         if (true || flags & MIname) // always available for now
2602         {
2603             import core.stdc..string : strlen;
2604 
2605             auto p = cast(immutable char*)addrOf(MIname);
2606             return p[0 .. strlen(p)];
2607         }
2608         // return null;
2609     }
2610 
2611     static int opApply(scope int delegate(ModuleInfo*) dg)
2612     {
2613         import core.internal.traits : externDFunc;
2614         alias moduleinfos_apply = externDFunc!("rt.minfo.moduleinfos_apply",
2615                                               int function(scope int delegate(immutable(ModuleInfo*))));
2616         // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
2617         return moduleinfos_apply(
2618             (immutable(ModuleInfo*)m) => dg(cast(ModuleInfo*)m));
2619     }
2620 }
2621 
2622 unittest
2623 {
2624     ModuleInfo* m1;
2625     foreach (m; ModuleInfo)
2626     {
2627         m1 = m;
2628     }
2629 }
2630 
2631 ///////////////////////////////////////////////////////////////////////////////
2632 // Throwable
2633 ///////////////////////////////////////////////////////////////////////////////
2634 
2635 
2636 /**
2637  * The base class of all thrown objects.
2638  *
2639  * All thrown objects must inherit from Throwable. Class $(D Exception), which
2640  * derives from this class, represents the category of thrown objects that are
2641  * safe to catch and handle. In principle, one should not catch Throwable
2642  * objects that are not derived from $(D Exception), as they represent
2643  * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
2644  * when these errors are thrown, making it unsafe to continue execution after
2645  * catching them.
2646  */
2647 class Throwable : Object
2648 {
2649     interface TraceInfo
2650     {
2651         int opApply(scope int delegate(ref const(char[]))) const;
2652         int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
2653         string toString() const;
2654     }
2655 
2656     string      msg;    /// A message describing the error.
2657 
2658     /**
2659      * The _file name of the D source code corresponding with
2660      * where the error was thrown from.
2661      */
2662     string      file;
2663     /**
2664      * The _line number of the D source code corresponding with
2665      * where the error was thrown from.
2666      */
2667     size_t      line;
2668 
2669     /**
2670      * The stack trace of where the error happened. This is an opaque object
2671      * that can either be converted to $(D string), or iterated over with $(D
2672      * foreach) to extract the items in the stack trace (as strings).
2673      */
2674     TraceInfo   info;
2675 
2676     /**
2677      * A reference to the _next error in the list. This is used when a new
2678      * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2679      * caught $(D Exception) will be chained to the new $(D Throwable) via this
2680      * field.
2681      */
2682     private Throwable   nextInChain;
2683 
2684     private uint _refcount;     // 0 : allocated by GC
2685                                 // 1 : allocated by _d_newThrowable()
2686                                 // 2.. : reference count + 1
2687 
2688     /**
2689      * Returns:
2690      * A reference to the _next error in the list. This is used when a new
2691      * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2692      * caught $(D Exception) will be chained to the new $(D Throwable) via this
2693      * field.
2694      */
2695     @property inout(Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; }
2696 
2697     /**
2698      * Replace next in chain with `tail`.
2699      * Use `chainTogether` instead if at all possible.
2700      */
2701     @property void next(Throwable tail) @safe scope pure nothrow @nogc
2702     {
2703         if (tail && tail._refcount)
2704             ++tail._refcount;           // increment the replacement *first*
2705 
2706         auto n = nextInChain;
2707         nextInChain = null;             // sever the tail before deleting it
2708 
2709         if (n && n._refcount)
2710             _d_delThrowable(n);         // now delete the old tail
2711 
2712         nextInChain = tail;             // and set the new tail
2713     }
2714 
2715     /**
2716      * Returns:
2717      *  mutable reference to the reference count, which is
2718      *  0 - allocated by the GC, 1 - allocated by _d_newThrowable(),
2719      *  and >=2 which is the reference count + 1
2720      */
2721     @system @nogc final pure nothrow ref uint refcount() return scope { return _refcount; }
2722 
2723     /**
2724      * Loop over the chain of Throwables.
2725      */
2726     int opApply(scope int delegate(Throwable) dg)
2727     {
2728         int result = 0;
2729         for (Throwable t = this; t; t = t.nextInChain)
2730         {
2731             result = dg(t);
2732             if (result)
2733                 break;
2734         }
2735         return result;
2736     }
2737 
2738     /**
2739      * Append `e2` to chain of exceptions that starts with `e1`.
2740      * Params:
2741      *  e1 = start of chain (can be null)
2742      *  e2 = second part of chain (can be null)
2743      * Returns:
2744      *  Throwable that is at the start of the chain; null if both `e1` and `e2` are null
2745      */
2746     static @__future @system @nogc pure nothrow Throwable chainTogether(return scope Throwable e1, return scope Throwable e2)
2747     {
2748         if (e2 && e2.refcount())
2749             ++e2.refcount();
2750         if (!e1)
2751             return e2;
2752         if (!e2)
2753             return e1;
2754         for (auto e = e1; 1; e = e.nextInChain)
2755         {
2756             if (!e.nextInChain)
2757             {
2758                 e.nextInChain = e2;
2759                 break;
2760             }
2761         }
2762         return e1;
2763     }
2764 
2765     @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2766     {
2767         this.msg = msg;
2768         this.nextInChain = nextInChain;
2769         //this.info = _d_traceContext();
2770     }
2771 
2772     @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2773     {
2774         this(msg, nextInChain);
2775         this.file = file;
2776         this.line = line;
2777         //this.info = _d_traceContext();
2778     }
2779 
2780     @trusted nothrow ~this()
2781     {
2782         if (nextInChain && nextInChain._refcount)
2783             _d_delThrowable(nextInChain);
2784     }
2785 
2786     /**
2787      * Overrides $(D Object.toString) and returns the error message.
2788      * Internally this forwards to the $(D toString) overload that
2789      * takes a $(D_PARAM sink) delegate.
2790      */
2791     override string toString()
2792     {
2793         string s;
2794         toString((buf) { s ~= buf; });
2795         return s;
2796     }
2797 
2798     /**
2799      * The Throwable hierarchy uses a toString overload that takes a
2800      * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
2801      * performed in certain error situations.  Override this $(D
2802      * toString) method to customize the error message.
2803      */
2804     void toString(scope void delegate(in char[]) sink) const
2805     {
2806         import core.internal..string : unsignedToTempString;
2807 
2808         char[20] tmpBuff = void;
2809 
2810         sink(typeid(this).name);
2811         sink("@"); sink(file);
2812         sink("("); sink(unsignedToTempString(line, tmpBuff, 10)); sink(")");
2813 
2814         if (msg.length)
2815         {
2816             sink(": "); sink(msg);
2817         }
2818         if (info)
2819         {
2820             try
2821             {
2822                 sink("\n----------------");
2823                 foreach (t; info)
2824                 {
2825                     sink("\n"); sink(t);
2826                 }
2827             }
2828             catch (Throwable)
2829             {
2830                 // ignore more errors
2831             }
2832         }
2833     }
2834 
2835     /**
2836      * Get the message describing the error.
2837      * Base behavior is to return the `Throwable.msg` field.
2838      * Override to return some other error message.
2839      *
2840      * Returns:
2841      *  Error message
2842      */
2843     @__future const(char)[] message() const
2844     {
2845         return this.msg;
2846     }
2847 }
2848 
2849 
2850 /**
2851  * The base class of all errors that are safe to catch and handle.
2852  *
2853  * In principle, only thrown objects derived from this class are safe to catch
2854  * inside a $(D catch) block. Thrown objects not derived from Exception
2855  * represent runtime errors that should not be caught, as certain runtime
2856  * guarantees may not hold, making it unsafe to continue program execution.
2857  */
2858 class Exception : Throwable
2859 {
2860 
2861     /**
2862      * Creates a new instance of Exception. The nextInChain parameter is used
2863      * internally and should always be $(D null) when passed by user code.
2864      * This constructor does not automatically throw the newly-created
2865      * Exception; the $(D throw) statement should be used for that purpose.
2866      */
2867     @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
2868     {
2869         super(msg, file, line, nextInChain);
2870     }
2871 
2872     @nogc @safe pure nothrow this(string msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__)
2873     {
2874         super(msg, file, line, nextInChain);
2875     }
2876 }
2877 
2878 ///
2879 @safe unittest
2880 {
2881     bool gotCaught;
2882     try
2883     {
2884         throw new Exception("msg");
2885     }
2886     catch (Exception e)
2887     {
2888         gotCaught = true;
2889         assert(e.msg == "msg");
2890     }
2891     assert(gotCaught);
2892 }
2893 
2894 unittest
2895 {
2896     {
2897         auto e = new Exception("msg");
2898         assert(e.file == __FILE__);
2899         assert(e.line == __LINE__ - 2);
2900         assert(e.nextInChain is null);
2901         assert(e.msg == "msg");
2902     }
2903 
2904     {
2905         auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
2906         assert(e.file == "hello");
2907         assert(e.line == 42);
2908         assert(e.nextInChain !is null);
2909         assert(e.msg == "msg");
2910     }
2911 
2912     {
2913         auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
2914         assert(e.file == "hello");
2915         assert(e.line == 42);
2916         assert(e.nextInChain !is null);
2917         assert(e.msg == "msg");
2918     }
2919 
2920     {
2921         auto e = new Exception("message");
2922         assert(e.message == "message");
2923     }
2924 }
2925 
2926 
2927 /**
2928  * The base class of all unrecoverable runtime errors.
2929  *
2930  * This represents the category of $(D Throwable) objects that are $(B not)
2931  * safe to catch and handle. In principle, one should not catch Error
2932  * objects, as they represent unrecoverable runtime errors.
2933  * Certain runtime guarantees may fail to hold when these errors are
2934  * thrown, making it unsafe to continue execution after catching them.
2935  */
2936 class Error : Throwable
2937 {
2938     /**
2939      * Creates a new instance of Error. The nextInChain parameter is used
2940      * internally and should always be $(D null) when passed by user code.
2941      * This constructor does not automatically throw the newly-created
2942      * Error; the $(D throw) statement should be used for that purpose.
2943      */
2944     @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2945     {
2946         super(msg, nextInChain);
2947         bypassedException = null;
2948     }
2949 
2950     @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2951     {
2952         super(msg, file, line, nextInChain);
2953         bypassedException = null;
2954     }
2955 
2956     /** The first $(D Exception) which was bypassed when this Error was thrown,
2957     or $(D null) if no $(D Exception)s were pending. */
2958     Throwable   bypassedException;
2959 }
2960 
2961 ///
2962 @system unittest
2963 {
2964     bool gotCaught;
2965     try
2966     {
2967         throw new Error("msg");
2968     }
2969     catch (Error e)
2970     {
2971         gotCaught = true;
2972         assert(e.msg == "msg");
2973     }
2974     assert(gotCaught);
2975 }
2976 
2977 unittest
2978 {
2979     {
2980         auto e = new Error("msg");
2981         assert(e.file is null);
2982         assert(e.line == 0);
2983         assert(e.nextInChain is null);
2984         assert(e.msg == "msg");
2985         assert(e.bypassedException is null);
2986     }
2987 
2988     {
2989         auto e = new Error("msg", new Exception("It's an Exception!"));
2990         assert(e.file is null);
2991         assert(e.line == 0);
2992         assert(e.nextInChain !is null);
2993         assert(e.msg == "msg");
2994         assert(e.bypassedException is null);
2995     }
2996 
2997     {
2998         auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
2999         assert(e.file == "hello");
3000         assert(e.line == 42);
3001         assert(e.nextInChain !is null);
3002         assert(e.msg == "msg");
3003         assert(e.bypassedException is null);
3004     }
3005 }
3006 
3007 /* Used in Exception Handling LSDA tables to 'wrap' C++ type info
3008  * so it can be distinguished from D TypeInfo
3009  */
3010 class __cpp_type_info_ptr
3011 {
3012     void* ptr;          // opaque pointer to C++ RTTI type info
3013 }
3014 
3015 extern (C)
3016 {
3017     // from druntime/src/rt/aaA.d
3018 
3019     // size_t _aaLen(in void* p) pure nothrow @nogc;
3020     private void* _aaGetY(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey) pure nothrow;
3021     private void* _aaGetX(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey, out bool found) pure nothrow;
3022     // inout(void)* _aaGetRvalueX(inout void* p, in TypeInfo keyti, in size_t valuesize, in void* pkey);
3023     inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow;
3024     inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow;
3025     void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow;
3026     void _aaClear(void* p) pure nothrow;
3027 
3028     // alias _dg_t = extern(D) int delegate(void*);
3029     // int _aaApply(void* aa, size_t keysize, _dg_t dg);
3030 
3031     // alias _dg2_t = extern(D) int delegate(void*, void*);
3032     // int _aaApply2(void* aa, size_t keysize, _dg2_t dg);
3033 
3034     private struct AARange { void* impl; size_t idx; }
3035     AARange _aaRange(void* aa) pure nothrow @nogc @safe;
3036     bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe;
3037     void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe;
3038     void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe;
3039     void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe;
3040 
3041     int _aaEqual(in TypeInfo tiRaw, in void* e1, in void* e2);
3042     hash_t _aaGetHash(in void* aa, in TypeInfo tiRaw) nothrow;
3043 
3044     /*
3045         _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
3046         This is a typesystem hole, however this is existing hole.
3047         Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
3048         copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
3049     */
3050     void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure;
3051 }
3052 
3053 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
3054 {
3055     return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
3056 }
3057 
3058 alias AssociativeArray(Key, Value) = Value[Key];
3059 
3060 /***********************************
3061  * Removes all remaining keys and values from an associative array.
3062  * Params:
3063  *      aa =     The associative array.
3064  */
3065 void clear(T : Value[Key], Value, Key)(T aa)
3066 {
3067     _aaClear(*cast(void **) &aa);
3068 }
3069 
3070 /* ditto */
3071 void clear(T : Value[Key], Value, Key)(T* aa)
3072 {
3073     _aaClear(*cast(void **) aa);
3074 }
3075 
3076 ///
3077 @system unittest
3078 {
3079     auto aa = ["k1": 2];
3080     aa.clear;
3081     assert("k1" !in aa);
3082 }
3083 
3084 /***********************************
3085  * Reorganizes the associative array in place so that lookups are more
3086  * efficient.
3087  * Params:
3088  *      aa =     The associative array.
3089  * Returns:
3090  *      The rehashed associative array.
3091  */
3092 T rehash(T : Value[Key], Value, Key)(T aa)
3093 {
3094     _aaRehash(cast(void**)&aa, typeid(Value[Key]));
3095     return aa;
3096 }
3097 
3098 /* ditto */
3099 T rehash(T : Value[Key], Value, Key)(T* aa)
3100 {
3101     _aaRehash(cast(void**)aa, typeid(Value[Key]));
3102     return *aa;
3103 }
3104 
3105 /* ditto */
3106 T rehash(T : shared Value[Key], Value, Key)(T aa)
3107 {
3108     _aaRehash(cast(void**)&aa, typeid(Value[Key]));
3109     return aa;
3110 }
3111 
3112 /* ditto */
3113 T rehash(T : shared Value[Key], Value, Key)(T* aa)
3114 {
3115     _aaRehash(cast(void**)aa, typeid(Value[Key]));
3116     return *aa;
3117 }
3118 
3119 /***********************************
3120  * Create a new associative array of the same size and copy the contents of the
3121  * associative array into it.
3122  * Params:
3123  *      aa =     The associative array.
3124  */
3125 V[K] dup(T : V[K], K, V)(T aa)
3126 {
3127     //pragma(msg, "K = ", K, ", V = ", V);
3128 
3129     // Bug10720 - check whether V is copyable
3130     static assert(is(typeof({ V v = aa[K.init]; })),
3131         "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");
3132 
3133     V[K] result;
3134 
3135     //foreach (k, ref v; aa)
3136     //    result[k] = v;  // Bug13701 - won't work if V is not mutable
3137 
3138     ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow
3139     {
3140         import core.stdc..string : memcpy;
3141 
3142         void* pv = _aaGetY(cast(void**)&result, typeid(V[K]), V.sizeof, &k);
3143         memcpy(pv, &v, V.sizeof);
3144         return *cast(V*)pv;
3145     }
3146 
3147     if (auto postblit = _getPostblit!V())
3148     {
3149         foreach (k, ref v; aa)
3150             postblit(duplicateElem(k, v));
3151     }
3152     else
3153     {
3154         foreach (k, ref v; aa)
3155             duplicateElem(k, v);
3156     }
3157 
3158     return result;
3159 }
3160 
3161 /* ditto */
3162 V[K] dup(T : V[K], K, V)(T* aa)
3163 {
3164     return (*aa).dup;
3165 }
3166 
3167 ///
3168 @safe unittest
3169 {
3170     auto aa = ["k1": 2];
3171     auto a2 = aa.dup;
3172     aa["k2"] = 3;
3173     assert("k2" !in a2);
3174 }
3175 
3176 // this should never be made public.
3177 private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe
3178 {
3179     // ensure we are dealing with a genuine AA.
3180     static if (is(const(V[K]) == const(T)))
3181         alias realAA = aa;
3182     else
3183         const(V[K]) realAA = aa;
3184     return _aaRange(() @trusted { return cast(void*)realAA; } ());
3185 }
3186 
3187 /***********************************
3188  * Returns a forward range over the keys of the associative array.
3189  * Params:
3190  *      aa =     The associative array.
3191  * Returns:
3192  *      A forward range.
3193  */
3194 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3195 {
3196     import core.internal.traits : substInout;
3197 
3198     static struct Result
3199     {
3200         AARange r;
3201 
3202     pure nothrow @nogc:
3203         @property bool empty()  @safe { return _aaRangeEmpty(r); }
3204         @property ref front()
3205         {
3206             auto p = (() @trusted => cast(substInout!K*) _aaRangeFrontKey(r)) ();
3207             return *p;
3208         }
3209         void popFront() @safe { _aaRangePopFront(r); }
3210         @property Result save() { return this; }
3211     }
3212 
3213     return Result(_aaToRange(aa));
3214 }
3215 
3216 /* ditto */
3217 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
3218 {
3219     return (*aa).byKey();
3220 }
3221 
3222 ///
3223 @safe unittest
3224 {
3225     auto dict = [1: 0, 2: 0];
3226     int sum;
3227     foreach (v; dict.byKey)
3228         sum += v;
3229 
3230     assert(sum == 3);
3231 }
3232 
3233 /***********************************
3234  * Returns a forward range over the values of the associative array.
3235  * Params:
3236  *      aa =     The associative array.
3237  * Returns:
3238  *      A forward range.
3239  */
3240 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3241 {
3242     import core.internal.traits : substInout;
3243 
3244     static struct Result
3245     {
3246         AARange r;
3247 
3248     pure nothrow @nogc:
3249         @property bool empty() @safe { return _aaRangeEmpty(r); }
3250         @property ref front()
3251         {
3252             auto p = (() @trusted => cast(substInout!V*) _aaRangeFrontValue(r)) ();
3253             return *p;
3254         }
3255         void popFront() @safe { _aaRangePopFront(r); }
3256         @property Result save() { return this; }
3257     }
3258 
3259     return Result(_aaToRange(aa));
3260 }
3261 
3262 /* ditto */
3263 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3264 {
3265     return (*aa).byValue();
3266 }
3267 
3268 ///
3269 @safe unittest
3270 {
3271     auto dict = ["k1": 1, "k2": 2];
3272     int sum;
3273     foreach (v; dict.byValue)
3274         sum += v;
3275 
3276     assert(sum == 3);
3277 }
3278 
3279 /***********************************
3280  * Returns a forward range over the key value pairs of the associative array.
3281  * Params:
3282  *      aa =     The associative array.
3283  * Returns:
3284  *      A forward range.
3285  */
3286 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3287 {
3288     import core.internal.traits : substInout;
3289 
3290     static struct Result
3291     {
3292         AARange r;
3293 
3294     pure nothrow @nogc:
3295         @property bool empty() @safe { return _aaRangeEmpty(r); }
3296         @property auto front()
3297         {
3298             static struct Pair
3299             {
3300                 // We save the pointers here so that the Pair we return
3301                 // won't mutate when Result.popFront is called afterwards.
3302                 private void* keyp;
3303                 private void* valp;
3304 
3305                 @property ref key() inout
3306                 {
3307                     auto p = (() @trusted => cast(substInout!K*) keyp) ();
3308                     return *p;
3309                 }
3310                 @property ref value() inout
3311                 {
3312                     auto p = (() @trusted => cast(substInout!V*) valp) ();
3313                     return *p;
3314                 }
3315             }
3316             return Pair(_aaRangeFrontKey(r),
3317                         _aaRangeFrontValue(r));
3318         }
3319         void popFront() @safe { return _aaRangePopFront(r); }
3320         @property Result save() { return this; }
3321     }
3322 
3323     return Result(_aaToRange(aa));
3324 }
3325 
3326 /* ditto */
3327 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3328 {
3329     return (*aa).byKeyValue();
3330 }
3331 
3332 ///
3333 @safe unittest
3334 {
3335     auto dict = ["k1": 1, "k2": 2];
3336     int sum;
3337     foreach (e; dict.byKeyValue)
3338         sum += e.value;
3339 
3340     assert(sum == 3);
3341 }
3342 
3343 /***********************************
3344  * Returns a dynamic array, the elements of which are the keys in the
3345  * associative array.
3346  * Params:
3347  *      aa =     The associative array.
3348  * Returns:
3349  *      A dynamic array.
3350  */
3351 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
3352 {
3353     auto a = cast(void[])_aaKeys(cast(inout(void)*)aa, Key.sizeof, typeid(Key[]));
3354     auto res = *cast(Key[]*)&a;
3355     _doPostblit(res);
3356     return res;
3357 }
3358 
3359 /* ditto */
3360 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
3361 {
3362     return (*aa).keys;
3363 }
3364 
3365 ///
3366 @system unittest
3367 {
3368     auto aa = [1: "v1", 2: "v2"];
3369     int sum;
3370     foreach (k; aa.keys)
3371         sum += k;
3372 
3373     assert(sum == 3);
3374 }
3375 
3376 /***********************************
3377  * Returns a dynamic array, the elements of which are the values in the
3378  * associative array.
3379  * Params:
3380  *      aa =     The associative array.
3381  * Returns:
3382  *      A dynamic array.
3383  */
3384 Value[] values(T : Value[Key], Value, Key)(T aa) @property
3385 {
3386     auto a = cast(void[])_aaValues(cast(inout(void)*)aa, Key.sizeof, Value.sizeof, typeid(Value[]));
3387     auto res = *cast(Value[]*)&a;
3388     _doPostblit(res);
3389     return res;
3390 }
3391 
3392 /* ditto */
3393 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
3394 {
3395     return (*aa).values;
3396 }
3397 
3398 ///
3399 @system unittest
3400 {
3401     auto aa = ["k1": 1, "k2": 2];
3402     int sum;
3403     foreach (e; aa.values)
3404         sum += e;
3405 
3406     assert(sum == 3);
3407 }
3408 
3409 /***********************************
3410  * Looks up key; if it exists returns corresponding value else evaluates and
3411  * returns defaultValue.
3412  * Params:
3413  *      aa =     The associative array.
3414  *      key =    The key.
3415  *      defaultValue = The default value.
3416  * Returns:
3417  *      The value.
3418  */
3419 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)
3420 {
3421     auto p = key in aa;
3422     return p ? *p : defaultValue;
3423 }
3424 
3425 /* ditto */
3426 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
3427 {
3428     return (*aa).get(key, defaultValue);
3429 }
3430 
3431 @safe unittest
3432 {
3433     auto aa = ["k1": 1];
3434     assert(aa.get("k1", 0) == 1);
3435     assert(aa.get("k2", 0) == 0);
3436 }
3437 
3438 /***********************************
3439  * Looks up key; if it exists returns corresponding value else evaluates
3440  * value, adds it to the associative array and returns it.
3441  * Params:
3442  *      aa =     The associative array.
3443  *      key =    The key.
3444  *      value =  The required value.
3445  * Returns:
3446  *      The value.
3447  */
3448 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
3449 {
3450     bool found;
3451     // if key is @safe-ly copyable, `require` can infer @safe
3452     static if (isSafeCopyable!K)
3453     {
3454         auto p = () @trusted
3455         {
3456             return cast(V*) _aaGetX(cast(void**) &aa, typeid(V[K]), V.sizeof, &key, found);
3457         } ();
3458     }
3459     else
3460     {
3461         auto p = cast(V*) _aaGetX(cast(void**) &aa, typeid(V[K]), V.sizeof, &key, found);
3462     }
3463     return found ? *p : (*p = value);
3464 }
3465 
3466 ///
3467 @safe unittest
3468 {
3469     auto aa = ["k1": 1];
3470     assert(aa.require("k1", 0) == 1);
3471     assert(aa.require("k2", 0) == 0);
3472     assert(aa["k2"] == 0);
3473 }
3474 
3475 // Constraints for aa update. Delegates, Functions or Functors (classes that
3476 // provide opCall) are allowed. See unittest for an example.
3477 private
3478 {
3479     template isCreateOperation(C, V)
3480     {
3481         static if (is(C : V delegate()) || is(C : V function()))
3482             enum bool isCreateOperation = true;
3483         else static if (isCreateOperation!(typeof(&C.opCall), V))
3484             enum bool isCreateOperation = true;
3485         else
3486             enum bool isCreateOperation = false;
3487     }
3488 
3489     template isUpdateOperation(U, V)
3490     {
3491         static if (is(U : V delegate(ref V)) || is(U : V function(ref V)))
3492             enum bool isUpdateOperation = true;
3493         else static if (isUpdateOperation!(typeof(&U.opCall), V))
3494             enum bool isUpdateOperation = true;
3495         else
3496             enum bool isUpdateOperation = false;
3497     }
3498 }
3499 
3500 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test.
3501 private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); }));
3502 
3503 /***********************************
3504  * Looks up key; if it exists applies the update delegate else evaluates the
3505  * create delegate and adds it to the associative array
3506  * Params:
3507  *      aa =     The associative array.
3508  *      key =    The key.
3509  *      create = The delegate to apply on create.
3510  *      update = The delegate to apply on update.
3511  */
3512 void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
3513 if (isCreateOperation!(C, V) && isUpdateOperation!(U, V))
3514 {
3515     bool found;
3516     // if key is @safe-ly copyable, `update` may infer @safe
3517     static if (isSafeCopyable!K)
3518     {
3519         auto p = () @trusted
3520         {
3521             return cast(V*) _aaGetX(cast(void**) &aa, typeid(V[K]), V.sizeof, &key, found);
3522         } ();
3523     }
3524     else
3525     {
3526         auto p = cast(V*) _aaGetX(cast(void**) &aa, typeid(V[K]), V.sizeof, &key, found);
3527     }
3528     if (!found)
3529         *p = create();
3530     else
3531         *p = update(*p);
3532 }
3533 
3534 ///
3535 @system unittest
3536 {
3537     auto aa = ["k1": 1];
3538 
3539     aa.update("k1", {
3540         return -1; // create (won't be executed
3541     }, (ref int v) {
3542         return v + 1; // update
3543     });
3544     assert(aa["k1"] == 2);
3545 
3546     aa.update("k2", {
3547         return 0; // create
3548     }, (ref int v) {
3549         return -1; // update (won't be executed)
3550     });
3551     assert(aa["k2"] == 0);
3552 }
3553 
3554 unittest
3555 {
3556     static struct S
3557     {
3558         int x;
3559     @nogc nothrow pure:
3560         this(this) @system {}
3561 
3562     @safe const:
3563         // stubs
3564         bool opEquals(S rhs) { assert(0); }
3565         size_t toHash() { assert(0); }
3566     }
3567 
3568     int[string] aai;
3569     static assert(is(typeof(() @safe { aai.require("a", 1234); })));
3570     static assert(is(typeof(() @safe { aai.update("a", { return 1234; }, (ref int x) { x++; return x; }); })));
3571 
3572     S[string] aas;
3573     static assert(is(typeof(() { aas.require("a", S(1234)); })));
3574     static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3575     static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3576 
3577     int[S] aais;
3578     static assert(is(typeof(() { aais.require(S(1234), 1234); })));
3579     static assert(is(typeof(() { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3580     static assert(!is(typeof(() @safe { aais.require(S(1234), 1234); })));
3581     static assert(!is(typeof(() @safe { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3582 }
3583 
3584 private void _destructRecurse(E, size_t n)(ref E[n] arr)
3585 {
3586     import core.internal.traits : hasElaborateDestructor;
3587 
3588     static if (hasElaborateDestructor!E)
3589     {
3590         foreach_reverse (ref elem; arr)
3591             _destructRecurse(elem);
3592     }
3593 }
3594 
3595 // Public and explicitly undocumented
3596 void _postblitRecurse(S)(ref S s)
3597     if (is(S == struct))
3598 {
3599     static if (__traits(hasMember, S, "__xpostblit") &&
3600                // Bugzilla 14746: Check that it's the exact member of S.
3601                __traits(isSame, S, __traits(parent, s.__xpostblit)))
3602         s.__xpostblit();
3603 }
3604 
3605 // Ditto
3606 void _postblitRecurse(E, size_t n)(ref E[n] arr)
3607 {
3608     import core.internal.traits : hasElaborateCopyConstructor;
3609 
3610     static if (hasElaborateCopyConstructor!E)
3611     {
3612         size_t i;
3613         scope(failure)
3614         {
3615             for (; i != 0; --i)
3616             {
3617                 _destructRecurse(arr[i - 1]); // What to do if this throws?
3618             }
3619         }
3620 
3621         for (i = 0; i < arr.length; ++i)
3622             _postblitRecurse(arr[i]);
3623     }
3624 }
3625 
3626 // Test destruction/postblit order
3627 @safe nothrow pure unittest
3628 {
3629     string[] order;
3630 
3631     struct InnerTop
3632     {
3633         ~this() @safe nothrow pure
3634         {
3635             order ~= "destroy inner top";
3636         }
3637 
3638         this(this) @safe nothrow pure
3639         {
3640             order ~= "copy inner top";
3641         }
3642     }
3643 
3644     struct InnerMiddle {}
3645 
3646     version (none) // https://issues.dlang.org/show_bug.cgi?id=14242
3647     struct InnerElement
3648     {
3649         static char counter = '1';
3650 
3651         ~this() @safe nothrow pure
3652         {
3653             order ~= "destroy inner element #" ~ counter++;
3654         }
3655 
3656         this(this) @safe nothrow pure
3657         {
3658             order ~= "copy inner element #" ~ counter++;
3659         }
3660     }
3661 
3662     struct InnerBottom
3663     {
3664         ~this() @safe nothrow pure
3665         {
3666             order ~= "destroy inner bottom";
3667         }
3668 
3669         this(this) @safe nothrow pure
3670         {
3671             order ~= "copy inner bottom";
3672         }
3673     }
3674 
3675     struct S
3676     {
3677         char[] s;
3678         InnerTop top;
3679         InnerMiddle middle;
3680         version (none) InnerElement[3] array; // https://issues.dlang.org/show_bug.cgi?id=14242
3681         int a;
3682         InnerBottom bottom;
3683         ~this() @safe nothrow pure { order ~= "destroy outer"; }
3684         this(this) @safe nothrow pure { order ~= "copy outer"; }
3685     }
3686 
3687     string[] destructRecurseOrder;
3688     {
3689         S s;
3690         _destructRecurse(s);
3691         destructRecurseOrder = order;
3692         order = null;
3693     }
3694 
3695     assert(order.length);
3696     assert(destructRecurseOrder == order);
3697     order = null;
3698 
3699     S s;
3700     _postblitRecurse(s);
3701     assert(order.length);
3702     auto postblitRecurseOrder = order;
3703     order = null;
3704     S s2 = s;
3705     assert(order.length);
3706     assert(postblitRecurseOrder == order);
3707 }
3708 
3709 // Test static struct
3710 nothrow @safe @nogc unittest
3711 {
3712     static int i = 0;
3713     static struct S { ~this() nothrow @safe @nogc { i = 42; } }
3714     S s;
3715     _destructRecurse(s);
3716     assert(i == 42);
3717 }
3718 
3719 unittest
3720 {
3721     // Bugzilla 14746
3722     static struct HasDtor
3723     {
3724         ~this() { assert(0); }
3725     }
3726     static struct Owner
3727     {
3728         HasDtor* ptr;
3729         alias ptr this;
3730     }
3731 
3732     Owner o;
3733     assert(o.ptr is null);
3734     destroy(o);     // must not reach in HasDtor.__dtor()
3735 }
3736 
3737 unittest
3738 {
3739     // Bugzilla 14746
3740     static struct HasPostblit
3741     {
3742         this(this) { assert(0); }
3743     }
3744     static struct Owner
3745     {
3746         HasPostblit* ptr;
3747         alias ptr this;
3748     }
3749 
3750     Owner o;
3751     assert(o.ptr is null);
3752     _postblitRecurse(o);     // must not reach in HasPostblit.__postblit()
3753 }
3754 
3755 // Test handling of fixed-length arrays
3756 // Separate from first test because of https://issues.dlang.org/show_bug.cgi?id=14242
3757 unittest
3758 {
3759     string[] order;
3760 
3761     struct S
3762     {
3763         char id;
3764 
3765         this(this)
3766         {
3767             order ~= "copy #" ~ id;
3768         }
3769 
3770         ~this()
3771         {
3772             order ~= "destroy #" ~ id;
3773         }
3774     }
3775 
3776     string[] destructRecurseOrder;
3777     {
3778         S[3] arr = [S('1'), S('2'), S('3')];
3779         _destructRecurse(arr);
3780         destructRecurseOrder = order;
3781         order = null;
3782     }
3783     assert(order.length);
3784     assert(destructRecurseOrder == order);
3785     order = null;
3786 
3787     S[3] arr = [S('1'), S('2'), S('3')];
3788     _postblitRecurse(arr);
3789     assert(order.length);
3790     auto postblitRecurseOrder = order;
3791     order = null;
3792 
3793     auto arrCopy = arr;
3794     assert(order.length);
3795     assert(postblitRecurseOrder == order);
3796 }
3797 
3798 // Test handling of failed postblit
3799 // Not nothrow or @safe because of https://issues.dlang.org/show_bug.cgi?id=14242
3800 /+ nothrow @safe +/ unittest
3801 {
3802     static class FailedPostblitException : Exception { this() nothrow @safe { super(null); } }
3803     static string[] order;
3804     static struct Inner
3805     {
3806         char id;
3807 
3808         @safe:
3809         this(this)
3810         {
3811             order ~= "copy inner #" ~ id;
3812             if (id == '2')
3813                 throw new FailedPostblitException();
3814         }
3815 
3816         ~this() nothrow
3817         {
3818             order ~= "destroy inner #" ~ id;
3819         }
3820     }
3821 
3822     static struct Outer
3823     {
3824         Inner inner1, inner2, inner3;
3825 
3826         nothrow @safe:
3827         this(char first, char second, char third)
3828         {
3829             inner1 = Inner(first);
3830             inner2 = Inner(second);
3831             inner3 = Inner(third);
3832         }
3833 
3834         this(this)
3835         {
3836             order ~= "copy outer";
3837         }
3838 
3839         ~this()
3840         {
3841             order ~= "destroy outer";
3842         }
3843     }
3844 
3845     auto outer = Outer('1', '2', '3');
3846 
3847     try _postblitRecurse(outer);
3848     catch (FailedPostblitException) {}
3849     catch (Exception) assert(false);
3850 
3851     auto postblitRecurseOrder = order;
3852     order = null;
3853 
3854     try auto copy = outer;
3855     catch (FailedPostblitException) {}
3856     catch (Exception) assert(false);
3857 
3858     assert(postblitRecurseOrder == order);
3859     order = null;
3860 
3861     Outer[3] arr = [Outer('1', '1', '1'), Outer('1', '2', '3'), Outer('3', '3', '3')];
3862 
3863     try _postblitRecurse(arr);
3864     catch (FailedPostblitException) {}
3865     catch (Exception) assert(false);
3866 
3867     postblitRecurseOrder = order;
3868     order = null;
3869 
3870     try auto arrCopy = arr;
3871     catch (FailedPostblitException) {}
3872     catch (Exception) assert(false);
3873 
3874     assert(postblitRecurseOrder == order);
3875 }
3876 
3877 private
3878 {
3879     extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow;
3880     extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
3881 }
3882 
3883 /**
3884  * (Property) Gets the current _capacity of a slice. The _capacity is the size
3885  * that the slice can grow to before the underlying array must be
3886  * reallocated or extended.
3887  *
3888  * If an append must reallocate a slice with no possibility of extension, then
3889  * `0` is returned. This happens when the slice references a static array, or
3890  * if another slice references elements past the end of the current slice.
3891  *
3892  * Note: The _capacity of a slice may be impacted by operations on other slices.
3893  */
3894 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
3895 {
3896     return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr);
3897 }
3898 
3899 ///
3900 @safe unittest
3901 {
3902     //Static array slice: no capacity
3903     int[4] sarray = [1, 2, 3, 4];
3904     int[]  slice  = sarray[];
3905     assert(sarray.capacity == 0);
3906     //Appending to slice will reallocate to a new array
3907     slice ~= 5;
3908     assert(slice.capacity >= 5);
3909 
3910     //Dynamic array slices
3911     int[] a = [1, 2, 3, 4];
3912     int[] b = a[1 .. $];
3913     int[] c = a[1 .. $ - 1];
3914     debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation
3915     {
3916         assert(a.capacity != 0);
3917         assert(a.capacity == b.capacity + 1); //both a and b share the same tail
3918     }
3919     assert(c.capacity == 0);              //an append to c must relocate c.
3920 }
3921 
3922 /**
3923  * Reserves capacity for a slice. The capacity is the size
3924  * that the slice can grow to before the underlying array must be
3925  * reallocated or extended.
3926  *
3927  * Returns: The new capacity of the array (which may be larger than
3928  * the requested capacity).
3929  */
3930 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
3931 {
3932     return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr);
3933 }
3934 
3935 ///
3936 unittest
3937 {
3938     //Static array slice: no capacity. Reserve relocates.
3939     int[4] sarray = [1, 2, 3, 4];
3940     int[]  slice  = sarray[];
3941     auto u = slice.reserve(8);
3942     assert(u >= 8);
3943     assert(sarray.ptr !is slice.ptr);
3944     assert(slice.capacity == u);
3945 
3946     //Dynamic array slices
3947     int[] a = [1, 2, 3, 4];
3948     a.reserve(8); //prepare a for appending 4 more items
3949     auto p = a.ptr;
3950     u = a.capacity;
3951     a ~= [5, 6, 7, 8];
3952     assert(p == a.ptr);      //a should not have been reallocated
3953     assert(u == a.capacity); //a should not have been extended
3954 }
3955 
3956 // Issue 6646: should be possible to use array.reserve from SafeD.
3957 @safe unittest
3958 {
3959     int[] a;
3960     a.reserve(10);
3961 }
3962 
3963 /**
3964  * Assume that it is safe to append to this array. Appends made to this array
3965  * after calling this function may append in place, even if the array was a
3966  * slice of a larger array to begin with.
3967  *
3968  * Use this only when it is certain there are no elements in use beyond the
3969  * array in the memory block.  If there are, those elements will be
3970  * overwritten by appending to this array.
3971  *
3972  * Warning: Calling this function, and then using references to data located after the
3973  * given array results in undefined behavior.
3974  *
3975  * Returns:
3976  *   The input is returned.
3977  */
3978 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
3979 {
3980     _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
3981     return arr;
3982 }
3983 
3984 ///
3985 unittest
3986 {
3987     int[] a = [1, 2, 3, 4];
3988 
3989     // Without assumeSafeAppend. Appending relocates.
3990     int[] b = a [0 .. 3];
3991     b ~= 5;
3992     assert(a.ptr != b.ptr);
3993 
3994     debug(SENTINEL) {} else
3995     {
3996         // With assumeSafeAppend. Appending overwrites.
3997         int[] c = a [0 .. 3];
3998         c.assumeSafeAppend() ~= 5;
3999         assert(a.ptr == c.ptr);
4000     }
4001 }
4002 
4003 unittest
4004 {
4005     int[] arr;
4006     auto newcap = arr.reserve(2000);
4007     assert(newcap >= 2000);
4008     assert(newcap == arr.capacity);
4009     auto ptr = arr.ptr;
4010     foreach (i; 0..2000)
4011         arr ~= i;
4012     assert(ptr == arr.ptr);
4013     arr = arr[0..1];
4014     arr.assumeSafeAppend();
4015     arr ~= 5;
4016     assert(ptr == arr.ptr);
4017 }
4018 
4019 unittest
4020 {
4021     int[] arr = [1, 2, 3];
4022     void foo(ref int[] i)
4023     {
4024         i ~= 5;
4025     }
4026     arr = arr[0 .. 2];
4027     foo(assumeSafeAppend(arr)); //pass by ref
4028     assert(arr[]==[1, 2, 5]);
4029     arr = arr[0 .. 1].assumeSafeAppend(); //pass by value
4030 }
4031 
4032 // https://issues.dlang.org/show_bug.cgi?id=10574
4033 unittest
4034 {
4035     int[] a;
4036     immutable(int[]) b;
4037     auto a2 = &assumeSafeAppend(a);
4038     auto b2 = &assumeSafeAppend(b);
4039     auto a3 = assumeSafeAppend(a[]);
4040     auto b3 = assumeSafeAppend(b[]);
4041     assert(is(typeof(*a2) == int[]));
4042     assert(is(typeof(*b2) == immutable(int[])));
4043     assert(is(typeof(a3) == int[]));
4044     assert(is(typeof(b3) == immutable(int[])));
4045 }
4046 
4047 version (none)
4048 {
4049     // enforce() copied from Phobos std.contracts for destroy(), left out until
4050     // we decide whether to use it.
4051 
4052 
4053     T _enforce(T, string file = __FILE__, int line = __LINE__)
4054         (T value, lazy const(char)[] msg = null)
4055     {
4056         if (!value) bailOut(file, line, msg);
4057         return value;
4058     }
4059 
4060     T _enforce(T, string file = __FILE__, int line = __LINE__)
4061         (T value, scope void delegate() dg)
4062     {
4063         if (!value) dg();
4064         return value;
4065     }
4066 
4067     T _enforce(T)(T value, lazy Exception ex)
4068     {
4069         if (!value) throw ex();
4070         return value;
4071     }
4072 
4073     private void _bailOut(string file, int line, in char[] msg)
4074     {
4075         char[21] buf = void;
4076         throw new Exception(cast(string)(file ~ "(" ~ ulongToString(buf[], line) ~ "): " ~ (msg ? msg : "Enforcement failed")));
4077     }
4078 }
4079 
4080 version (D_Ddoc)
4081 {
4082     // This lets DDoc produce better documentation.
4083 
4084     /**
4085     Calculates the hash value of `arg` with an optional `seed` initial value.
4086     The result might not be equal to `typeid(T).getHash(&arg)`.
4087 
4088     Params:
4089         arg = argument to calculate the hash value of
4090         seed = optional `seed` value (may be used for hash chaining)
4091 
4092     Return: calculated hash value of `arg`
4093     */
4094     size_t hashOf(T)(auto ref T arg, size_t seed)
4095     {
4096         static import core.internal.hash;
4097         return core.internal.hash.hashOf(arg, seed);
4098     }
4099     /// ditto
4100     size_t hashOf(T)(auto ref T arg)
4101     {
4102         static import core.internal.hash;
4103         return core.internal.hash.hashOf(arg);
4104     }
4105 
4106     @safe unittest
4107     {
4108         auto h1 = "my.string".hashOf;
4109         assert(h1 == "my.string".hashOf);
4110     }
4111 }
4112 else
4113 {
4114     public import core.internal.hash : hashOf;
4115 }
4116 
4117 ///
4118 @system unittest
4119 {
4120     class MyObject
4121     {
4122         size_t myMegaHash() const @safe pure nothrow
4123         {
4124             return 42;
4125         }
4126     }
4127     struct Test
4128     {
4129         int a;
4130         string b;
4131         MyObject c;
4132         size_t toHash() const pure nothrow
4133         {
4134             size_t hash = a.hashOf();
4135             hash = b.hashOf(hash);
4136             size_t h1 = c.myMegaHash();
4137             hash = h1.hashOf(hash); //Mix two hash values
4138             return hash;
4139         }
4140     }
4141 }
4142 
4143 bool _xopEquals(in void*, in void*)
4144 {
4145     throw new Error("TypeInfo.equals is not implemented");
4146 }
4147 
4148 bool _xopCmp(in void*, in void*)
4149 {
4150     throw new Error("TypeInfo.compare is not implemented");
4151 }
4152 
4153 void __ctfeWrite(scope const(char)[] s) @nogc @safe pure nothrow {}
4154 
4155 /******************************************
4156  * Create RTInfo for type T
4157  */
4158 
4159 template RTInfoImpl(size_t[] pointers)
4160 {
4161     immutable size_t[pointers.length] data = pointers[];
4162     immutable RTInfoImpl = data.ptr;
4163 }
4164 
4165 template RTInfo(T)
4166 {
4167     enum RTInfo = RTInfoImpl!(__traits(getPointerBitmap, T));
4168 }
4169 
4170 /**
4171 * shortcuts for the precise GC, also generated by the compiler
4172 * used instead of the actual pointer bitmap
4173 */
4174 enum immutable(void)* rtinfoNoPointers  = null;
4175 enum immutable(void)* rtinfoHasPointers = cast(void*)1;
4176 
4177 // Compiler hook into the runtime implementation of array (vector) operations.
4178 template _arrayOp(Args...)
4179 {
4180     import core.internal.arrayop;
4181     alias _arrayOp = arrayOp!Args;
4182 }
4183 
4184 /*
4185  * Support for switch statements switching on strings.
4186  * Params:
4187  *      caseLabels = sorted array of strings generated by compiler. Note the
4188                    strings are sorted by length first, and then lexicographically.
4189  *      condition = string to look up in table
4190  * Returns:
4191  *      index of match in caseLabels, a negative integer if not found
4192 */
4193 int __switch(T, caseLabels...)(/*in*/ const scope T[] condition) pure nothrow @safe @nogc
4194 {
4195     // This closes recursion for other cases.
4196     static if (caseLabels.length == 0)
4197     {
4198         return int.min;
4199     }
4200     else static if (caseLabels.length == 1)
4201     {
4202         return __cmp(condition, caseLabels[0]) == 0 ? 0 : int.min;
4203     }
4204     // To be adjusted after measurements
4205     // Compile-time inlined binary search.
4206     else static if (caseLabels.length < 7)
4207     {
4208         int r = void;
4209         enum mid = cast(int)caseLabels.length / 2;
4210         if (condition.length == caseLabels[mid].length)
4211         {
4212             r = __cmp(condition, caseLabels[mid]);
4213             if (r == 0) return mid;
4214         }
4215         else
4216         {
4217             // Equivalent to (but faster than) condition.length > caseLabels[$ / 2].length ? 1 : -1
4218             r = ((condition.length > caseLabels[mid].length) << 1) - 1;
4219         }
4220 
4221         if (r < 0)
4222         {
4223             // Search the left side
4224             return __switch!(T, caseLabels[0 .. mid])(condition);
4225         }
4226         else
4227         {
4228             // Search the right side
4229             return __switch!(T, caseLabels[mid + 1 .. $])(condition) + mid + 1;
4230         }
4231     }
4232     else
4233     {
4234         // Need immutable array to be accessible in pure code, but case labels are
4235         // currently coerced to the switch condition type (e.g. const(char)[]).
4236         static immutable T[][caseLabels.length] cases = {
4237             auto res = new immutable(T)[][](caseLabels.length);
4238             foreach (i, s; caseLabels)
4239                 res[i] = s.idup;
4240             return res;
4241         }();
4242 
4243         // Run-time binary search in a static array of labels.
4244         return __switchSearch!T(cases[], condition);
4245     }
4246 }
4247 
4248 // binary search in sorted string cases, also see `__switch`.
4249 private int __switchSearch(T)(/*in*/ const scope T[][] cases, /*in*/ const scope T[] condition) pure nothrow @safe @nogc
4250 {
4251     size_t low = 0;
4252     size_t high = cases.length;
4253 
4254     do
4255     {
4256         auto mid = (low + high) / 2;
4257         int r = void;
4258         if (condition.length == cases[mid].length)
4259         {
4260             r = __cmp(condition, cases[mid]);
4261             if (r == 0) return cast(int) mid;
4262         }
4263         else
4264         {
4265             // Generates better code than "expr ? 1 : -1" on dmd and gdc, same with ldc
4266             r = ((condition.length > cases[mid].length) << 1) - 1;
4267         }
4268 
4269         if (r > 0) low = mid + 1;
4270         else high = mid;
4271     }
4272     while (low < high);
4273 
4274     // Not found
4275     return -1;
4276 }
4277 
4278 unittest
4279 {
4280     static void testSwitch(T)()
4281     {
4282         switch (cast(T[]) "c")
4283         {
4284              case "coo":
4285              default:
4286                  break;
4287         }
4288 
4289         static int bug5381(immutable(T)[] s)
4290         {
4291             switch (s)
4292             {
4293                 case "unittest":        return 1;
4294                 case "D_Version2":      return 2;
4295                 case "nonenone":        return 3;
4296                 case "none":            return 4;
4297                 case "all":             return 5;
4298                 default:                return 6;
4299             }
4300         }
4301 
4302         int rc = bug5381("unittest");
4303         assert(rc == 1);
4304 
4305         rc = bug5381("D_Version2");
4306         assert(rc == 2);
4307 
4308         rc = bug5381("nonenone");
4309         assert(rc == 3);
4310 
4311         rc = bug5381("none");
4312         assert(rc == 4);
4313 
4314         rc = bug5381("all");
4315         assert(rc == 5);
4316 
4317         rc = bug5381("nonerandom");
4318         assert(rc == 6);
4319 
4320         static int binarySearch(immutable(T)[] s)
4321         {
4322             switch (s)
4323             {
4324                 static foreach (i; 0 .. 16)
4325                 case i.stringof: return i;
4326                 default: return -1;
4327             }
4328         }
4329         static foreach (i; 0 .. 16)
4330             assert(binarySearch(i.stringof) == i);
4331         assert(binarySearch("") == -1);
4332         assert(binarySearch("sth.") == -1);
4333         assert(binarySearch(null) == -1);
4334 
4335         static int bug16739(immutable(T)[] s)
4336         {
4337             switch (s)
4338             {
4339                 case "\u0100": return 1;
4340                 case "a": return 2;
4341                 default: return 3;
4342             }
4343         }
4344         assert(bug16739("\u0100") == 1);
4345         assert(bug16739("a") == 2);
4346         assert(bug16739("foo") == 3);
4347     }
4348     testSwitch!char;
4349     testSwitch!wchar;
4350     testSwitch!dchar;
4351 }
4352 
4353 // Compiler lowers final switch default case to this (which is a runtime error)
4354 // Old implementation is in core/exception.d
4355 void __switch_error()(string file = __FILE__, size_t line = __LINE__)
4356 {
4357     import core.exception : __switch_errorT;
4358     __switch_errorT(file, line);
4359 }
4360 
4361 // Helper functions
4362 
4363 private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow
4364 {
4365     TypeInfo element = cast() value;
4366     for (;;)
4367     {
4368         if (auto qualified = cast(TypeInfo_Const) element)
4369             element = qualified.base;
4370         else if (auto redefined = cast(TypeInfo_Enum) element)
4371             element = redefined.base;
4372         else if (auto staticArray = cast(TypeInfo_StaticArray) element)
4373             element = staticArray.value;
4374         else if (auto vector = cast(TypeInfo_Vector) element)
4375             element = vector.base;
4376         else
4377             break;
4378     }
4379     return cast(inout) element;
4380 }
4381 
4382 private size_t getArrayHash(in TypeInfo element, in void* ptr, in size_t count) @trusted nothrow
4383 {
4384     if (!count)
4385         return 0;
4386 
4387     const size_t elementSize = element.tsize;
4388     if (!elementSize)
4389         return 0;
4390 
4391     static bool hasCustomToHash(in TypeInfo value) @trusted pure nothrow
4392     {
4393         const element = getElement(value);
4394 
4395         if (const struct_ = cast(const TypeInfo_Struct) element)
4396             return !!struct_.xtoHash;
4397 
4398         return cast(const TypeInfo_Array) element
4399             || cast(const TypeInfo_AssociativeArray) element
4400             || cast(const ClassInfo) element
4401             || cast(const TypeInfo_Interface) element;
4402     }
4403 
4404     import core.internal.traits : externDFunc;
4405     if (!hasCustomToHash(element))
4406         return hashOf(ptr[0 .. elementSize * count]);
4407 
4408     size_t hash = 0;
4409     foreach (size_t i; 0 .. count)
4410         hash = hashOf(element.getHash(ptr + i * elementSize), hash);
4411     return hash;
4412 }
4413 
4414 /// Provide the .dup array property.
4415 @property auto dup(T)(T[] a)
4416     if (!is(const(T) : T))
4417 {
4418     import core.internal.traits : Unconst;
4419     static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
4420                   " to "~Unconst!T.stringof~" in dup.");
4421 
4422     // wrap unsafe _dup in @trusted to preserve @safe postblit
4423     static if (__traits(compiles, (T b) @safe { T a = b; }))
4424         return _trustedDup!(T, Unconst!T)(a);
4425     else
4426         return _dup!(T, Unconst!T)(a);
4427 }
4428 
4429 ///
4430 @safe unittest
4431 {
4432     auto arr = [1, 2];
4433     auto arr2 = arr.dup;
4434     arr[0] = 0;
4435     assert(arr == [0, 2]);
4436     assert(arr2 == [1, 2]);
4437 }
4438 
4439 /// ditto
4440 // const overload to support implicit conversion to immutable (unique result, see DIP29)
4441 @property T[] dup(T)(const(T)[] a)
4442     if (is(const(T) : T))
4443 {
4444     // wrap unsafe _dup in @trusted to preserve @safe postblit
4445     static if (__traits(compiles, (T b) @safe { T a = b; }))
4446         return _trustedDup!(const(T), T)(a);
4447     else
4448         return _dup!(const(T), T)(a);
4449 }
4450 
4451 
4452 /// Provide the .idup array property.
4453 @property immutable(T)[] idup(T)(T[] a)
4454 {
4455     static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
4456                   " to immutable in idup.");
4457 
4458     // wrap unsafe _dup in @trusted to preserve @safe postblit
4459     static if (__traits(compiles, (T b) @safe { T a = b; }))
4460         return _trustedDup!(T, immutable(T))(a);
4461     else
4462         return _dup!(T, immutable(T))(a);
4463 }
4464 
4465 /// ditto
4466 @property immutable(T)[] idup(T:void)(const(T)[] a)
4467 {
4468     return a.dup;
4469 }
4470 
4471 ///
4472 @safe unittest
4473 {
4474     char[] arr = ['a', 'b', 'c'];
4475     string s = arr.idup;
4476     arr[0] = '.';
4477     assert(s == "abc");
4478 }
4479 
4480 private U[] _trustedDup(T, U)(T[] a) @trusted
4481 {
4482     return _dup!(T, U)(a);
4483 }
4484 
4485 private U[] _dup(T, U)(T[] a) // pure nothrow depends on postblit
4486 {
4487     if (__ctfe)
4488     {
4489         static if (is(T : void))
4490             assert(0, "Cannot dup a void[] array at compile time.");
4491         else
4492         {
4493             U[] res;
4494             foreach (ref e; a)
4495                 res ~= e;
4496             return res;
4497         }
4498     }
4499 
4500     import core.stdc..string : memcpy;
4501 
4502     void[] arr = _d_newarrayU(typeid(T[]), a.length);
4503     memcpy(arr.ptr, cast(const(void)*)a.ptr, T.sizeof * a.length);
4504     auto res = *cast(U[]*)&arr;
4505 
4506     static if (!is(T : void))
4507         _doPostblit(res);
4508     return res;
4509 }
4510 
4511 private extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;
4512 
4513 
4514 /**************
4515  * Get the postblit for type T.
4516  * Returns:
4517  *      null if no postblit is necessary
4518  *      function pointer for struct postblits
4519  *      delegate for class postblits
4520  */
4521 private auto _getPostblit(T)() @trusted pure nothrow @nogc
4522 {
4523     // infer static postblit type, run postblit if any
4524     static if (is(T == struct))
4525     {
4526         import core.internal.traits : Unqual;
4527         // use typeid(Unqual!T) here to skip TypeInfo_Const/Shared/...
4528         alias _PostBlitType = typeof(function (ref T t){ T a = t; });
4529         return cast(_PostBlitType)typeid(Unqual!T).xpostblit;
4530     }
4531     else if ((&typeid(T).postblit).funcptr !is &TypeInfo.postblit)
4532     {
4533         alias _PostBlitType = typeof(delegate (ref T t){ T a = t; });
4534         return cast(_PostBlitType)&typeid(T).postblit;
4535     }
4536     else
4537         return null;
4538 }
4539 
4540 private void _doPostblit(T)(T[] arr)
4541 {
4542     // infer static postblit type, run postblit if any
4543     if (auto postblit = _getPostblit!T())
4544     {
4545         foreach (ref elem; arr)
4546             postblit(elem);
4547     }
4548 }
4549 
4550 unittest
4551 {
4552     static struct S1 { int* p; }
4553     static struct S2 { @disable this(); }
4554     static struct S3 { @disable this(this); }
4555 
4556     int dg1() pure nothrow @safe
4557     {
4558         {
4559            char[] m;
4560            string i;
4561            m = m.dup;
4562            i = i.idup;
4563            m = i.dup;
4564            i = m.idup;
4565         }
4566         {
4567            S1[] m;
4568            immutable(S1)[] i;
4569            m = m.dup;
4570            i = i.idup;
4571            static assert(!is(typeof(m.idup)));
4572            static assert(!is(typeof(i.dup)));
4573         }
4574         {
4575             S3[] m;
4576             immutable(S3)[] i;
4577             static assert(!is(typeof(m.dup)));
4578             static assert(!is(typeof(i.idup)));
4579         }
4580         {
4581             shared(S1)[] m;
4582             m = m.dup;
4583             static assert(!is(typeof(m.idup)));
4584         }
4585         {
4586             int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
4587         }
4588         return 1;
4589     }
4590 
4591     int dg2() pure nothrow @safe
4592     {
4593         {
4594            S2[] m = [S2.init, S2.init];
4595            immutable(S2)[] i = [S2.init, S2.init];
4596            m = m.dup;
4597            m = i.dup;
4598            i = m.idup;
4599            i = i.idup;
4600         }
4601         return 2;
4602     }
4603 
4604     enum a = dg1();
4605     enum b = dg2();
4606     assert(dg1() == a);
4607     assert(dg2() == b);
4608 }
4609 
4610 unittest
4611 {
4612     static struct Sunpure { this(this) @safe nothrow {} }
4613     static struct Sthrow { this(this) @safe pure {} }
4614     static struct Sunsafe { this(this) @system pure nothrow {} }
4615 
4616     static assert( __traits(compiles, ()         { [].dup!Sunpure; }));
4617     static assert(!__traits(compiles, () pure    { [].dup!Sunpure; }));
4618     static assert( __traits(compiles, ()         { [].dup!Sthrow; }));
4619     static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
4620     static assert( __traits(compiles, ()         { [].dup!Sunsafe; }));
4621     static assert(!__traits(compiles, () @safe   { [].dup!Sunsafe; }));
4622 
4623     static assert( __traits(compiles, ()         { [].idup!Sunpure; }));
4624     static assert(!__traits(compiles, () pure    { [].idup!Sunpure; }));
4625     static assert( __traits(compiles, ()         { [].idup!Sthrow; }));
4626     static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
4627     static assert( __traits(compiles, ()         { [].idup!Sunsafe; }));
4628     static assert(!__traits(compiles, () @safe   { [].idup!Sunsafe; }));
4629 }
4630 
4631 unittest
4632 {
4633     static int*[] pureFoo() pure { return null; }
4634     { char[] s; immutable x = s.dup; }
4635     { immutable x = (cast(int*[])null).dup; }
4636     { immutable x = pureFoo(); }
4637     { immutable x = pureFoo().dup; }
4638 }
4639 
4640 unittest
4641 {
4642     auto a = [1, 2, 3];
4643     auto b = a.dup;
4644     debug(SENTINEL) {} else
4645         assert(b.capacity >= 3);
4646 }
4647 
4648 unittest
4649 {
4650     // Bugzilla 12580
4651     void[] m = [0];
4652     shared(void)[] s = [cast(shared)1];
4653     immutable(void)[] i = [cast(immutable)2];
4654 
4655     s = s.dup;
4656     static assert(is(typeof(s.dup) == shared(void)[]));
4657 
4658     m = i.dup;
4659     i = m.dup;
4660     i = i.idup;
4661     i = m.idup;
4662     i = s.idup;
4663     i = s.dup;
4664     static assert(!__traits(compiles, m = s.dup));
4665 }
4666 
4667 unittest
4668 {
4669     // Bugzilla 13809
4670     static struct S
4671     {
4672         this(this) {}
4673         ~this() {}
4674     }
4675 
4676     S[] arr;
4677     auto a = arr.dup;
4678 }
4679 
4680 unittest
4681 {
4682     // Bugzilla 16504
4683     static struct S
4684     {
4685         __gshared int* gp;
4686         int* p;
4687         // postblit and hence .dup could escape
4688         this(this) { gp = p; }
4689     }
4690 
4691     int p;
4692     scope S[1] arr = [S(&p)];
4693     auto a = arr.dup; // dup does escape
4694 }
4695 
4696 // compiler frontend lowers dynamic array comparison to this
4697 bool __ArrayEq(T1, T2)(T1[] a, T2[] b)
4698 {
4699     if (a.length != b.length)
4700         return false;
4701     foreach (size_t i; 0 .. a.length)
4702     {
4703         if (a[i] != b[i])
4704             return false;
4705     }
4706     return true;
4707 }
4708 
4709 // compiler frontend lowers struct array postblitting to this
4710 void __ArrayPostblit(T)(T[] a)
4711 {
4712     foreach (ref T e; a)
4713         e.__xpostblit();
4714 }
4715 
4716 // compiler frontend lowers dynamic array deconstruction to this
4717 void __ArrayDtor(T)(T[] a)
4718 {
4719     foreach_reverse (ref T e; a)
4720         e.__xdtor();
4721 }
4722 
4723 /**
4724 Used by `__ArrayCast` to emit a descriptive error message.
4725 
4726 It is a template so it can be used by `__ArrayCast` in -betterC
4727 builds.  It is separate from `__ArrayCast` to minimize code
4728 bloat.
4729 
4730 Params:
4731     fromType = name of the type being cast from
4732     fromSize = total size in bytes of the array being cast from
4733     toType   = name of the type being cast o
4734     toSize   = total size in bytes of the array being cast to
4735  */
4736 private void onArrayCastError()(string fromType, size_t fromSize, string toType, size_t toSize) @trusted
4737 {
4738     import core.internal..string : unsignedToTempString;
4739     import core.stdc.stdlib : alloca;
4740 
4741     const(char)[][8] msgComponents =
4742     [
4743         "Cannot cast `"
4744         , fromType
4745         , "` to `"
4746         , toType
4747         , "`; an array of size "
4748         , unsignedToTempString(fromSize)
4749         , " does not align on an array of size "
4750         , unsignedToTempString(toSize)
4751     ];
4752 
4753     // convert discontiguous `msgComponents` to contiguous string on the stack
4754     size_t length = 0;
4755     foreach (m ; msgComponents)
4756         length += m.length;
4757 
4758     auto msg = (cast(char*)alloca(length))[0 .. length];
4759 
4760     size_t index = 0;
4761     foreach (m ; msgComponents)
4762         foreach (c; m)
4763             msg[index++] = c;
4764 
4765     // first argument must evaluate to `false` at compile-time to maintain memory safety in release builds
4766     assert(false, msg);
4767 }
4768 
4769 /**
4770 The compiler lowers expressions of `cast(TTo[])TFrom[]` to
4771 this implementation.
4772 
4773 Params:
4774     from = the array to reinterpret-cast
4775 
4776 Returns:
4777     `from` reinterpreted as `TTo[]`
4778  */
4779 TTo[] __ArrayCast(TFrom, TTo)(TFrom[] from) @nogc pure @trusted
4780 {
4781     const fromSize = from.length * TFrom.sizeof;
4782     const toLength = fromSize / TTo.sizeof;
4783 
4784     if ((fromSize % TTo.sizeof) != 0)
4785     {
4786         onArrayCastError(TFrom.stringof, fromSize, TTo.stringof, toLength * TTo.sizeof);
4787     }
4788 
4789     struct Array
4790     {
4791         size_t length;
4792         void* ptr;
4793     }
4794     auto a = cast(Array*)&from;
4795     a.length = toLength; // jam new length
4796     return *cast(TTo[]*)a;
4797 }
4798 
4799 @safe @nogc pure nothrow unittest
4800 {
4801     byte[int.sizeof * 3] b = cast(byte) 0xab;
4802     int[] i;
4803     short[] s;
4804 
4805     i = __ArrayCast!(byte, int)(b);
4806     assert(i.length == 3);
4807     foreach (v; i)
4808         assert(v == cast(int) 0xabab_abab);
4809 
4810     s = __ArrayCast!(byte, short)(b);
4811     assert(s.length == 6);
4812     foreach (v; s)
4813         assert(v == cast(short) 0xabab);
4814 
4815     s = __ArrayCast!(int, short)(i);
4816     assert(s.length == 6);
4817     foreach (v; s)
4818         assert(v == cast(short) 0xabab);
4819 }
4820 
4821 // Allows customized assert error messages
4822 string _d_assert_fail(string comp, A, B)(A a, B b)
4823 {
4824     import core.internal.dassert : invertCompToken, miniFormat;
4825     auto valA = miniFormat(a);
4826     auto valB = miniFormat(b);
4827     enum token = invertCompToken(comp);
4828     return valA ~ " " ~ token ~ " " ~ valB;
4829 }
Suggestion Box / Bug Report