The OpenD Programming Language

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