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