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