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