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