Split up "gfortran.dg/goacc/loop-2.f95"
[official-gcc.git] / libphobos / libdruntime / object.d
blob2fe27a195df3b84561a9131e7ab65522aa022e3e
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.
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 */
11 module object;
13 private
15 extern (C) Object _d_newclass(const TypeInfo_Class ci);
16 extern (C) void rt_finalize(void *data, bool det=true);
19 // NOTE: For some reason, this declaration method doesn't work
20 // in this particular file (and this file only). It must
21 // be a DMD thing.
22 //alias typeof(int.sizeof) size_t;
23 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
25 version (D_LP64)
27 alias size_t = ulong;
28 alias ptrdiff_t = long;
30 else
32 alias size_t = uint;
33 alias ptrdiff_t = int;
36 alias sizediff_t = ptrdiff_t; //For backwards compatibility only.
38 alias hash_t = size_t; //For backwards compatibility only.
39 alias equals_t = bool; //For backwards compatibility only.
41 alias string = immutable(char)[];
42 alias wstring = immutable(wchar)[];
43 alias dstring = immutable(dchar)[];
45 version (D_ObjectiveC) public import core.attribute : selector;
47 /**
48 * All D class objects inherit from Object.
50 class Object
52 /**
53 * Convert Object to a human readable string.
55 string toString()
57 return typeid(this).name;
60 /**
61 * Compute hash function for Object.
63 size_t toHash() @trusted nothrow
65 // BUG: this prevents a compacting GC from working, needs to be fixed
66 return cast(size_t)cast(void*)this;
69 /**
70 * Compare with another Object obj.
71 * Returns:
72 * $(TABLE
73 * $(TR $(TD this < obj) $(TD < 0))
74 * $(TR $(TD this == obj) $(TD 0))
75 * $(TR $(TD this > obj) $(TD > 0))
76 * )
78 int opCmp(Object o)
80 // BUG: this prevents a compacting GC from working, needs to be fixed
81 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
83 throw new Exception("need opCmp for class " ~ typeid(this).name);
84 //return this !is o;
87 /**
88 * Test whether $(D this) is equal to $(D o).
89 * The default implementation only compares by identity (using the $(D is) operator).
90 * Generally, overrides for $(D opEquals) should attempt to compare objects by their contents.
92 bool opEquals(Object o)
94 return this is o;
97 interface Monitor
99 void lock();
100 void unlock();
104 * Create instance of class specified by the fully qualified name
105 * classname.
106 * The class must either have no constructors or have
107 * a default constructor.
108 * Returns:
109 * null if failed
110 * Example:
111 * ---
112 * module foo.bar;
114 * class C
116 * this() { x = 10; }
117 * int x;
120 * void main()
122 * auto c = cast(C)Object.factory("foo.bar.C");
123 * assert(c !is null && c.x == 10);
125 * ---
127 static Object factory(string classname)
129 auto ci = TypeInfo_Class.find(classname);
130 if (ci)
132 return ci.create();
134 return null;
138 auto opEquals(Object lhs, Object rhs)
140 // If aliased to the same object or both null => equal
141 if (lhs is rhs) return true;
143 // If either is null => non-equal
144 if (lhs is null || rhs is null) return false;
146 // If same exact type => one call to method opEquals
147 if (typeid(lhs) is typeid(rhs) ||
148 !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
149 /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
150 (issue 7147). But CTFE also guarantees that equal TypeInfos are
151 always identical. So, no opEquals needed during CTFE. */
153 return lhs.opEquals(rhs);
156 // General case => symmetric calls to method opEquals
157 return lhs.opEquals(rhs) && rhs.opEquals(lhs);
160 /************************
161 * Returns true if lhs and rhs are equal.
163 auto opEquals(const Object lhs, const Object rhs)
165 // A hack for the moment.
166 return opEquals(cast()lhs, cast()rhs);
169 private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
171 void setSameMutex(shared Object ownee, shared Object owner)
173 _d_setSameMutex(ownee, owner);
177 * Information about an interface.
178 * When an object is accessed via an interface, an Interface* appears as the
179 * first entry in its vtbl.
181 struct Interface
183 TypeInfo_Class classinfo; /// .classinfo for this interface (not for containing class)
184 void*[] vtbl;
185 size_t offset; /// offset to Interface 'this' from Object 'this'
189 * Array of pairs giving the offset and type information for each
190 * member in an aggregate.
192 struct OffsetTypeInfo
194 size_t offset; /// Offset of member from start of object
195 TypeInfo ti; /// TypeInfo for this member
199 * Runtime type information about a type.
200 * Can be retrieved for any type using a
201 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
203 class TypeInfo
205 override string toString() const pure @safe nothrow
207 return typeid(this).name;
210 override size_t toHash() @trusted const nothrow
212 import core.internal.traits : externDFunc;
213 alias hashOf = externDFunc!("rt.util.hash.hashOf",
214 size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
215 return hashOf(this.toString(), 0);
218 override int opCmp(Object o)
220 import core.internal.traits : externDFunc;
221 alias dstrcmp = externDFunc!("core.internal.string.dstrcmp",
222 int function(scope const char[] s1, scope const char[] s2) @trusted pure nothrow @nogc);
224 if (this is o)
225 return 0;
226 TypeInfo ti = cast(TypeInfo)o;
227 if (ti is null)
228 return 1;
229 return dstrcmp(this.toString(), ti.toString());
232 override bool opEquals(Object o)
234 /* TypeInfo instances are singletons, but duplicates can exist
235 * across DLL's. Therefore, comparing for a name match is
236 * sufficient.
238 if (this is o)
239 return true;
240 auto ti = cast(const TypeInfo)o;
241 return ti && this.toString() == ti.toString();
245 * Computes a hash of the instance of a type.
246 * Params:
247 * p = pointer to start of instance of the type
248 * Returns:
249 * the hash
250 * Bugs:
251 * fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
253 size_t getHash(in void* p) @trusted nothrow const { return cast(size_t)p; }
255 /// Compares two instances for equality.
256 bool equals(in void* p1, in void* p2) const { return p1 == p2; }
258 /// Compares two instances for <, ==, or >.
259 int compare(in void* p1, in void* p2) const { return _xopCmp(p1, p2); }
261 /// Returns size of the type.
262 @property size_t tsize() nothrow pure const @safe @nogc { return 0; }
264 /// Swaps two instances of the type.
265 void swap(void* p1, void* p2) const
267 immutable size_t n = tsize;
268 for (size_t i = 0; i < n; i++)
270 byte t = (cast(byte *)p1)[i];
271 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
272 (cast(byte*)p2)[i] = t;
276 /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
277 null if none. */
278 @property inout(TypeInfo) next() nothrow pure inout @nogc { return null; }
281 * Return default initializer. If the type should be initialized to all
282 * zeros, an array with a null ptr and a length equal to the type size will
283 * be returned. For static arrays, this returns the default initializer for
284 * a single element of the array, use `tsize` to get the correct size.
286 abstract const(void)[] initializer() nothrow pure const @safe @nogc;
288 /** Get flags for type: 1 means GC should scan for pointers,
289 2 means arg of this type is passed in XMM register */
290 @property uint flags() nothrow pure const @safe @nogc { return 0; }
292 /// Get type information on the contents of the type; null if not available
293 const(OffsetTypeInfo)[] offTi() const { return null; }
294 /// Run the destructor on the object and all its sub-objects
295 void destroy(void* p) const {}
296 /// Run the postblit on the object and all its sub-objects
297 void postblit(void* p) const {}
300 /// Return alignment of type
301 @property size_t talign() nothrow pure const @safe @nogc { return tsize; }
303 /** Return internal info on arguments fitting into 8byte.
304 * See X86-64 ABI 3.2.3
306 version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
308 arg1 = this;
309 return 0;
312 /** Return info used by the garbage collector to do precise collection.
314 @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return null; }
317 class TypeInfo_Enum : TypeInfo
319 override string toString() const { return name; }
321 override bool opEquals(Object o)
323 if (this is o)
324 return true;
325 auto c = cast(const TypeInfo_Enum)o;
326 return c && this.name == c.name &&
327 this.base == c.base;
330 override size_t getHash(in void* p) const { return base.getHash(p); }
331 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
332 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
333 override @property size_t tsize() nothrow pure const { return base.tsize; }
334 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
336 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
337 override @property uint flags() nothrow pure const { return base.flags; }
339 override const(void)[] initializer() const
341 return m_init.length ? m_init : base.initializer();
344 override @property size_t talign() nothrow pure const { return base.talign; }
346 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
348 return base.argTypes(arg1, arg2);
351 override @property immutable(void)* rtInfo() const { return base.rtInfo; }
353 TypeInfo base;
354 string name;
355 void[] m_init;
358 unittest // issue 12233
360 static assert(is(typeof(TypeInfo.init) == TypeInfo));
361 assert(TypeInfo.init is null);
365 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
366 class TypeInfo_Pointer : TypeInfo
368 override string toString() const { return m_next.toString() ~ "*"; }
370 override bool opEquals(Object o)
372 if (this is o)
373 return true;
374 auto c = cast(const TypeInfo_Pointer)o;
375 return c && this.m_next == c.m_next;
378 override size_t getHash(in void* p) @trusted const
380 return cast(size_t)*cast(void**)p;
383 override bool equals(in void* p1, in void* p2) const
385 return *cast(void**)p1 == *cast(void**)p2;
388 override int compare(in void* p1, in void* p2) const
390 if (*cast(void**)p1 < *cast(void**)p2)
391 return -1;
392 else if (*cast(void**)p1 > *cast(void**)p2)
393 return 1;
394 else
395 return 0;
398 override @property size_t tsize() nothrow pure const
400 return (void*).sizeof;
403 override const(void)[] initializer() const @trusted
405 return (cast(void *)null)[0 .. (void*).sizeof];
408 override void swap(void* p1, void* p2) const
410 void* tmp = *cast(void**)p1;
411 *cast(void**)p1 = *cast(void**)p2;
412 *cast(void**)p2 = tmp;
415 override @property inout(TypeInfo) next() nothrow pure inout { return m_next; }
416 override @property uint flags() nothrow pure const { return 1; }
418 TypeInfo m_next;
421 class TypeInfo_Array : TypeInfo
423 override string toString() const { return value.toString() ~ "[]"; }
425 override bool opEquals(Object o)
427 if (this is o)
428 return true;
429 auto c = cast(const TypeInfo_Array)o;
430 return c && this.value == c.value;
433 override size_t getHash(in void* p) @trusted const
435 void[] a = *cast(void[]*)p;
436 return getArrayHash(value, a.ptr, a.length);
439 override bool equals(in void* p1, in void* p2) const
441 void[] a1 = *cast(void[]*)p1;
442 void[] a2 = *cast(void[]*)p2;
443 if (a1.length != a2.length)
444 return false;
445 size_t sz = value.tsize;
446 for (size_t i = 0; i < a1.length; i++)
448 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
449 return false;
451 return true;
454 override int compare(in void* p1, in void* p2) const
456 void[] a1 = *cast(void[]*)p1;
457 void[] a2 = *cast(void[]*)p2;
458 size_t sz = value.tsize;
459 size_t len = a1.length;
461 if (a2.length < len)
462 len = a2.length;
463 for (size_t u = 0; u < len; u++)
465 immutable int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
466 if (result)
467 return result;
469 return cast(int)a1.length - cast(int)a2.length;
472 override @property size_t tsize() nothrow pure const
474 return (void[]).sizeof;
477 override const(void)[] initializer() const @trusted
479 return (cast(void *)null)[0 .. (void[]).sizeof];
482 override void swap(void* p1, void* p2) const
484 void[] tmp = *cast(void[]*)p1;
485 *cast(void[]*)p1 = *cast(void[]*)p2;
486 *cast(void[]*)p2 = tmp;
489 TypeInfo value;
491 override @property inout(TypeInfo) next() nothrow pure inout
493 return value;
496 override @property uint flags() nothrow pure const { return 1; }
498 override @property size_t talign() nothrow pure const
500 return (void[]).alignof;
503 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
505 arg1 = typeid(size_t);
506 arg2 = typeid(void*);
507 return 0;
511 class TypeInfo_StaticArray : TypeInfo
513 override string toString() const
515 import core.internal.traits : externDFunc;
516 alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString",
517 char[] function(ulong, return char[], uint) @safe pure nothrow @nogc);
519 char[20] tmpBuff = void;
520 return value.toString() ~ "[" ~ sizeToTempString(len, tmpBuff, 10) ~ "]";
523 override bool opEquals(Object o)
525 if (this is o)
526 return true;
527 auto c = cast(const TypeInfo_StaticArray)o;
528 return c && this.len == c.len &&
529 this.value == c.value;
532 override size_t getHash(in void* p) @trusted const
534 return getArrayHash(value, p, len);
537 override bool equals(in void* p1, in void* p2) const
539 size_t sz = value.tsize;
541 for (size_t u = 0; u < len; u++)
543 if (!value.equals(p1 + u * sz, p2 + u * sz))
544 return false;
546 return true;
549 override int compare(in void* p1, in void* p2) const
551 size_t sz = value.tsize;
553 for (size_t u = 0; u < len; u++)
555 immutable int result = value.compare(p1 + u * sz, p2 + u * sz);
556 if (result)
557 return result;
559 return 0;
562 override @property size_t tsize() nothrow pure const
564 return len * value.tsize;
567 override void swap(void* p1, void* p2) const
569 import core.memory;
570 import core.stdc.string : memcpy;
572 void* tmp;
573 size_t sz = value.tsize;
574 ubyte[16] buffer;
575 void* pbuffer;
577 if (sz < buffer.sizeof)
578 tmp = buffer.ptr;
579 else
580 tmp = pbuffer = (new void[sz]).ptr;
582 for (size_t u = 0; u < len; u += sz)
584 size_t o = u * sz;
585 memcpy(tmp, p1 + o, sz);
586 memcpy(p1 + o, p2 + o, sz);
587 memcpy(p2 + o, tmp, sz);
589 if (pbuffer)
590 GC.free(pbuffer);
593 override const(void)[] initializer() nothrow pure const
595 return value.initializer();
598 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
599 override @property uint flags() nothrow pure const { return value.flags; }
601 override void destroy(void* p) const
603 immutable sz = value.tsize;
604 p += sz * len;
605 foreach (i; 0 .. len)
607 p -= sz;
608 value.destroy(p);
612 override void postblit(void* p) const
614 immutable sz = value.tsize;
615 foreach (i; 0 .. len)
617 value.postblit(p);
618 p += sz;
622 TypeInfo value;
623 size_t len;
625 override @property size_t talign() nothrow pure const
627 return value.talign;
630 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
632 arg1 = typeid(void*);
633 return 0;
637 class TypeInfo_AssociativeArray : TypeInfo
639 override string toString() const
641 return value.toString() ~ "[" ~ key.toString() ~ "]";
644 override bool opEquals(Object o)
646 if (this is o)
647 return true;
648 auto c = cast(const TypeInfo_AssociativeArray)o;
649 return c && this.key == c.key &&
650 this.value == c.value;
653 override bool equals(in void* p1, in void* p2) @trusted const
655 return !!_aaEqual(this, *cast(const void**) p1, *cast(const void**) p2);
658 override hash_t getHash(in void* p) nothrow @trusted const
660 return _aaGetHash(cast(void*)p, this);
663 // BUG: need to add the rest of the functions
665 override @property size_t tsize() nothrow pure const
667 return (char[int]).sizeof;
670 override const(void)[] initializer() const @trusted
672 return (cast(void *)null)[0 .. (char[int]).sizeof];
675 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
676 override @property uint flags() nothrow pure const { return 1; }
678 TypeInfo value;
679 TypeInfo key;
681 override @property size_t talign() nothrow pure const
683 return (char[int]).alignof;
686 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
688 arg1 = typeid(void*);
689 return 0;
693 class TypeInfo_Vector : TypeInfo
695 override string toString() const { return "__vector(" ~ base.toString() ~ ")"; }
697 override bool opEquals(Object o)
699 if (this is o)
700 return true;
701 auto c = cast(const TypeInfo_Vector)o;
702 return c && this.base == c.base;
705 override size_t getHash(in void* p) const { return base.getHash(p); }
706 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
707 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
708 override @property size_t tsize() nothrow pure const { return base.tsize; }
709 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
711 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
712 override @property uint flags() nothrow pure const { return base.flags; }
714 override const(void)[] initializer() nothrow pure const
716 return base.initializer();
719 override @property size_t talign() nothrow pure const { return 16; }
721 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
723 return base.argTypes(arg1, arg2);
726 TypeInfo base;
729 class TypeInfo_Function : TypeInfo
731 override string toString() const
733 import core.demangle : demangleType;
735 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
736 SafeDemangleFunctionType demangle = ( () @trusted => cast(SafeDemangleFunctionType)(&demangleType) ) ();
738 return (() @trusted => cast(string)(demangle(deco))) ();
741 override bool opEquals(Object o)
743 if (this is o)
744 return true;
745 auto c = cast(const TypeInfo_Function)o;
746 return c && this.deco == c.deco;
749 // BUG: need to add the rest of the functions
751 override @property size_t tsize() nothrow pure const
753 return 0; // no size for functions
756 override const(void)[] initializer() const @safe
758 return null;
761 TypeInfo next;
764 * Mangled function type string
766 string deco;
769 unittest
771 abstract class C
773 void func();
774 void func(int a);
775 int func(int a, int b);
778 alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func"));
779 assert(typeid(functionTypes[0]).toString() == "void function()");
780 assert(typeid(functionTypes[1]).toString() == "void function(int)");
781 assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
784 class TypeInfo_Delegate : TypeInfo
786 override string toString() const
788 return cast(string)(next.toString() ~ " delegate()");
791 override bool opEquals(Object o)
793 if (this is o)
794 return true;
795 auto c = cast(const TypeInfo_Delegate)o;
796 return c && this.deco == c.deco;
799 override size_t getHash(in void* p) @trusted const
801 return hashOf(*cast(void delegate()*)p);
804 override bool equals(in void* p1, in void* p2) const
806 auto dg1 = *cast(void delegate()*)p1;
807 auto dg2 = *cast(void delegate()*)p2;
808 return dg1 == dg2;
811 override int compare(in void* p1, in void* p2) const
813 auto dg1 = *cast(void delegate()*)p1;
814 auto dg2 = *cast(void delegate()*)p2;
816 if (dg1 < dg2)
817 return -1;
818 else if (dg1 > dg2)
819 return 1;
820 else
821 return 0;
824 override @property size_t tsize() nothrow pure const
826 alias dg = int delegate();
827 return dg.sizeof;
830 override const(void)[] initializer() const @trusted
832 return (cast(void *)null)[0 .. (int delegate()).sizeof];
835 override @property uint flags() nothrow pure const { return 1; }
837 TypeInfo next;
838 string deco;
840 override @property size_t talign() nothrow pure const
842 alias dg = int delegate();
843 return dg.alignof;
846 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
848 arg1 = typeid(void*);
849 arg2 = typeid(void*);
850 return 0;
854 unittest
856 // Bugzilla 15367
857 void f1() {}
858 void f2() {}
860 // TypeInfo_Delegate.getHash
861 int[void delegate()] aa;
862 assert(aa.length == 0);
863 aa[&f1] = 1;
864 assert(aa.length == 1);
865 aa[&f1] = 1;
866 assert(aa.length == 1);
868 auto a1 = [&f2, &f1];
869 auto a2 = [&f2, &f1];
871 // TypeInfo_Delegate.equals
872 for (auto i = 0; i < 2; i++)
873 assert(a1[i] == a2[i]);
874 assert(a1 == a2);
876 // TypeInfo_Delegate.compare
877 for (auto i = 0; i < 2; i++)
878 assert(a1[i] <= a2[i]);
879 assert(a1 <= a2);
883 * Runtime type information about a class.
884 * Can be retrieved from an object instance by using the
885 * $(DDSUBLINK spec/property,classinfo, .classinfo) property.
887 class TypeInfo_Class : TypeInfo
889 override string toString() const { return info.name; }
891 override bool opEquals(Object o)
893 if (this is o)
894 return true;
895 auto c = cast(const TypeInfo_Class)o;
896 return c && this.info.name == c.info.name;
899 override size_t getHash(in void* p) @trusted const
901 auto o = *cast(Object*)p;
902 return o ? o.toHash() : 0;
905 override bool equals(in void* p1, in void* p2) const
907 Object o1 = *cast(Object*)p1;
908 Object o2 = *cast(Object*)p2;
910 return (o1 is o2) || (o1 && o1.opEquals(o2));
913 override int compare(in void* p1, in void* p2) const
915 Object o1 = *cast(Object*)p1;
916 Object o2 = *cast(Object*)p2;
917 int c = 0;
919 // Regard null references as always being "less than"
920 if (o1 !is o2)
922 if (o1)
924 if (!o2)
925 c = 1;
926 else
927 c = o1.opCmp(o2);
929 else
930 c = -1;
932 return c;
935 override @property size_t tsize() nothrow pure const
937 return Object.sizeof;
940 override const(void)[] initializer() nothrow pure const @safe
942 return m_init;
945 override @property uint flags() nothrow pure const { return 1; }
947 override @property const(OffsetTypeInfo)[] offTi() nothrow pure const
949 return m_offTi;
952 @property auto info() @safe nothrow pure const { return this; }
953 @property auto typeinfo() @safe nothrow pure const { return this; }
955 byte[] m_init; /** class static initializer
956 * (init.length gives size in bytes of class)
958 string name; /// class name
959 void*[] vtbl; /// virtual function pointer table
960 Interface[] interfaces; /// interfaces this class implements
961 TypeInfo_Class base; /// base class
962 void* destructor;
963 void function(Object) classInvariant;
964 enum ClassFlags : uint
966 isCOMclass = 0x1,
967 noPointers = 0x2,
968 hasOffTi = 0x4,
969 hasCtor = 0x8,
970 hasGetMembers = 0x10,
971 hasTypeInfo = 0x20,
972 isAbstract = 0x40,
973 isCPPclass = 0x80,
974 hasDtor = 0x100,
976 ClassFlags m_flags;
977 void* deallocator;
978 OffsetTypeInfo[] m_offTi;
979 void function(Object) defaultConstructor; // default Constructor
981 immutable(void)* m_RTInfo; // data for precise GC
982 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
985 * Search all modules for TypeInfo_Class corresponding to classname.
986 * Returns: null if not found
988 static const(TypeInfo_Class) find(in char[] classname)
990 foreach (m; ModuleInfo)
992 if (m)
994 //writefln("module %s, %d", m.name, m.localClasses.length);
995 foreach (c; m.localClasses)
997 if (c is null)
998 continue;
999 //writefln("\tclass %s", c.name);
1000 if (c.name == classname)
1001 return c;
1005 return null;
1009 * Create instance of Object represented by 'this'.
1011 Object create() const
1013 if (m_flags & 8 && !defaultConstructor)
1014 return null;
1015 if (m_flags & 64) // abstract
1016 return null;
1017 Object o = _d_newclass(this);
1018 if (m_flags & 8 && defaultConstructor)
1020 defaultConstructor(o);
1022 return o;
1026 alias ClassInfo = TypeInfo_Class;
1028 unittest
1030 // Bugzilla 14401
1031 static class X
1033 int a;
1036 assert(typeid(X).initializer is typeid(X).m_init);
1037 assert(typeid(X).initializer.length == typeid(const(X)).initializer.length);
1038 assert(typeid(X).initializer.length == typeid(shared(X)).initializer.length);
1039 assert(typeid(X).initializer.length == typeid(immutable(X)).initializer.length);
1042 class TypeInfo_Interface : TypeInfo
1044 override string toString() const { return info.name; }
1046 override bool opEquals(Object o)
1048 if (this is o)
1049 return true;
1050 auto c = cast(const TypeInfo_Interface)o;
1051 return c && this.info.name == typeid(c).name;
1054 override size_t getHash(in void* p) @trusted const
1056 Interface* pi = **cast(Interface ***)*cast(void**)p;
1057 Object o = cast(Object)(*cast(void**)p - pi.offset);
1058 assert(o);
1059 return o.toHash();
1062 override bool equals(in void* p1, in void* p2) const
1064 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1065 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1066 pi = **cast(Interface ***)*cast(void**)p2;
1067 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1069 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
1072 override int compare(in void* p1, in void* p2) const
1074 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1075 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1076 pi = **cast(Interface ***)*cast(void**)p2;
1077 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1078 int c = 0;
1080 // Regard null references as always being "less than"
1081 if (o1 != o2)
1083 if (o1)
1085 if (!o2)
1086 c = 1;
1087 else
1088 c = o1.opCmp(o2);
1090 else
1091 c = -1;
1093 return c;
1096 override @property size_t tsize() nothrow pure const
1098 return Object.sizeof;
1101 override const(void)[] initializer() const @trusted
1103 return (cast(void *)null)[0 .. Object.sizeof];
1106 override @property uint flags() nothrow pure const { return 1; }
1108 TypeInfo_Class info;
1111 class TypeInfo_Struct : TypeInfo
1113 override string toString() const { return name; }
1115 override bool opEquals(Object o)
1117 if (this is o)
1118 return true;
1119 auto s = cast(const TypeInfo_Struct)o;
1120 return s && this.name == s.name &&
1121 this.initializer().length == s.initializer().length;
1124 override size_t getHash(in void* p) @trusted pure nothrow const
1126 assert(p);
1127 if (xtoHash)
1129 return (*xtoHash)(p);
1131 else
1133 import core.internal.traits : externDFunc;
1134 alias hashOf = externDFunc!("rt.util.hash.hashOf",
1135 size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
1136 return hashOf(p[0 .. initializer().length], 0);
1140 override bool equals(in void* p1, in void* p2) @trusted pure nothrow const
1142 import core.stdc.string : memcmp;
1144 if (!p1 || !p2)
1145 return false;
1146 else if (xopEquals)
1148 version (GNU)
1149 { // BUG: GDC and DMD use different calling conventions
1150 return (*xopEquals)(p2, p1);
1152 else
1153 return (*xopEquals)(p1, p2);
1155 else if (p1 == p2)
1156 return true;
1157 else
1158 // BUG: relies on the GC not moving objects
1159 return memcmp(p1, p2, initializer().length) == 0;
1162 override int compare(in void* p1, in void* p2) @trusted pure nothrow const
1164 import core.stdc.string : memcmp;
1166 // Regard null references as always being "less than"
1167 if (p1 != p2)
1169 if (p1)
1171 if (!p2)
1172 return true;
1173 else if (xopCmp)
1175 version (GNU)
1176 { // BUG: GDC and DMD use different calling conventions
1177 return (*xopCmp)(p1, p2);
1179 else
1180 return (*xopCmp)(p2, p1);
1182 else
1183 // BUG: relies on the GC not moving objects
1184 return memcmp(p1, p2, initializer().length);
1186 else
1187 return -1;
1189 return 0;
1192 override @property size_t tsize() nothrow pure const
1194 return initializer().length;
1197 override const(void)[] initializer() nothrow pure const @safe
1199 return m_init;
1202 override @property uint flags() nothrow pure const { return m_flags; }
1204 override @property size_t talign() nothrow pure const { return m_align; }
1206 final override void destroy(void* p) const
1208 if (xdtor)
1210 if (m_flags & StructFlags.isDynamicType)
1211 (*xdtorti)(p, this);
1212 else
1213 (*xdtor)(p);
1217 override void postblit(void* p) const
1219 if (xpostblit)
1220 (*xpostblit)(p);
1223 string name;
1224 void[] m_init; // initializer; m_init.ptr == null if 0 initialize
1226 @safe pure nothrow
1228 size_t function(in void*) xtoHash;
1229 bool function(in void*, in void*) xopEquals;
1230 int function(in void*, in void*) xopCmp;
1231 string function(in void*) xtoString;
1233 enum StructFlags : uint
1235 hasPointers = 0x1,
1236 isDynamicType = 0x2, // built at runtime, needs type info in xdtor
1238 StructFlags m_flags;
1240 union
1242 void function(void*) xdtor;
1243 void function(void*, const TypeInfo_Struct ti) xdtorti;
1245 void function(void*) xpostblit;
1247 uint m_align;
1249 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
1251 version (X86_64)
1253 override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1255 arg1 = m_arg1;
1256 arg2 = m_arg2;
1257 return 0;
1259 TypeInfo m_arg1;
1260 TypeInfo m_arg2;
1262 immutable(void)* m_RTInfo; // data for precise GC
1265 unittest
1267 struct S
1269 bool opEquals(ref const S rhs) const
1271 return false;
1274 S s;
1275 assert(!typeid(S).equals(&s, &s));
1278 class TypeInfo_Tuple : TypeInfo
1280 TypeInfo[] elements;
1282 override string toString() const
1284 string s = "(";
1285 foreach (i, element; elements)
1287 if (i)
1288 s ~= ',';
1289 s ~= element.toString();
1291 s ~= ")";
1292 return s;
1295 override bool opEquals(Object o)
1297 if (this is o)
1298 return true;
1300 auto t = cast(const TypeInfo_Tuple)o;
1301 if (t && elements.length == t.elements.length)
1303 for (size_t i = 0; i < elements.length; i++)
1305 if (elements[i] != t.elements[i])
1306 return false;
1308 return true;
1310 return false;
1313 override size_t getHash(in void* p) const
1315 assert(0);
1318 override bool equals(in void* p1, in void* p2) const
1320 assert(0);
1323 override int compare(in void* p1, in void* p2) const
1325 assert(0);
1328 override @property size_t tsize() nothrow pure const
1330 assert(0);
1333 override const(void)[] initializer() const @trusted
1335 assert(0);
1338 override void swap(void* p1, void* p2) const
1340 assert(0);
1343 override void destroy(void* p) const
1345 assert(0);
1348 override void postblit(void* p) const
1350 assert(0);
1353 override @property size_t talign() nothrow pure const
1355 assert(0);
1358 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1360 assert(0);
1364 class TypeInfo_Const : TypeInfo
1366 override string toString() const
1368 return cast(string) ("const(" ~ base.toString() ~ ")");
1371 //override bool opEquals(Object o) { return base.opEquals(o); }
1372 override bool opEquals(Object o)
1374 if (this is o)
1375 return true;
1377 if (typeid(this) != typeid(o))
1378 return false;
1380 auto t = cast(TypeInfo_Const)o;
1381 return base.opEquals(t.base);
1384 override size_t getHash(in void *p) const { return base.getHash(p); }
1385 override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); }
1386 override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); }
1387 override @property size_t tsize() nothrow pure const { return base.tsize; }
1388 override void swap(void *p1, void *p2) const { return base.swap(p1, p2); }
1390 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
1391 override @property uint flags() nothrow pure const { return base.flags; }
1393 override const(void)[] initializer() nothrow pure const
1395 return base.initializer();
1398 override @property size_t talign() nothrow pure const { return base.talign; }
1400 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1402 return base.argTypes(arg1, arg2);
1405 TypeInfo base;
1408 class TypeInfo_Invariant : TypeInfo_Const
1410 override string toString() const
1412 return cast(string) ("immutable(" ~ base.toString() ~ ")");
1416 class TypeInfo_Shared : TypeInfo_Const
1418 override string toString() const
1420 return cast(string) ("shared(" ~ base.toString() ~ ")");
1424 class TypeInfo_Inout : TypeInfo_Const
1426 override string toString() const
1428 return cast(string) ("inout(" ~ base.toString() ~ ")");
1433 ///////////////////////////////////////////////////////////////////////////////
1434 // ModuleInfo
1435 ///////////////////////////////////////////////////////////////////////////////
1438 enum
1440 MIctorstart = 0x1, // we've started constructing it
1441 MIctordone = 0x2, // finished construction
1442 MIstandalone = 0x4, // module ctor does not depend on other module
1443 // ctors being done first
1444 MItlsctor = 8,
1445 MItlsdtor = 0x10,
1446 MIctor = 0x20,
1447 MIdtor = 0x40,
1448 MIxgetMembers = 0x80,
1449 MIictor = 0x100,
1450 MIunitTest = 0x200,
1451 MIimportedModules = 0x400,
1452 MIlocalClasses = 0x800,
1453 MIname = 0x1000,
1457 struct ModuleInfo
1459 uint _flags;
1460 uint _index; // index into _moduleinfo_array[]
1462 version (all)
1464 deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
1465 void opAssign(in ModuleInfo m) { _flags = m._flags; _index = m._index; }
1467 else
1469 @disable this();
1470 @disable this(this) const;
1473 const:
1474 private void* addrOf(int flag) nothrow pure @nogc
1477 assert(flag >= MItlsctor && flag <= MIname);
1478 assert(!(flag & (flag - 1)) && !(flag & ~(flag - 1) << 1));
1480 body
1482 import core.stdc.string : strlen;
1484 void* p = cast(void*)&this + ModuleInfo.sizeof;
1486 if (flags & MItlsctor)
1488 if (flag == MItlsctor) return p;
1489 p += typeof(tlsctor).sizeof;
1491 if (flags & MItlsdtor)
1493 if (flag == MItlsdtor) return p;
1494 p += typeof(tlsdtor).sizeof;
1496 if (flags & MIctor)
1498 if (flag == MIctor) return p;
1499 p += typeof(ctor).sizeof;
1501 if (flags & MIdtor)
1503 if (flag == MIdtor) return p;
1504 p += typeof(dtor).sizeof;
1506 if (flags & MIxgetMembers)
1508 if (flag == MIxgetMembers) return p;
1509 p += typeof(xgetMembers).sizeof;
1511 if (flags & MIictor)
1513 if (flag == MIictor) return p;
1514 p += typeof(ictor).sizeof;
1516 if (flags & MIunitTest)
1518 if (flag == MIunitTest) return p;
1519 p += typeof(unitTest).sizeof;
1521 if (flags & MIimportedModules)
1523 if (flag == MIimportedModules) return p;
1524 p += size_t.sizeof + *cast(size_t*)p * typeof(importedModules[0]).sizeof;
1526 if (flags & MIlocalClasses)
1528 if (flag == MIlocalClasses) return p;
1529 p += size_t.sizeof + *cast(size_t*)p * typeof(localClasses[0]).sizeof;
1531 if (true || flags & MIname) // always available for now
1533 if (flag == MIname) return p;
1534 p += strlen(cast(immutable char*)p);
1536 assert(0);
1539 @property uint index() nothrow pure @nogc { return _index; }
1541 @property uint flags() nothrow pure @nogc { return _flags; }
1543 @property void function() tlsctor() nothrow pure @nogc
1545 return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null;
1548 @property void function() tlsdtor() nothrow pure @nogc
1550 return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null;
1553 @property void* xgetMembers() nothrow pure @nogc
1555 return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null;
1558 @property void function() ctor() nothrow pure @nogc
1560 return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null;
1563 @property void function() dtor() nothrow pure @nogc
1565 return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null;
1568 @property void function() ictor() nothrow pure @nogc
1570 return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null;
1573 @property void function() unitTest() nothrow pure @nogc
1575 return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null;
1578 @property immutable(ModuleInfo*)[] importedModules() nothrow pure @nogc
1580 if (flags & MIimportedModules)
1582 auto p = cast(size_t*)addrOf(MIimportedModules);
1583 return (cast(immutable(ModuleInfo*)*)(p + 1))[0 .. *p];
1585 return null;
1588 @property TypeInfo_Class[] localClasses() nothrow pure @nogc
1590 if (flags & MIlocalClasses)
1592 auto p = cast(size_t*)addrOf(MIlocalClasses);
1593 return (cast(TypeInfo_Class*)(p + 1))[0 .. *p];
1595 return null;
1598 @property string name() nothrow pure @nogc
1600 if (true || flags & MIname) // always available for now
1602 import core.stdc.string : strlen;
1604 auto p = cast(immutable char*)addrOf(MIname);
1605 return p[0 .. strlen(p)];
1607 // return null;
1610 static int opApply(scope int delegate(ModuleInfo*) dg)
1612 import core.internal.traits : externDFunc;
1613 alias moduleinfos_apply = externDFunc!("rt.minfo.moduleinfos_apply",
1614 int function(scope int delegate(immutable(ModuleInfo*))));
1615 // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
1616 return moduleinfos_apply(
1617 (immutable(ModuleInfo*)m) => dg(cast(ModuleInfo*)m));
1621 unittest
1623 ModuleInfo* m1;
1624 foreach (m; ModuleInfo)
1626 m1 = m;
1630 ///////////////////////////////////////////////////////////////////////////////
1631 // Throwable
1632 ///////////////////////////////////////////////////////////////////////////////
1636 * The base class of all thrown objects.
1638 * All thrown objects must inherit from Throwable. Class $(D Exception), which
1639 * derives from this class, represents the category of thrown objects that are
1640 * safe to catch and handle. In principle, one should not catch Throwable
1641 * objects that are not derived from $(D Exception), as they represent
1642 * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
1643 * when these errors are thrown, making it unsafe to continue execution after
1644 * catching them.
1646 class Throwable : Object
1648 interface TraceInfo
1650 int opApply(scope int delegate(ref const(char[]))) const;
1651 int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
1652 string toString() const;
1655 string msg; /// A message describing the error.
1658 * The _file name of the D source code corresponding with
1659 * where the error was thrown from.
1661 string file;
1663 * The _line number of the D source code corresponding with
1664 * where the error was thrown from.
1666 size_t line;
1669 * The stack trace of where the error happened. This is an opaque object
1670 * that can either be converted to $(D string), or iterated over with $(D
1671 * foreach) to extract the items in the stack trace (as strings).
1673 TraceInfo info;
1676 * A reference to the _next error in the list. This is used when a new
1677 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
1678 * caught $(D Exception) will be chained to the new $(D Throwable) via this
1679 * field.
1681 Throwable next;
1683 @nogc @safe pure nothrow this(string msg, Throwable next = null)
1685 this.msg = msg;
1686 this.next = next;
1687 //this.info = _d_traceContext();
1690 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable next = null)
1692 this(msg, next);
1693 this.file = file;
1694 this.line = line;
1695 //this.info = _d_traceContext();
1699 * Overrides $(D Object.toString) and returns the error message.
1700 * Internally this forwards to the $(D toString) overload that
1701 * takes a $(D_PARAM sink) delegate.
1703 override string toString()
1705 string s;
1706 toString((buf) { s ~= buf; });
1707 return s;
1711 * The Throwable hierarchy uses a toString overload that takes a
1712 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
1713 * performed in certain error situations. Override this $(D
1714 * toString) method to customize the error message.
1716 void toString(scope void delegate(in char[]) sink) const
1718 import core.internal.traits : externDFunc;
1719 alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString",
1720 char[] function(ulong, return char[], uint) @safe pure nothrow @nogc);
1722 char[20] tmpBuff = void;
1724 sink(typeid(this).name);
1725 sink("@"); sink(file);
1726 sink("("); sink(sizeToTempString(line, tmpBuff, 10)); sink(")");
1728 if (msg.length)
1730 sink(": "); sink(msg);
1732 if (info)
1736 sink("\n----------------");
1737 foreach (t; info)
1739 sink("\n"); sink(t);
1742 catch (Throwable)
1744 // ignore more errors
1752 * The base class of all errors that are safe to catch and handle.
1754 * In principle, only thrown objects derived from this class are safe to catch
1755 * inside a $(D catch) block. Thrown objects not derived from Exception
1756 * represent runtime errors that should not be caught, as certain runtime
1757 * guarantees may not hold, making it unsafe to continue program execution.
1759 class Exception : Throwable
1763 * Creates a new instance of Exception. The next parameter is used
1764 * internally and should always be $(D null) when passed by user code.
1765 * This constructor does not automatically throw the newly-created
1766 * Exception; the $(D throw) statement should be used for that purpose.
1768 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1770 super(msg, file, line, next);
1773 @nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
1775 super(msg, file, line, next);
1779 unittest
1782 auto e = new Exception("msg");
1783 assert(e.file == __FILE__);
1784 assert(e.line == __LINE__ - 2);
1785 assert(e.next is null);
1786 assert(e.msg == "msg");
1790 auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
1791 assert(e.file == "hello");
1792 assert(e.line == 42);
1793 assert(e.next !is null);
1794 assert(e.msg == "msg");
1798 auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
1799 assert(e.file == "hello");
1800 assert(e.line == 42);
1801 assert(e.next !is null);
1802 assert(e.msg == "msg");
1808 * The base class of all unrecoverable runtime errors.
1810 * This represents the category of $(D Throwable) objects that are $(B not)
1811 * safe to catch and handle. In principle, one should not catch Error
1812 * objects, as they represent unrecoverable runtime errors.
1813 * Certain runtime guarantees may fail to hold when these errors are
1814 * thrown, making it unsafe to continue execution after catching them.
1816 class Error : Throwable
1819 * Creates a new instance of Error. The next parameter is used
1820 * internally and should always be $(D null) when passed by user code.
1821 * This constructor does not automatically throw the newly-created
1822 * Error; the $(D throw) statement should be used for that purpose.
1824 @nogc @safe pure nothrow this(string msg, Throwable next = null)
1826 super(msg, next);
1827 bypassedException = null;
1830 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable next = null)
1832 super(msg, file, line, next);
1833 bypassedException = null;
1836 /** The first $(D Exception) which was bypassed when this Error was thrown,
1837 or $(D null) if no $(D Exception)s were pending. */
1838 Throwable bypassedException;
1841 unittest
1844 auto e = new Error("msg");
1845 assert(e.file is null);
1846 assert(e.line == 0);
1847 assert(e.next is null);
1848 assert(e.msg == "msg");
1849 assert(e.bypassedException is null);
1853 auto e = new Error("msg", new Exception("It's an Exception!"));
1854 assert(e.file is null);
1855 assert(e.line == 0);
1856 assert(e.next !is null);
1857 assert(e.msg == "msg");
1858 assert(e.bypassedException is null);
1862 auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
1863 assert(e.file == "hello");
1864 assert(e.line == 42);
1865 assert(e.next !is null);
1866 assert(e.msg == "msg");
1867 assert(e.bypassedException is null);
1871 /* Used in Exception Handling LSDA tables to 'wrap' C++ type info
1872 * so it can be distinguished from D TypeInfo
1874 class __cpp_type_info_ptr
1876 void* ptr; // opaque pointer to C++ RTTI type info
1879 extern (C)
1881 // from druntime/src/rt/aaA.d
1883 // size_t _aaLen(in void* p) pure nothrow @nogc;
1884 private void* _aaGetY(void** paa, const TypeInfo_AssociativeArray ti, in size_t valuesize, in void* pkey) pure nothrow;
1885 // inout(void)* _aaGetRvalueX(inout void* p, in TypeInfo keyti, in size_t valuesize, in void* pkey);
1886 inout(void)[] _aaValues(inout void* p, in size_t keysize, in size_t valuesize, const TypeInfo tiValArray) pure nothrow;
1887 inout(void)[] _aaKeys(inout void* p, in size_t keysize, const TypeInfo tiKeyArray) pure nothrow;
1888 void* _aaRehash(void** pp, in TypeInfo keyti) pure nothrow;
1889 void _aaClear(void* p) pure nothrow;
1891 // alias _dg_t = extern(D) int delegate(void*);
1892 // int _aaApply(void* aa, size_t keysize, _dg_t dg);
1894 // alias _dg2_t = extern(D) int delegate(void*, void*);
1895 // int _aaApply2(void* aa, size_t keysize, _dg2_t dg);
1897 private struct AARange { void* impl; size_t idx; }
1898 AARange _aaRange(void* aa) pure nothrow @nogc;
1899 bool _aaRangeEmpty(AARange r) pure nothrow @nogc;
1900 void* _aaRangeFrontKey(AARange r) pure nothrow @nogc;
1901 void* _aaRangeFrontValue(AARange r) pure nothrow @nogc;
1902 void _aaRangePopFront(ref AARange r) pure nothrow @nogc;
1904 int _aaEqual(in TypeInfo tiRaw, in void* e1, in void* e2);
1905 hash_t _aaGetHash(in void* aa, in TypeInfo tiRaw) nothrow;
1908 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
1909 This is a typesystem hole, however this is existing hole.
1910 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
1911 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
1913 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure;
1916 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
1918 return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
1921 alias AssociativeArray(Key, Value) = Value[Key];
1923 void clear(T : Value[Key], Value, Key)(T aa)
1925 _aaClear(*cast(void **) &aa);
1928 void clear(T : Value[Key], Value, Key)(T* aa)
1930 _aaClear(*cast(void **) aa);
1933 T rehash(T : Value[Key], Value, Key)(T aa)
1935 _aaRehash(cast(void**)&aa, typeid(Value[Key]));
1936 return aa;
1939 T rehash(T : Value[Key], Value, Key)(T* aa)
1941 _aaRehash(cast(void**)aa, typeid(Value[Key]));
1942 return *aa;
1945 T rehash(T : shared Value[Key], Value, Key)(T aa)
1947 _aaRehash(cast(void**)&aa, typeid(Value[Key]));
1948 return aa;
1951 T rehash(T : shared Value[Key], Value, Key)(T* aa)
1953 _aaRehash(cast(void**)aa, typeid(Value[Key]));
1954 return *aa;
1957 V[K] dup(T : V[K], K, V)(T aa)
1959 //pragma(msg, "K = ", K, ", V = ", V);
1961 // Bug10720 - check whether V is copyable
1962 static assert(is(typeof({ V v = aa[K.init]; })),
1963 "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");
1965 V[K] result;
1967 //foreach (k, ref v; aa)
1968 // result[k] = v; // Bug13701 - won't work if V is not mutable
1970 ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow
1972 import core.stdc.string : memcpy;
1974 void* pv = _aaGetY(cast(void**)&result, typeid(V[K]), V.sizeof, &k);
1975 memcpy(pv, &v, V.sizeof);
1976 return *cast(V*)pv;
1979 if (auto postblit = _getPostblit!V())
1981 foreach (k, ref v; aa)
1982 postblit(duplicateElem(k, v));
1984 else
1986 foreach (k, ref v; aa)
1987 duplicateElem(k, v);
1990 return result;
1993 V[K] dup(T : V[K], K, V)(T* aa)
1995 return (*aa).dup;
1998 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc
2000 import core.internal.traits : substInout;
2002 static struct Result
2004 AARange r;
2006 pure nothrow @nogc:
2007 @property bool empty() { return _aaRangeEmpty(r); }
2008 @property ref front() { return *cast(substInout!K*)_aaRangeFrontKey(r); }
2009 void popFront() { _aaRangePopFront(r); }
2010 @property Result save() { return this; }
2013 return Result(_aaRange(cast(void*)aa));
2016 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
2018 return (*aa).byKey();
2021 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc
2023 import core.internal.traits : substInout;
2025 static struct Result
2027 AARange r;
2029 pure nothrow @nogc:
2030 @property bool empty() { return _aaRangeEmpty(r); }
2031 @property ref front() { return *cast(substInout!V*)_aaRangeFrontValue(r); }
2032 void popFront() { _aaRangePopFront(r); }
2033 @property Result save() { return this; }
2036 return Result(_aaRange(cast(void*)aa));
2039 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
2041 return (*aa).byValue();
2044 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc
2046 import core.internal.traits : substInout;
2048 static struct Result
2050 AARange r;
2052 pure nothrow @nogc:
2053 @property bool empty() { return _aaRangeEmpty(r); }
2054 @property auto front() @trusted
2056 static struct Pair
2058 // We save the pointers here so that the Pair we return
2059 // won't mutate when Result.popFront is called afterwards.
2060 private void* keyp;
2061 private void* valp;
2063 @property ref key() inout { return *cast(substInout!K*)keyp; }
2064 @property ref value() inout { return *cast(substInout!V*)valp; }
2066 return Pair(_aaRangeFrontKey(r),
2067 _aaRangeFrontValue(r));
2069 void popFront() { _aaRangePopFront(r); }
2070 @property Result save() { return this; }
2073 return Result(_aaRange(cast(void*)aa));
2076 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
2078 return (*aa).byKeyValue();
2081 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
2083 auto a = cast(void[])_aaKeys(cast(inout(void)*)aa, Key.sizeof, typeid(Key[]));
2084 auto res = *cast(Key[]*)&a;
2085 _doPostblit(res);
2086 return res;
2089 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
2091 return (*aa).keys;
2094 Value[] values(T : Value[Key], Value, Key)(T aa) @property
2096 auto a = cast(void[])_aaValues(cast(inout(void)*)aa, Key.sizeof, Value.sizeof, typeid(Value[]));
2097 auto res = *cast(Value[]*)&a;
2098 _doPostblit(res);
2099 return res;
2102 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
2104 return (*aa).values;
2107 unittest
2109 static struct T
2111 static size_t count;
2112 this(this) { ++count; }
2114 T[int] aa;
2115 T t;
2116 aa[0] = t;
2117 aa[1] = t;
2118 assert(T.count == 2);
2119 auto vals = aa.values;
2120 assert(vals.length == 2);
2121 assert(T.count == 4);
2123 T.count = 0;
2124 int[T] aa2;
2125 aa2[t] = 0;
2126 assert(T.count == 1);
2127 aa2[t] = 1;
2128 assert(T.count == 1);
2129 auto keys = aa2.keys;
2130 assert(keys.length == 1);
2131 assert(T.count == 2);
2134 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)
2136 auto p = key in aa;
2137 return p ? *p : defaultValue;
2140 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
2142 return (*aa).get(key, defaultValue);
2145 pure nothrow unittest
2147 int[int] a;
2148 foreach (i; a.byKey)
2150 assert(false);
2152 foreach (i; a.byValue)
2154 assert(false);
2158 pure /*nothrow */ unittest
2160 auto a = [ 1:"one", 2:"two", 3:"three" ];
2161 auto b = a.dup;
2162 assert(b == [ 1:"one", 2:"two", 3:"three" ]);
2164 int[] c;
2165 foreach (k; a.byKey)
2167 c ~= k;
2170 assert(c.length == 3);
2171 assert(c[0] == 1 || c[1] == 1 || c[2] == 1);
2172 assert(c[0] == 2 || c[1] == 2 || c[2] == 2);
2173 assert(c[0] == 3 || c[1] == 3 || c[2] == 3);
2176 pure nothrow unittest
2178 // test for bug 5925
2179 const a = [4:0];
2180 const b = [4:0];
2181 assert(a == b);
2184 pure nothrow unittest
2186 // test for bug 9052
2187 static struct Json {
2188 Json[string] aa;
2189 void opAssign(Json) {}
2190 size_t length() const { return aa.length; }
2191 // This length() instantiates AssociativeArray!(string, const(Json)) to call AA.length(), and
2192 // inside ref Slot opAssign(Slot p); (which is automatically generated by compiler in Slot),
2193 // this.value = p.value would actually fail, because both side types of the assignment
2194 // are const(Json).
2198 pure nothrow unittest
2200 // test for bug 8583: ensure Slot and aaA are on the same page wrt value alignment
2201 string[byte] aa0 = [0: "zero"];
2202 string[uint[3]] aa1 = [[1,2,3]: "onetwothree"];
2203 ushort[uint[3]] aa2 = [[9,8,7]: 987];
2204 ushort[uint[4]] aa3 = [[1,2,3,4]: 1234];
2205 string[uint[5]] aa4 = [[1,2,3,4,5]: "onetwothreefourfive"];
2207 assert(aa0.byValue.front == "zero");
2208 assert(aa1.byValue.front == "onetwothree");
2209 assert(aa2.byValue.front == 987);
2210 assert(aa3.byValue.front == 1234);
2211 assert(aa4.byValue.front == "onetwothreefourfive");
2214 pure nothrow unittest
2216 // test for bug 10720
2217 static struct NC
2219 @disable this(this) { }
2222 NC[string] aa;
2223 static assert(!is(aa.nonExistingField));
2226 pure nothrow unittest
2228 // bug 5842
2229 string[string] test = null;
2230 test["test1"] = "test1";
2231 test.remove("test1");
2232 test.rehash;
2233 test["test3"] = "test3"; // causes divide by zero if rehash broke the AA
2236 pure nothrow unittest
2238 string[] keys = ["a", "b", "c", "d", "e", "f"];
2240 // Test forward range capabilities of byKey
2242 int[string] aa;
2243 foreach (key; keys)
2244 aa[key] = 0;
2246 auto keyRange = aa.byKey();
2247 auto savedKeyRange = keyRange.save;
2249 // Consume key range once
2250 size_t keyCount = 0;
2251 while (!keyRange.empty)
2253 aa[keyRange.front]++;
2254 keyCount++;
2255 keyRange.popFront();
2258 foreach (key; keys)
2260 assert(aa[key] == 1);
2262 assert(keyCount == keys.length);
2264 // Verify it's possible to iterate the range the second time
2265 keyCount = 0;
2266 while (!savedKeyRange.empty)
2268 aa[savedKeyRange.front]++;
2269 keyCount++;
2270 savedKeyRange.popFront();
2273 foreach (key; keys)
2275 assert(aa[key] == 2);
2277 assert(keyCount == keys.length);
2280 // Test forward range capabilities of byValue
2282 size_t[string] aa;
2283 foreach (i; 0 .. keys.length)
2285 aa[keys[i]] = i;
2288 auto valRange = aa.byValue();
2289 auto savedValRange = valRange.save;
2291 // Consume value range once
2292 int[] hasSeen;
2293 hasSeen.length = keys.length;
2294 while (!valRange.empty)
2296 assert(hasSeen[valRange.front] == 0);
2297 hasSeen[valRange.front]++;
2298 valRange.popFront();
2301 foreach (sawValue; hasSeen) { assert(sawValue == 1); }
2303 // Verify it's possible to iterate the range the second time
2304 hasSeen = null;
2305 hasSeen.length = keys.length;
2306 while (!savedValRange.empty)
2308 assert(!hasSeen[savedValRange.front]);
2309 hasSeen[savedValRange.front] = true;
2310 savedValRange.popFront();
2313 foreach (sawValue; hasSeen) { assert(sawValue); }
2317 pure nothrow unittest
2319 // expanded test for 5842: increase AA size past the point where the AA
2320 // stops using binit, in order to test another code path in rehash.
2321 int[int] aa;
2322 foreach (int i; 0 .. 32)
2323 aa[i] = i;
2324 foreach (int i; 0 .. 32)
2325 aa.remove(i);
2326 aa.rehash;
2327 aa[1] = 1;
2330 pure nothrow unittest
2332 // bug 13078
2333 shared string[][string] map;
2334 map.rehash;
2337 pure nothrow unittest
2339 // bug 11761: test forward range functionality
2340 auto aa = ["a": 1];
2342 void testFwdRange(R, T)(R fwdRange, T testValue)
2344 assert(!fwdRange.empty);
2345 assert(fwdRange.front == testValue);
2346 static assert(is(typeof(fwdRange.save) == typeof(fwdRange)));
2348 auto saved = fwdRange.save;
2349 fwdRange.popFront();
2350 assert(fwdRange.empty);
2352 assert(!saved.empty);
2353 assert(saved.front == testValue);
2354 saved.popFront();
2355 assert(saved.empty);
2358 testFwdRange(aa.byKey, "a");
2359 testFwdRange(aa.byValue, 1);
2360 //testFwdRange(aa.byPair, tuple("a", 1));
2363 unittest
2365 // Issue 9119
2366 int[string] aa;
2367 assert(aa.byKeyValue.empty);
2369 aa["a"] = 1;
2370 aa["b"] = 2;
2371 aa["c"] = 3;
2373 auto pairs = aa.byKeyValue;
2375 auto savedPairs = pairs.save;
2376 size_t count = 0;
2377 while (!pairs.empty)
2379 assert(pairs.front.key in aa);
2380 assert(pairs.front.value == aa[pairs.front.key]);
2381 count++;
2382 pairs.popFront();
2384 assert(count == aa.length);
2386 // Verify that saved range can iterate over the AA again
2387 count = 0;
2388 while (!savedPairs.empty)
2390 assert(savedPairs.front.key in aa);
2391 assert(savedPairs.front.value == aa[savedPairs.front.key]);
2392 count++;
2393 savedPairs.popFront();
2395 assert(count == aa.length);
2398 unittest
2400 // Verify iteration with const.
2401 auto aa = [1:2, 3:4];
2402 foreach (const t; aa.byKeyValue)
2404 auto k = t.key;
2405 auto v = t.value;
2409 unittest
2411 // test for bug 14626
2412 static struct S
2414 string[string] aa;
2415 inout(string) key() inout { return aa.byKey().front; }
2416 inout(string) val() inout { return aa.byValue().front; }
2417 auto keyval() inout { return aa.byKeyValue().front; }
2420 S s = S(["a":"b"]);
2421 assert(s.key() == "a");
2422 assert(s.val() == "b");
2423 assert(s.keyval().key == "a");
2424 assert(s.keyval().value == "b");
2426 void testInoutKeyVal(inout(string) key)
2428 inout(string)[typeof(key)] aa;
2430 foreach (i; aa.byKey()) {}
2431 foreach (i; aa.byValue()) {}
2432 foreach (i; aa.byKeyValue()) {}
2435 const int[int] caa;
2436 static assert(is(typeof(caa.byValue().front) == const int));
2439 private void _destructRecurse(S)(ref S s)
2440 if (is(S == struct))
2442 static if (__traits(hasMember, S, "__xdtor") &&
2443 // Bugzilla 14746: Check that it's the exact member of S.
2444 __traits(isSame, S, __traits(parent, s.__xdtor)))
2445 s.__xdtor();
2448 private void _destructRecurse(E, size_t n)(ref E[n] arr)
2450 import core.internal.traits : hasElaborateDestructor;
2452 static if (hasElaborateDestructor!E)
2454 foreach_reverse (ref elem; arr)
2455 _destructRecurse(elem);
2459 // Public and explicitly undocumented
2460 void _postblitRecurse(S)(ref S s)
2461 if (is(S == struct))
2463 static if (__traits(hasMember, S, "__xpostblit") &&
2464 // Bugzilla 14746: Check that it's the exact member of S.
2465 __traits(isSame, S, __traits(parent, s.__xpostblit)))
2466 s.__xpostblit();
2469 // Ditto
2470 void _postblitRecurse(E, size_t n)(ref E[n] arr)
2472 import core.internal.traits : hasElaborateCopyConstructor;
2474 static if (hasElaborateCopyConstructor!E)
2476 size_t i;
2477 scope(failure)
2479 for (; i != 0; --i)
2481 _destructRecurse(arr[i - 1]); // What to do if this throws?
2485 for (i = 0; i < arr.length; ++i)
2486 _postblitRecurse(arr[i]);
2490 // Test destruction/postblit order
2491 @safe nothrow pure unittest
2493 string[] order;
2495 struct InnerTop
2497 ~this() @safe nothrow pure
2499 order ~= "destroy inner top";
2502 this(this) @safe nothrow pure
2504 order ~= "copy inner top";
2508 struct InnerMiddle {}
2510 version (none) // https://issues.dlang.org/show_bug.cgi?id=14242
2511 struct InnerElement
2513 static char counter = '1';
2515 ~this() @safe nothrow pure
2517 order ~= "destroy inner element #" ~ counter++;
2520 this(this) @safe nothrow pure
2522 order ~= "copy inner element #" ~ counter++;
2526 struct InnerBottom
2528 ~this() @safe nothrow pure
2530 order ~= "destroy inner bottom";
2533 this(this) @safe nothrow pure
2535 order ~= "copy inner bottom";
2539 struct S
2541 char[] s;
2542 InnerTop top;
2543 InnerMiddle middle;
2544 version (none) InnerElement[3] array; // https://issues.dlang.org/show_bug.cgi?id=14242
2545 int a;
2546 InnerBottom bottom;
2547 ~this() @safe nothrow pure { order ~= "destroy outer"; }
2548 this(this) @safe nothrow pure { order ~= "copy outer"; }
2551 string[] destructRecurseOrder;
2553 S s;
2554 _destructRecurse(s);
2555 destructRecurseOrder = order;
2556 order = null;
2559 assert(order.length);
2560 assert(destructRecurseOrder == order);
2561 order = null;
2563 S s;
2564 _postblitRecurse(s);
2565 assert(order.length);
2566 auto postblitRecurseOrder = order;
2567 order = null;
2568 S s2 = s;
2569 assert(order.length);
2570 assert(postblitRecurseOrder == order);
2573 // Test static struct
2574 nothrow @safe @nogc unittest
2576 static int i = 0;
2577 static struct S { ~this() nothrow @safe @nogc { i = 42; } }
2578 S s;
2579 _destructRecurse(s);
2580 assert(i == 42);
2583 unittest
2585 // Bugzilla 14746
2586 static struct HasDtor
2588 ~this() { assert(0); }
2590 static struct Owner
2592 HasDtor* ptr;
2593 alias ptr this;
2596 Owner o;
2597 assert(o.ptr is null);
2598 destroy(o); // must not reach in HasDtor.__dtor()
2601 unittest
2603 // Bugzilla 14746
2604 static struct HasPostblit
2606 this(this) { assert(0); }
2608 static struct Owner
2610 HasPostblit* ptr;
2611 alias ptr this;
2614 Owner o;
2615 assert(o.ptr is null);
2616 _postblitRecurse(o); // must not reach in HasPostblit.__postblit()
2619 // Test handling of fixed-length arrays
2620 // Separate from first test because of https://issues.dlang.org/show_bug.cgi?id=14242
2621 unittest
2623 string[] order;
2625 struct S
2627 char id;
2629 this(this)
2631 order ~= "copy #" ~ id;
2634 ~this()
2636 order ~= "destroy #" ~ id;
2640 string[] destructRecurseOrder;
2642 S[3] arr = [S('1'), S('2'), S('3')];
2643 _destructRecurse(arr);
2644 destructRecurseOrder = order;
2645 order = null;
2647 assert(order.length);
2648 assert(destructRecurseOrder == order);
2649 order = null;
2651 S[3] arr = [S('1'), S('2'), S('3')];
2652 _postblitRecurse(arr);
2653 assert(order.length);
2654 auto postblitRecurseOrder = order;
2655 order = null;
2657 auto arrCopy = arr;
2658 assert(order.length);
2659 assert(postblitRecurseOrder == order);
2662 // Test handling of failed postblit
2663 // Not nothrow or @safe because of https://issues.dlang.org/show_bug.cgi?id=14242
2664 /+ nothrow @safe +/ unittest
2666 static class FailedPostblitException : Exception { this() nothrow @safe { super(null); } }
2667 static string[] order;
2668 static struct Inner
2670 char id;
2672 @safe:
2673 this(this)
2675 order ~= "copy inner #" ~ id;
2676 if (id == '2')
2677 throw new FailedPostblitException();
2680 ~this() nothrow
2682 order ~= "destroy inner #" ~ id;
2686 static struct Outer
2688 Inner inner1, inner2, inner3;
2690 nothrow @safe:
2691 this(char first, char second, char third)
2693 inner1 = Inner(first);
2694 inner2 = Inner(second);
2695 inner3 = Inner(third);
2698 this(this)
2700 order ~= "copy outer";
2703 ~this()
2705 order ~= "destroy outer";
2709 auto outer = Outer('1', '2', '3');
2711 try _postblitRecurse(outer);
2712 catch (FailedPostblitException) {}
2713 catch (Exception) assert(false);
2715 auto postblitRecurseOrder = order;
2716 order = null;
2718 try auto copy = outer;
2719 catch (FailedPostblitException) {}
2720 catch (Exception) assert(false);
2722 assert(postblitRecurseOrder == order);
2723 order = null;
2725 Outer[3] arr = [Outer('1', '1', '1'), Outer('1', '2', '3'), Outer('3', '3', '3')];
2727 try _postblitRecurse(arr);
2728 catch (FailedPostblitException) {}
2729 catch (Exception) assert(false);
2731 postblitRecurseOrder = order;
2732 order = null;
2734 try auto arrCopy = arr;
2735 catch (FailedPostblitException) {}
2736 catch (Exception) assert(false);
2738 assert(postblitRecurseOrder == order);
2742 Destroys the given object and puts it in an invalid state. It's used to
2743 _destroy an object so that any cleanup which its destructor or finalizer
2744 does is done and so that it no longer references any other objects. It does
2745 $(I not) initiate a GC cycle or free any GC memory.
2747 void destroy(T)(T obj) if (is(T == class))
2749 rt_finalize(cast(void*)obj);
2752 /// ditto
2753 void destroy(T)(T obj) if (is(T == interface))
2755 destroy(cast(Object)obj);
2758 version (unittest) unittest
2760 interface I { }
2762 class A: I { string s = "A"; this() {} }
2763 auto a = new A, b = new A;
2764 a.s = b.s = "asd";
2765 destroy(a);
2766 assert(a.s == "A");
2768 I i = b;
2769 destroy(i);
2770 assert(b.s == "A");
2773 static bool destroyed = false;
2774 class B: I
2776 string s = "B";
2777 this() {}
2778 ~this()
2780 destroyed = true;
2783 auto a = new B, b = new B;
2784 a.s = b.s = "asd";
2785 destroy(a);
2786 assert(destroyed);
2787 assert(a.s == "B");
2789 destroyed = false;
2790 I i = b;
2791 destroy(i);
2792 assert(destroyed);
2793 assert(b.s == "B");
2795 // this test is invalid now that the default ctor is not run after clearing
2796 version (none)
2798 class C
2800 string s;
2801 this()
2803 s = "C";
2806 auto a = new C;
2807 a.s = "asd";
2808 destroy(a);
2809 assert(a.s == "C");
2813 /// ditto
2814 void destroy(T)(ref T obj) if (is(T == struct))
2816 _destructRecurse(obj);
2817 () @trusted {
2818 auto buf = (cast(ubyte*) &obj)[0 .. T.sizeof];
2819 auto init = cast(ubyte[])typeid(T).initializer();
2820 if (init.ptr is null) // null ptr means initialize to 0s
2821 buf[] = 0;
2822 else
2823 buf[] = init[];
2824 } ();
2827 version (unittest) nothrow @safe @nogc unittest
2830 struct A { string s = "A"; }
2831 A a;
2832 a.s = "asd";
2833 destroy(a);
2834 assert(a.s == "A");
2837 static int destroyed = 0;
2838 struct C
2840 string s = "C";
2841 ~this() nothrow @safe @nogc
2843 destroyed ++;
2847 struct B
2849 C c;
2850 string s = "B";
2851 ~this() nothrow @safe @nogc
2853 destroyed ++;
2856 B a;
2857 a.s = "asd";
2858 a.c.s = "jkl";
2859 destroy(a);
2860 assert(destroyed == 2);
2861 assert(a.s == "B");
2862 assert(a.c.s == "C" );
2866 /// ditto
2867 void destroy(T : U[n], U, size_t n)(ref T obj) if (!is(T == struct))
2869 foreach_reverse (ref e; obj[])
2870 destroy(e);
2873 version (unittest) unittest
2875 int[2] a;
2876 a[0] = 1;
2877 a[1] = 2;
2878 destroy(a);
2879 assert(a == [ 0, 0 ]);
2882 unittest
2884 static struct vec2f {
2885 float[2] values;
2886 alias values this;
2889 vec2f v;
2890 destroy!vec2f(v);
2893 unittest
2895 // Bugzilla 15009
2896 static string op;
2897 static struct S
2899 int x;
2900 this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; }
2901 this(this) { op ~= "P" ~ cast(char)('0'+x); }
2902 ~this() { op ~= "D" ~ cast(char)('0'+x); }
2906 S[2] a1 = [S(1), S(2)];
2907 op = "";
2909 assert(op == "D2D1"); // built-in scope destruction
2911 S[2] a1 = [S(1), S(2)];
2912 op = "";
2913 destroy(a1);
2914 assert(op == "D2D1"); // consistent with built-in behavior
2918 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
2919 op = "";
2921 assert(op == "D4D3D2D1");
2923 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
2924 op = "";
2925 destroy(a2);
2926 assert(op == "D4D3D2D1", op);
2930 /// ditto
2931 void destroy(T)(ref T obj)
2932 if (!is(T == struct) && !is(T == interface) && !is(T == class) && !_isStaticArray!T)
2934 obj = T.init;
2937 template _isStaticArray(T : U[N], U, size_t N)
2939 enum bool _isStaticArray = true;
2942 template _isStaticArray(T)
2944 enum bool _isStaticArray = false;
2947 version (unittest) unittest
2950 int a = 42;
2951 destroy(a);
2952 assert(a == 0);
2955 float a = 42;
2956 destroy(a);
2957 assert(isnan(a));
2961 version (unittest)
2963 private bool isnan(float x)
2965 return x != x;
2969 private
2971 extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow;
2972 extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void *arrptr) pure nothrow;
2976 * (Property) Gets the current _capacity of a slice. The _capacity is the size
2977 * that the slice can grow to before the underlying array must be
2978 * reallocated or extended.
2980 * If an append must reallocate a slice with no possibility of extension, then
2981 * `0` is returned. This happens when the slice references a static array, or
2982 * if another slice references elements past the end of the current slice.
2984 * Note: The _capacity of a slice may be impacted by operations on other slices.
2986 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
2988 return _d_arraysetcapacity(typeid(T[]), 0, cast(void *)&arr);
2991 @safe unittest
2993 //Static array slice: no capacity
2994 int[4] sarray = [1, 2, 3, 4];
2995 int[] slice = sarray[];
2996 assert(sarray.capacity == 0);
2997 //Appending to slice will reallocate to a new array
2998 slice ~= 5;
2999 assert(slice.capacity >= 5);
3001 //Dynamic array slices
3002 int[] a = [1, 2, 3, 4];
3003 int[] b = a[1 .. $];
3004 int[] c = a[1 .. $ - 1];
3005 debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation
3007 assert(a.capacity != 0);
3008 assert(a.capacity == b.capacity + 1); //both a and b share the same tail
3010 assert(c.capacity == 0); //an append to c must relocate c.
3014 * Reserves capacity for a slice. The capacity is the size
3015 * that the slice can grow to before the underlying array must be
3016 * reallocated or extended.
3018 * Returns: The new capacity of the array (which may be larger than
3019 * the requested capacity).
3021 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
3023 return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void *)&arr);
3026 unittest
3028 //Static array slice: no capacity. Reserve relocates.
3029 int[4] sarray = [1, 2, 3, 4];
3030 int[] slice = sarray[];
3031 auto u = slice.reserve(8);
3032 assert(u >= 8);
3033 assert(sarray.ptr !is slice.ptr);
3034 assert(slice.capacity == u);
3036 //Dynamic array slices
3037 int[] a = [1, 2, 3, 4];
3038 a.reserve(8); //prepare a for appending 4 more items
3039 auto p = a.ptr;
3040 u = a.capacity;
3041 a ~= [5, 6, 7, 8];
3042 assert(p == a.ptr); //a should not have been reallocated
3043 assert(u == a.capacity); //a should not have been extended
3046 // Issue 6646: should be possible to use array.reserve from SafeD.
3047 @safe unittest
3049 int[] a;
3050 a.reserve(10);
3054 * Assume that it is safe to append to this array. Appends made to this array
3055 * after calling this function may append in place, even if the array was a
3056 * slice of a larger array to begin with.
3058 * Use this only when it is certain there are no elements in use beyond the
3059 * array in the memory block. If there are, those elements will be
3060 * overwritten by appending to this array.
3062 * Warning: Calling this function, and then using references to data located after the
3063 * given array results in undefined behavior.
3065 * Returns:
3066 * The input is returned.
3068 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow
3070 _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
3071 return arr;
3074 unittest
3076 int[] a = [1, 2, 3, 4];
3078 // Without assumeSafeAppend. Appending relocates.
3079 int[] b = a [0 .. 3];
3080 b ~= 5;
3081 assert(a.ptr != b.ptr);
3083 debug(SENTINEL) {} else
3085 // With assumeSafeAppend. Appending overwrites.
3086 int[] c = a [0 .. 3];
3087 c.assumeSafeAppend() ~= 5;
3088 assert(a.ptr == c.ptr);
3092 unittest
3094 int[] arr;
3095 auto newcap = arr.reserve(2000);
3096 assert(newcap >= 2000);
3097 assert(newcap == arr.capacity);
3098 auto ptr = arr.ptr;
3099 foreach (i; 0..2000)
3100 arr ~= i;
3101 assert(ptr == arr.ptr);
3102 arr = arr[0..1];
3103 arr.assumeSafeAppend();
3104 arr ~= 5;
3105 assert(ptr == arr.ptr);
3108 unittest
3110 int[] arr = [1, 2, 3];
3111 void foo(ref int[] i)
3113 i ~= 5;
3115 arr = arr[0 .. 2];
3116 foo(assumeSafeAppend(arr)); //pass by ref
3117 assert(arr[]==[1, 2, 5]);
3118 arr = arr[0 .. 1].assumeSafeAppend(); //pass by value
3121 // https://issues.dlang.org/show_bug.cgi?id=10574
3122 unittest
3124 int[] a;
3125 immutable(int[]) b;
3126 auto a2 = &assumeSafeAppend(a);
3127 auto b2 = &assumeSafeAppend(b);
3128 auto a3 = assumeSafeAppend(a[]);
3129 auto b3 = assumeSafeAppend(b[]);
3130 assert(is(typeof(*a2) == int[]));
3131 assert(is(typeof(*b2) == immutable(int[])));
3132 assert(is(typeof(a3) == int[]));
3133 assert(is(typeof(b3) == immutable(int[])));
3136 version (none)
3138 // enforce() copied from Phobos std.contracts for destroy(), left out until
3139 // we decide whether to use it.
3142 T _enforce(T, string file = __FILE__, int line = __LINE__)
3143 (T value, lazy const(char)[] msg = null)
3145 if (!value) bailOut(file, line, msg);
3146 return value;
3149 T _enforce(T, string file = __FILE__, int line = __LINE__)
3150 (T value, scope void delegate() dg)
3152 if (!value) dg();
3153 return value;
3156 T _enforce(T)(T value, lazy Exception ex)
3158 if (!value) throw ex();
3159 return value;
3162 private void _bailOut(string file, int line, in char[] msg)
3164 char[21] buf;
3165 throw new Exception(cast(string)(file ~ "(" ~ ulongToString(buf[], line) ~ "): " ~ (msg ? msg : "Enforcement failed")));
3170 /***************************************
3171 * Helper function used to see if two containers of different
3172 * types have the same contents in the same sequence.
3175 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
3177 if (a1.length != a2.length)
3178 return false;
3180 // This is function is used as a compiler intrinsic and explicitly written
3181 // in a lowered flavor to use as few CTFE instructions as possible.
3182 size_t idx = 0;
3183 immutable length = a1.length;
3185 for (;idx < length;++idx)
3187 if (a1[idx] != a2[idx])
3188 return false;
3190 return true;
3194 Calculates the hash value of $(D arg) with $(D seed) initial value.
3195 The result may not be equal to `typeid(T).getHash(&arg)`.
3196 The $(D seed) value may be used for hash chaining:
3197 ----
3198 struct Test
3200 int a;
3201 string b;
3202 MyObject c;
3204 size_t toHash() const @safe pure nothrow
3206 size_t hash = a.hashOf();
3207 hash = b.hashOf(hash);
3208 size_t h1 = c.myMegaHash();
3209 hash = h1.hashOf(hash); //Mix two hash values
3210 return hash;
3213 ----
3215 size_t hashOf(T)(auto ref T arg, size_t seed = 0)
3217 import core.internal.hash;
3218 return core.internal.hash.hashOf(arg, seed);
3221 unittest
3223 // Issue # 16654 / 16764
3224 auto a = [1];
3225 auto b = a.dup;
3226 assert(hashOf(a) == hashOf(b));
3229 bool _xopEquals(in void*, in void*)
3231 throw new Error("TypeInfo.equals is not implemented");
3234 bool _xopCmp(in void*, in void*)
3236 throw new Error("TypeInfo.compare is not implemented");
3239 void __ctfeWrite(const string s) @nogc @safe pure nothrow {}
3241 /******************************************
3242 * Create RTInfo for type T
3245 template RTInfo(T)
3247 enum RTInfo = null;
3250 // lhs == rhs lowers to __equals(lhs, rhs) for dynamic arrays
3251 bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
3253 import core.internal.traits : Unqual;
3254 alias U1 = Unqual!T1;
3255 alias U2 = Unqual!T2;
3257 static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
3258 static @trusted R trustedCast(R, S)(S[] r) { return cast(R) r; }
3260 if (lhs.length != rhs.length)
3261 return false;
3263 if (lhs.length == 0 && rhs.length == 0)
3264 return true;
3266 static if (is(U1 == void) && is(U2 == void))
3268 return __equals(trustedCast!(ubyte[])(lhs), trustedCast!(ubyte[])(rhs));
3270 else static if (is(U1 == void))
3272 return __equals(trustedCast!(ubyte[])(lhs), rhs);
3274 else static if (is(U2 == void))
3276 return __equals(lhs, trustedCast!(ubyte[])(rhs));
3278 else static if (!is(U1 == U2))
3280 // This should replace src/object.d _ArrayEq which
3281 // compares arrays of different types such as long & int,
3282 // char & wchar.
3283 // Compiler lowers to __ArrayEq in dmd/src/opover.d
3284 foreach (const u; 0 .. lhs.length)
3286 if (at(lhs, u) != at(rhs, u))
3287 return false;
3289 return true;
3291 else static if (__traits(isIntegral, U1))
3294 if (!__ctfe)
3296 import core.stdc.string : memcmp;
3297 return () @trusted { return memcmp(cast(void*)lhs.ptr, cast(void*)rhs.ptr, lhs.length * U1.sizeof) == 0; }();
3299 else
3301 foreach (const u; 0 .. lhs.length)
3303 if (at(lhs, u) != at(rhs, u))
3304 return false;
3306 return true;
3309 else
3311 foreach (const u; 0 .. lhs.length)
3313 static if (__traits(compiles, __equals(at(lhs, u), at(rhs, u))))
3315 if (!__equals(at(lhs, u), at(rhs, u)))
3316 return false;
3318 else static if (__traits(isFloating, U1))
3320 if (at(lhs, u) != at(rhs, u))
3321 return false;
3323 else static if (is(U1 : Object) && is(U2 : Object))
3325 if (!(cast(Object)at(lhs, u) is cast(Object)at(rhs, u)
3326 || at(lhs, u) && (cast(Object)at(lhs, u)).opEquals(cast(Object)at(rhs, u))))
3327 return false;
3329 else static if (__traits(hasMember, U1, "opEquals"))
3331 if (!at(lhs, u).opEquals(at(rhs, u)))
3332 return false;
3334 else static if (is(U1 == delegate))
3336 if (at(lhs, u) != at(rhs, u))
3337 return false;
3339 else static if (is(U1 == U11*, U11))
3341 if (at(lhs, u) != at(rhs, u))
3342 return false;
3344 else
3346 if (at(lhs, u).tupleof != at(rhs, u).tupleof)
3347 return false;
3351 return true;
3355 unittest {
3356 assert(__equals([], []));
3357 assert(!__equals([1, 2], [1, 2, 3]));
3360 unittest
3362 struct A
3364 int a;
3367 auto arr1 = [A(0), A(2)];
3368 auto arr2 = [A(0), A(1)];
3369 auto arr3 = [A(0), A(1)];
3371 assert(arr1 != arr2);
3372 assert(arr2 == arr3);
3375 unittest
3377 struct A
3379 int a;
3380 int b;
3382 bool opEquals(const A other)
3384 return this.a == other.b && this.b == other.a;
3388 auto arr1 = [A(1, 0), A(0, 1)];
3389 auto arr2 = [A(1, 0), A(0, 1)];
3390 auto arr3 = [A(0, 1), A(1, 0)];
3392 assert(arr1 != arr2);
3393 assert(arr2 == arr3);
3396 // Compare class and interface objects for ordering.
3397 private int __cmp(Obj)(Obj lhs, Obj rhs)
3398 if (is(Obj : Object))
3400 if (lhs is rhs)
3401 return 0;
3402 // Regard null references as always being "less than"
3403 if (!lhs)
3404 return -1;
3405 if (!rhs)
3406 return 1;
3407 return lhs.opCmp(rhs);
3410 int __cmp(T)(const T[] lhs, const T[] rhs) @trusted
3411 if (__traits(isScalar, T))
3413 // Compute U as the implementation type for T
3414 static if (is(T == ubyte) || is(T == void) || is(T == bool))
3415 alias U = char;
3416 else static if (is(T == wchar))
3417 alias U = ushort;
3418 else static if (is(T == dchar))
3419 alias U = uint;
3420 else static if (is(T == ifloat))
3421 alias U = float;
3422 else static if (is(T == idouble))
3423 alias U = double;
3424 else static if (is(T == ireal))
3425 alias U = real;
3426 else
3427 alias U = T;
3429 static if (is(U == char))
3431 import core.internal.string : dstrcmp;
3432 return dstrcmp(cast(char[]) lhs, cast(char[]) rhs);
3434 else static if (!is(U == T))
3436 // Reuse another implementation
3437 return __cmp(cast(U[]) lhs, cast(U[]) rhs);
3439 else
3441 immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length;
3442 foreach (const u; 0 .. len)
3444 static if (__traits(isFloating, T))
3446 immutable a = lhs.ptr[u], b = rhs.ptr[u];
3447 static if (is(T == cfloat) || is(T == cdouble)
3448 || is(T == creal))
3450 // Use rt.cmath2._Ccmp instead ?
3451 auto r = (a.re > b.re) - (a.re < b.re);
3452 if (!r) r = (a.im > b.im) - (a.im < b.im);
3454 else
3456 const r = (a > b) - (a < b);
3458 if (r) return r;
3460 else if (lhs.ptr[u] != rhs.ptr[u])
3461 return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1;
3463 return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length);
3467 // This function is called by the compiler when dealing with array
3468 // comparisons in the semantic analysis phase of CmpExp. The ordering
3469 // comparison is lowered to a call to this template.
3470 int __cmp(T1, T2)(T1[] s1, T2[] s2)
3471 if (!__traits(isScalar, T1) && !__traits(isScalar, T2))
3473 import core.internal.traits : Unqual;
3474 alias U1 = Unqual!T1;
3475 alias U2 = Unqual!T2;
3477 static if (is(U1 == void) && is(U2 == void))
3478 static @trusted ref inout(ubyte) at(inout(void)[] r, size_t i) { return (cast(inout(ubyte)*) r.ptr)[i]; }
3479 else
3480 static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
3482 // All unsigned byte-wide types = > dstrcmp
3483 immutable len = s1.length <= s2.length ? s1.length : s2.length;
3485 foreach (const u; 0 .. len)
3487 static if (__traits(compiles, __cmp(at(s1, u), at(s2, u))))
3489 auto c = __cmp(at(s1, u), at(s2, u));
3490 if (c != 0)
3491 return c;
3493 else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u))))
3495 auto c = at(s1, u).opCmp(at(s2, u));
3496 if (c != 0)
3497 return c;
3499 else static if (__traits(compiles, at(s1, u) < at(s2, u)))
3501 if (at(s1, u) != at(s2, u))
3502 return at(s1, u) < at(s2, u) ? -1 : 1;
3504 else
3506 // TODO: fix this legacy bad behavior, see
3507 // https://issues.dlang.org/show_bug.cgi?id=17244
3508 static assert(is(U1 == U2), "Internal error.");
3509 import core.stdc.string : memcmp;
3510 auto c = (() @trusted => memcmp(&at(s1, u), &at(s2, u), U1.sizeof))();
3511 if (c != 0)
3512 return c;
3515 return s1.length < s2.length ? -1 : (s1.length > s2.length);
3518 // integral types
3519 @safe unittest
3521 void compareMinMax(T)()
3523 T[2] a = [T.max, T.max];
3524 T[2] b = [T.min, T.min];
3526 assert(__cmp(a, b) > 0);
3527 assert(__cmp(b, a) < 0);
3530 compareMinMax!int;
3531 compareMinMax!uint;
3532 compareMinMax!long;
3533 compareMinMax!ulong;
3534 compareMinMax!short;
3535 compareMinMax!ushort;
3536 compareMinMax!byte;
3537 compareMinMax!dchar;
3538 compareMinMax!wchar;
3541 // char types (dstrcmp)
3542 @safe unittest
3544 void compareMinMax(T)()
3546 T[2] a = [T.max, T.max];
3547 T[2] b = [T.min, T.min];
3549 assert(__cmp(a, b) > 0);
3550 assert(__cmp(b, a) < 0);
3553 compareMinMax!ubyte;
3554 compareMinMax!bool;
3555 compareMinMax!char;
3556 compareMinMax!(const char);
3558 string s1 = "aaaa";
3559 string s2 = "bbbb";
3560 assert(__cmp(s2, s1) > 0);
3561 assert(__cmp(s1, s2) < 0);
3564 // fp types
3565 @safe unittest
3567 void compareMinMax(T)()
3569 T[2] a = [T.max, T.max];
3570 T[2] b = [T.min_normal, T.min_normal];
3571 T[2] c = [T.max, T.min_normal];
3572 T[1] d = [T.max];
3574 assert(__cmp(a, b) > 0);
3575 assert(__cmp(b, a) < 0);
3576 assert(__cmp(a, c) > 0);
3577 assert(__cmp(a, d) > 0);
3578 assert(__cmp(d, c) < 0);
3579 assert(__cmp(c, c) == 0);
3582 compareMinMax!real;
3583 compareMinMax!float;
3584 compareMinMax!double;
3585 compareMinMax!ireal;
3586 compareMinMax!ifloat;
3587 compareMinMax!idouble;
3588 compareMinMax!creal;
3589 //compareMinMax!cfloat;
3590 compareMinMax!cdouble;
3592 // qualifiers
3593 compareMinMax!(const real);
3594 compareMinMax!(immutable real);
3597 // void[]
3598 @safe unittest
3600 void[] a;
3601 const(void)[] b;
3603 (() @trusted
3605 a = cast(void[]) "bb";
3606 b = cast(const(void)[]) "aa";
3607 })();
3609 assert(__cmp(a, b) > 0);
3610 assert(__cmp(b, a) < 0);
3613 // arrays of arrays with mixed modifiers
3614 @safe unittest
3616 // https://issues.dlang.org/show_bug.cgi?id=17876
3617 bool less1(immutable size_t[][] a, size_t[][] b) { return a < b; }
3618 bool less2(const void[][] a, void[][] b) { return a < b; }
3619 bool less3(inout size_t[][] a, size_t[][] b) { return a < b; }
3621 immutable size_t[][] a = [[1, 2], [3, 4]];
3622 size_t[][] b = [[1, 2], [3, 5]];
3623 assert(less1(a, b));
3624 assert(less3(a, b));
3626 auto va = [cast(immutable void[])a[0], a[1]];
3627 auto vb = [cast(void[])b[0], b[1]];
3628 assert(less2(va, vb));
3631 // objects
3632 @safe unittest
3634 class C
3636 int i;
3637 this(int i) { this.i = i; }
3639 override int opCmp(Object c) const @safe
3641 return i - (cast(C)c).i;
3645 auto c1 = new C(1);
3646 auto c2 = new C(2);
3647 assert(__cmp(c1, null) > 0);
3648 assert(__cmp(null, c1) < 0);
3649 assert(__cmp(c1, c1) == 0);
3650 assert(__cmp(c1, c2) < 0);
3651 assert(__cmp(c2, c1) > 0);
3653 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
3654 assert(__cmp([c2, c2], [c1, c1]) > 0);
3657 // structs
3658 @safe unittest
3660 struct C
3662 ubyte i;
3663 this(ubyte i) { this.i = i; }
3666 auto c1 = C(1);
3667 auto c2 = C(2);
3669 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
3670 assert(__cmp([c2, c2], [c1, c1]) > 0);
3671 assert(__cmp([c2, c2], [c2, c1]) > 0);
3674 // Compiler hook into the runtime implementation of array (vector) operations.
3675 template _arrayOp(Args...)
3677 import core.internal.arrayop;
3678 alias _arrayOp = arrayOp!Args;
3681 // Helper functions
3683 private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow
3685 TypeInfo element = cast() value;
3686 for (;;)
3688 if (auto qualified = cast(TypeInfo_Const) element)
3689 element = qualified.base;
3690 else if (auto redefined = cast(TypeInfo_Enum) element)
3691 element = redefined.base;
3692 else if (auto staticArray = cast(TypeInfo_StaticArray) element)
3693 element = staticArray.value;
3694 else if (auto vector = cast(TypeInfo_Vector) element)
3695 element = vector.base;
3696 else
3697 break;
3699 return cast(inout) element;
3702 private size_t getArrayHash(in TypeInfo element, in void* ptr, in size_t count) @trusted nothrow
3704 if (!count)
3705 return 0;
3707 const size_t elementSize = element.tsize;
3708 if (!elementSize)
3709 return 0;
3711 static bool hasCustomToHash(in TypeInfo value) @trusted pure nothrow
3713 const element = getElement(value);
3715 if (const struct_ = cast(const TypeInfo_Struct) element)
3716 return !!struct_.xtoHash;
3718 return cast(const TypeInfo_Array) element
3719 || cast(const TypeInfo_AssociativeArray) element
3720 || cast(const ClassInfo) element
3721 || cast(const TypeInfo_Interface) element;
3724 import core.internal.traits : externDFunc;
3725 alias hashOf = externDFunc!("rt.util.hash.hashOf",
3726 size_t function(const(void)[], size_t) @trusted pure nothrow @nogc);
3727 if (!hasCustomToHash(element))
3728 return hashOf(ptr[0 .. elementSize * count], 0);
3730 size_t hash = 0;
3731 foreach (size_t i; 0 .. count)
3732 hash += element.getHash(ptr + i * elementSize);
3733 return hash;
3737 // Tests ensure TypeInfo_Array.getHash uses element hash functions instead of hashing array data
3739 unittest
3741 class C
3743 int i;
3744 this(in int i) { this.i = i; }
3745 override hash_t toHash() { return 0; }
3747 C[] a1 = [new C(11)], a2 = [new C(12)];
3748 assert(typeid(C[]).getHash(&a1) == typeid(C[]).getHash(&a2));
3751 unittest
3753 struct S
3755 int i;
3756 hash_t toHash() const @safe nothrow { return 0; }
3758 S[] a1 = [S(11)], a2 = [S(12)];
3759 assert(typeid(S[]).getHash(&a1) == typeid(S[]).getHash(&a2));
3762 @safe unittest
3764 struct S
3766 int i;
3767 const @safe nothrow:
3768 hash_t toHash() { return 0; }
3769 bool opEquals(const S) { return true; }
3770 int opCmp(const S) { return 0; }
3773 int[S[]] aa = [[S(11)] : 13];
3774 assert(aa[[S(12)]] == 13);
3777 /// Provide the .dup array property.
3778 @property auto dup(T)(T[] a)
3779 if (!is(const(T) : T))
3781 import core.internal.traits : Unconst;
3782 static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
3783 " to "~Unconst!T.stringof~" in dup.");
3785 // wrap unsafe _dup in @trusted to preserve @safe postblit
3786 static if (__traits(compiles, (T b) @safe { T a = b; }))
3787 return _trustedDup!(T, Unconst!T)(a);
3788 else
3789 return _dup!(T, Unconst!T)(a);
3792 /// ditto
3793 // const overload to support implicit conversion to immutable (unique result, see DIP29)
3794 @property T[] dup(T)(const(T)[] a)
3795 if (is(const(T) : T))
3797 // wrap unsafe _dup in @trusted to preserve @safe postblit
3798 static if (__traits(compiles, (T b) @safe { T a = b; }))
3799 return _trustedDup!(const(T), T)(a);
3800 else
3801 return _dup!(const(T), T)(a);
3805 /// Provide the .idup array property.
3806 @property immutable(T)[] idup(T)(T[] a)
3808 static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
3809 " to immutable in idup.");
3811 // wrap unsafe _dup in @trusted to preserve @safe postblit
3812 static if (__traits(compiles, (T b) @safe { T a = b; }))
3813 return _trustedDup!(T, immutable(T))(a);
3814 else
3815 return _dup!(T, immutable(T))(a);
3818 /// ditto
3819 @property immutable(T)[] idup(T:void)(const(T)[] a)
3821 return a.dup;
3824 private U[] _trustedDup(T, U)(T[] a) @trusted
3826 return _dup!(T, U)(a);
3829 private U[] _dup(T, U)(T[] a) // pure nothrow depends on postblit
3831 if (__ctfe)
3833 static if (is(T : void))
3834 assert(0, "Cannot dup a void[] array at compile time.");
3835 else
3837 U[] res;
3838 foreach (ref e; a)
3839 res ~= e;
3840 return res;
3844 import core.stdc.string : memcpy;
3846 void[] arr = _d_newarrayU(typeid(T[]), a.length);
3847 memcpy(arr.ptr, cast(const(void)*)a.ptr, T.sizeof * a.length);
3848 auto res = *cast(U[]*)&arr;
3850 static if (!is(T : void))
3851 _doPostblit(res);
3852 return res;
3855 private extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;
3858 /**************
3859 * Get the postblit for type T.
3860 * Returns:
3861 * null if no postblit is necessary
3862 * function pointer for struct postblits
3863 * delegate for class postblits
3865 private auto _getPostblit(T)() @trusted pure nothrow @nogc
3867 // infer static postblit type, run postblit if any
3868 static if (is(T == struct))
3870 import core.internal.traits : Unqual;
3871 // use typeid(Unqual!T) here to skip TypeInfo_Const/Shared/...
3872 alias _PostBlitType = typeof(function (ref T t){ T a = t; });
3873 return cast(_PostBlitType)typeid(Unqual!T).xpostblit;
3875 else if ((&typeid(T).postblit).funcptr !is &TypeInfo.postblit)
3877 alias _PostBlitType = typeof(delegate (ref T t){ T a = t; });
3878 return cast(_PostBlitType)&typeid(T).postblit;
3880 else
3881 return null;
3884 private void _doPostblit(T)(T[] arr)
3886 // infer static postblit type, run postblit if any
3887 if (auto postblit = _getPostblit!T())
3889 foreach (ref elem; arr)
3890 postblit(elem);
3894 unittest
3896 static struct S1 { int* p; }
3897 static struct S2 { @disable this(); }
3898 static struct S3 { @disable this(this); }
3900 int dg1() pure nothrow @safe
3903 char[] m;
3904 string i;
3905 m = m.dup;
3906 i = i.idup;
3907 m = i.dup;
3908 i = m.idup;
3911 S1[] m;
3912 immutable(S1)[] i;
3913 m = m.dup;
3914 i = i.idup;
3915 static assert(!is(typeof(m.idup)));
3916 static assert(!is(typeof(i.dup)));
3919 S3[] m;
3920 immutable(S3)[] i;
3921 static assert(!is(typeof(m.dup)));
3922 static assert(!is(typeof(i.idup)));
3925 shared(S1)[] m;
3926 m = m.dup;
3927 static assert(!is(typeof(m.idup)));
3930 int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
3932 return 1;
3935 int dg2() pure nothrow @safe
3938 S2[] m = [S2.init, S2.init];
3939 immutable(S2)[] i = [S2.init, S2.init];
3940 m = m.dup;
3941 m = i.dup;
3942 i = m.idup;
3943 i = i.idup;
3945 return 2;
3948 enum a = dg1();
3949 enum b = dg2();
3950 assert(dg1() == a);
3951 assert(dg2() == b);
3954 unittest
3956 static struct Sunpure { this(this) @safe nothrow {} }
3957 static struct Sthrow { this(this) @safe pure {} }
3958 static struct Sunsafe { this(this) @system pure nothrow {} }
3960 static assert( __traits(compiles, () { [].dup!Sunpure; }));
3961 static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
3962 static assert( __traits(compiles, () { [].dup!Sthrow; }));
3963 static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
3964 static assert( __traits(compiles, () { [].dup!Sunsafe; }));
3965 static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
3967 static assert( __traits(compiles, () { [].idup!Sunpure; }));
3968 static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
3969 static assert( __traits(compiles, () { [].idup!Sthrow; }));
3970 static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
3971 static assert( __traits(compiles, () { [].idup!Sunsafe; }));
3972 static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
3975 unittest
3977 static int*[] pureFoo() pure { return null; }
3978 { char[] s; immutable x = s.dup; }
3979 { immutable x = (cast(int*[])null).dup; }
3980 { immutable x = pureFoo(); }
3981 { immutable x = pureFoo().dup; }
3984 unittest
3986 auto a = [1, 2, 3];
3987 auto b = a.dup;
3988 debug(SENTINEL) {} else
3989 assert(b.capacity >= 3);
3992 unittest
3994 // Bugzilla 12580
3995 void[] m = [0];
3996 shared(void)[] s = [cast(shared)1];
3997 immutable(void)[] i = [cast(immutable)2];
3999 s = s.dup;
4000 static assert(is(typeof(s.dup) == shared(void)[]));
4002 m = i.dup;
4003 i = m.dup;
4004 i = i.idup;
4005 i = m.idup;
4006 i = s.idup;
4007 i = s.dup;
4008 static assert(!__traits(compiles, m = s.dup));
4011 unittest
4013 // Bugzilla 13809
4014 static struct S
4016 this(this) {}
4017 ~this() {}
4020 S[] arr;
4021 auto a = arr.dup;
4024 unittest
4026 // Bugzilla 16504
4027 static struct S
4029 __gshared int* gp;
4030 int* p;
4031 // postblit and hence .dup could escape
4032 this(this) { gp = p; }
4035 int p;
4036 scope arr = [S(&p)];
4037 auto a = arr.dup; // dup does escape