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