The OpenD Programming Language

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