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