hppa: Improve handling of REG+D addresses when generating PA 2.0 code
[official-gcc.git] / libphobos / libdruntime / object.d
blob4264ecf6fd62f8c1de2d95e27f5e5c32e1a3398c
1 /**
2 * $(SCRIPT inhibitQuickIndex = 1;)
3 * $(DIVC quickindex,
4 * $(BOOKTABLE,
5 * $(TR $(TH Category) $(TH Symbols))
6 * $(TR $(TD Arrays) $(TD
7 * $(MYREF assumeSafeAppend)
8 * $(MYREF capacity)
9 * $(A #.dup.2, $(TT dup))
10 * $(MYREF idup)
11 * $(MYREF reserve)
12 * ))
13 * $(TR $(TD Associative arrays) $(TD
14 * $(MYREF byKey)
15 * $(MYREF byKeyValue)
16 * $(MYREF byValue)
17 * $(MYREF clear)
18 * $(MYREF dup)
19 * $(MYREF get)
20 * $(MYREF keys)
21 * $(MYREF rehash)
22 * $(MYREF require)
23 * $(MYREF update)
24 * $(MYREF values)
25 * ))
26 * $(TR $(TD General) $(TD
27 * $(MYREF destroy)
28 * $(MYREF hashOf)
29 * $(MYREF imported)
30 * $(MYREF noreturn)
31 * ))
32 * $(TR $(TD Classes) $(TD
33 * $(MYREF Error)
34 * $(MYREF Exception)
35 * $(MYREF Object)
36 * $(MYREF opEquals)
37 * $(MYREF Throwable)
38 * ))
39 * $(TR $(TD Type info) $(TD
40 * $(MYREF Interface)
41 * $(MYREF ModuleInfo)
42 * $(MYREF OffsetTypeInfo)
43 * $(MYREF RTInfoImpl)
44 * $(MYREF rtinfoNoPointers)
45 * $(MYREF TypeInfo)
46 * $(MYREF TypeInfo_Class)
47 * ))
48 * ))
50 * Forms the symbols available to all D programs. Includes Object, which is
51 * the root of the class object hierarchy. This module is implicitly
52 * imported.
54 * Copyright: Copyright Digital Mars 2000 - 2011.
55 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
56 * Authors: Walter Bright, Sean Kelly
57 * Source: $(DRUNTIMESRC object.d)
60 module object;
62 alias size_t = typeof(int.sizeof);
63 alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
65 alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
66 /**
67 * Bottom type.
68 * See $(DDSUBLINK spec/type, noreturn, `noreturn`).
70 alias noreturn = typeof(*null);
72 alias hash_t = size_t; // For backwards compatibility only.
73 alias equals_t = bool; // For backwards compatibility only.
75 alias string = immutable(char)[];
76 alias wstring = immutable(wchar)[];
77 alias dstring = immutable(dchar)[];
79 version (D_ObjectiveC)
81 deprecated("explicitly import `selector` instead using: `import core.attribute : selector;`")
82 public import core.attribute : selector;
84 version (Posix) public import core.attribute : gnuAbiTag;
86 // Some ABIs use a complex varargs implementation requiring TypeInfo.argTypes().
87 version (GNU)
89 // No TypeInfo-based core.vararg.va_arg().
91 else version (X86_64)
93 version (DigitalMars) version = WithArgTypes;
94 else version (Windows) { /* no need for Win64 ABI */ }
95 else version = WithArgTypes;
97 else version (AArch64)
99 // Apple uses a trivial varargs implementation
100 version (OSX) {}
101 else version (iOS) {}
102 else version (TVOS) {}
103 else version (WatchOS) {}
104 else version = WithArgTypes;
108 * All D class objects inherit from Object.
110 class Object
113 * Convert Object to a human readable string.
115 string toString()
117 return typeid(this).name;
120 @system unittest
122 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
123 enum fqn_unittest = "object.Object." ~ unittest_sym_name; // object.__unittest_LX_CY
125 class C {}
127 Object obj = new Object;
128 C c = new C;
130 assert(obj.toString() == "object.Object");
131 assert(c.toString() == fqn_unittest ~ ".C");
135 * Compute hash function for Object.
137 size_t toHash() @trusted nothrow
139 // BUG: this prevents a compacting GC from working, needs to be fixed
140 size_t addr = cast(size_t) cast(void*) this;
141 // The bottom log2((void*).alignof) bits of the address will always
142 // be 0. Moreover it is likely that each Object is allocated with a
143 // separate call to malloc. The alignment of malloc differs from
144 // platform to platform, but rather than having special cases for
145 // each platform it is safe to use a shift of 4. To minimize
146 // collisions in the low bits it is more important for the shift to
147 // not be too small than for the shift to not be too big.
148 return addr ^ (addr >>> 4);
152 * Compare with another Object obj.
153 * Returns:
154 * $(TABLE
155 * $(TR $(TD this < obj) $(TD < 0))
156 * $(TR $(TD this == obj) $(TD 0))
157 * $(TR $(TD this > obj) $(TD > 0))
160 int opCmp(Object o)
162 // BUG: this prevents a compacting GC from working, needs to be fixed
163 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
165 throw new Exception("need opCmp for class " ~ typeid(this).name);
166 //return this !is o;
169 @system unittest
171 Object obj = new Object;
173 bool gotCaught;
176 obj.opCmp(new Object);
178 catch (Exception e)
180 gotCaught = true;
181 assert(e.msg == "need opCmp for class object.Object");
183 assert(gotCaught);
187 * Test whether $(D this) is equal to $(D o).
188 * The default implementation only compares by identity (using the $(D is) operator).
189 * Generally, overrides and overloads for $(D opEquals) should attempt to compare objects by their contents.
190 * A class will most likely want to add an overload that takes your specific type as the argument
191 * and does the content comparison. Then you can override this and forward it to your specific
192 * typed overload with a cast. Remember to check for `null` on the typed overload.
194 * Examples:
195 * ---
196 * class Child {
197 * int contents;
198 * // the typed overload first. It can use all the attribute you want
199 * bool opEquals(const Child c) const @safe pure nothrow @nogc
201 * if (c is null)
202 * return false;
203 * return this.contents == c.contents;
206 * // and now the generic override forwards with a cast
207 * override bool opEquals(Object o)
209 * return this.opEquals(cast(Child) o);
212 * ---
214 bool opEquals(Object o)
216 return this is o;
219 interface Monitor
221 void lock();
222 void unlock();
226 * Create instance of class specified by the fully qualified name
227 * classname.
228 * The class must either have no constructors or have
229 * a default constructor.
230 * Returns:
231 * null if failed
232 * Example:
233 * ---
234 * module foo.bar;
236 * class C
238 * this() { x = 10; }
239 * int x;
242 * void main()
244 * auto c = cast(C)Object.factory("foo.bar.C");
245 * assert(c !is null && c.x == 10);
247 * ---
249 static Object factory(string classname)
251 auto ci = TypeInfo_Class.find(classname);
252 if (ci)
254 return ci.create();
256 return null;
259 @system unittest
261 Object valid_obj = Object.factory("object.Object");
262 Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__");
264 assert(valid_obj !is null);
265 assert(invalid_obj is null);
270 Implementation for class opEquals override. Calls the class-defined methods after a null check.
271 Please note this is not nogc right now, even if your implementation is, because of
272 the typeinfo name string compare. This is because of dmd's dll implementation. However,
273 it can infer to @safe if your class' opEquals is.
275 bool opEquals(LHS, RHS)(LHS lhs, RHS rhs)
276 if ((is(LHS : const Object) || is(LHS : const shared Object)) &&
277 (is(RHS : const Object) || is(RHS : const shared Object)))
279 static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs)))
281 // If aliased to the same object or both null => equal
282 if (lhs is rhs) return true;
284 // If either is null => non-equal
285 if (lhs is null || rhs is null) return false;
287 if (!lhs.opEquals(rhs)) return false;
289 // If same exact type => one call to method opEquals
290 if (typeid(lhs) is typeid(rhs) ||
291 !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
292 /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't:
293 https://issues.dlang.org/show_bug.cgi?id=7147
294 But CTFE also guarantees that equal TypeInfos are
295 always identical. So, no opEquals needed during CTFE. */
297 return true;
300 // General case => symmetric calls to method opEquals
301 return rhs.opEquals(lhs);
303 else
305 // this is a compatibility hack for the old const cast behavior
306 // if none of the new overloads compile, we'll go back plain Object,
307 // including casting away const. It does this through the pointer
308 // to bypass any opCast that may be present on the original class.
309 return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs);
314 /// If aliased to the same object or both null => equal
315 @system unittest // this one is not @safe because it goes through the Object base method
317 class F { int flag; this(int flag) { this.flag = flag; } }
319 F f;
320 assert(f == f); // both null
321 f = new F(1);
322 assert(f == f); // both aliased to the same object
325 /// If either is null => non-equal
326 @system unittest
328 class F { int flag; this(int flag) { this.flag = flag; } }
329 F f;
330 assert(!(new F(0) == f));
331 assert(!(f == new F(0)));
334 /// If same exact type => one call to method opEquals
335 /// This test passes `@safe` because it defines a new opEquals with `@safe`
336 @safe unittest
338 class F
340 int flag;
342 this(int flag)
344 this.flag = flag;
347 bool opEquals(const F o) const @safe nothrow pure
349 return flag == o.flag;
353 F f;
354 assert(new F(0) == new F(0));
355 assert(!(new F(0) == new F(1)));
358 /// General case => symmetric calls to method opEquals
359 @safe unittest
361 int fEquals, gEquals;
363 class Base
365 int flag;
366 this(int flag)
368 this.flag = flag;
372 class F : Base
374 this(int flag) { super(flag); }
376 bool opEquals(const Base o) @safe
378 fEquals++;
379 return flag == o.flag;
383 class G : Base
385 this(int flag) { super(flag); }
387 bool opEquals(const Base o) @safe
389 gEquals++;
390 return flag == o.flag;
394 assert(new F(1) == new G(1));
395 assert(fEquals == 1);
396 assert(gEquals == 1);
400 This test shows an example for a comprehensive inheritance equality chain too.
402 unittest
404 static class Base
406 int member;
408 this(int member) pure @safe nothrow @nogc
410 this.member = member;
413 override bool opEquals(Object rhs) const
415 return this.opEquals(cast(Base) rhs);
418 bool opEquals(const Base rhs) const @nogc pure nothrow @safe
420 if (rhs is null)
421 return false;
422 return this.member == rhs.member;
426 // works through the direct class with attributes enabled, except for pure and nogc in the current TypeInfo implementation
427 bool testThroughBase() nothrow @safe
429 Base b1 = new Base(0);
430 Base b2 = new Base(0);
431 assert(b1 == b2);
432 Base b3 = new Base(1);
433 assert(b1 != b3);
434 return true;
437 static assert(testThroughBase());
439 // also works through the base class interface thanks to the override, but no more attributes
440 bool testThroughObject()
442 Object o1 = new Base(0);
443 Object o2 = new Base(0);
444 assert(o1 == o2);
445 Object o3 = new Base(1);
446 assert(o1 != o3);
447 return true;
450 static assert(testThroughObject());
452 // Each time you make a child, you want to override all old opEquals
453 // and add a new overload for the new child.
454 static class Child : Base
456 int member2;
458 this(int member, int member2) pure @safe nothrow @nogc
460 super(member);
461 this.member2 = member2;
464 // override the whole chain so it works consistently though any base
465 override bool opEquals(Object rhs) const
467 return this.opEquals(cast(Child) rhs);
469 override bool opEquals(const Base rhs) const
471 return this.opEquals(cast(const Child) rhs);
473 // and then add the new overload, if necessary, to handle new members
474 bool opEquals(const Child rhs) const @nogc pure nothrow @safe
476 if (rhs is null)
477 return false;
478 // can call back to the devirtualized base test with implicit conversion
479 // then compare the new member too. or we could have just compared the base
480 // member directly here as well.
481 return Base.opEquals(rhs) && this.member2 == rhs.member2;
484 // a mixin template, of course, could automate this.
487 bool testThroughChild()
489 Child a = new Child(0, 0);
490 Child b = new Child(0, 1);
491 assert(a != b);
493 Base ba = a;
494 Base bb = b;
495 assert(ba != bb);
497 Object oa = a;
498 Object ob = b;
499 assert(oa != ob);
501 return true;
504 static assert(testThroughChild());
507 // To cover const Object opEquals
508 @system unittest
510 const Object obj1 = new Object;
511 const Object obj2 = new Object;
513 assert(obj1 == obj1);
514 assert(obj1 != obj2);
517 // https://issues.dlang.org/show_bug.cgi?id=23291
518 @system unittest
520 static shared class C { bool opEquals(const(shared(C)) rhs) const shared { return true;}}
521 const(C) c = new C();
522 const(C)[] a = [c];
523 const(C)[] b = [c];
524 assert(a[0] == b[0]);
527 private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
529 /** Makes ownee use owner's mutex.
530 * This will initialize owner's mutex if it hasn't been set yet.
531 * Params:
532 * ownee = object to change
533 * owner = source object
535 void setSameMutex(shared Object ownee, shared Object owner)
537 import core.atomic : atomicLoad;
538 _d_setSameMutex(atomicLoad(ownee), atomicLoad(owner));
541 @system unittest
543 shared Object obj1 = new Object;
544 synchronized class C
546 void bar() {}
548 shared C obj2 = new shared(C);
549 obj2.bar();
551 assert(obj1.__monitor != obj2.__monitor);
552 assert(obj1.__monitor is null);
554 setSameMutex(obj1, obj2);
555 assert(obj1.__monitor == obj2.__monitor);
556 assert(obj1.__monitor !is null);
560 * Information about an interface.
561 * When an object is accessed via an interface, an Interface* appears as the
562 * first entry in its vtbl.
564 struct Interface
566 /// Class info returned by `typeid` for this interface (not for containing class)
567 TypeInfo_Class classinfo;
568 void*[] vtbl;
569 size_t offset; /// offset to Interface 'this' from Object 'this'
573 * Array of pairs giving the offset and type information for each
574 * member in an aggregate.
576 struct OffsetTypeInfo
578 size_t offset; /// Offset of member from start of object
579 TypeInfo ti; /// TypeInfo for this member
583 * Runtime type information about a type.
584 * Can be retrieved for any type using a
585 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
587 class TypeInfo
589 override string toString() const @safe nothrow
591 return typeid(this).name;
594 override size_t toHash() @trusted const nothrow
596 return hashOf(this.toString());
599 override int opCmp(Object rhs)
601 if (this is rhs)
602 return 0;
603 auto ti = cast(TypeInfo) rhs;
604 if (ti is null)
605 return 1;
606 return __cmp(this.toString(), ti.toString());
609 @system unittest
611 assert(typeid(void) <= typeid(void));
612 assert(typeid(void).opCmp(null));
613 assert(!typeid(void).opCmp(typeid(void)));
616 override bool opEquals(Object o)
618 return opEquals(cast(TypeInfo) o);
621 bool opEquals(const TypeInfo ti) @safe nothrow const
623 /* TypeInfo instances are singletons, but duplicates can exist
624 * across DLL's. Therefore, comparing for a name match is
625 * sufficient.
627 if (this is ti)
628 return true;
629 return ti && this.toString() == ti.toString();
632 @system unittest
634 auto anotherObj = new Object();
636 assert(typeid(void).opEquals(typeid(void)));
637 assert(typeid(void) != anotherObj); // calling .opEquals here directly is a type mismatch
641 * Computes a hash of the instance of a type.
642 * Params:
643 * p = pointer to start of instance of the type
644 * Returns:
645 * the hash
646 * Bugs:
647 * fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
649 size_t getHash(scope const void* p) @trusted nothrow const
651 // by default, do not assume anything about the type
652 return 0;
655 /// Compares two instances for equality.
656 bool equals(in void* p1, in void* p2) const { return p1 == p2; }
658 /// Compares two instances for &lt;, ==, or &gt;.
659 int compare(in void* p1, in void* p2) const { return _xopCmp(p1, p2); }
661 /// Returns size of the type.
662 @property size_t tsize() nothrow pure const @safe @nogc { return 0; }
664 /// Swaps two instances of the type.
665 void swap(void* p1, void* p2) const
667 size_t remaining = tsize;
668 // If the type might contain pointers perform the swap in pointer-sized
669 // chunks in case a garbage collection pass interrupts this function.
670 if ((cast(size_t) p1 | cast(size_t) p2) % (void*).alignof == 0)
672 while (remaining >= (void*).sizeof)
674 void* tmp = *cast(void**) p1;
675 *cast(void**) p1 = *cast(void**) p2;
676 *cast(void**) p2 = tmp;
677 p1 += (void*).sizeof;
678 p2 += (void*).sizeof;
679 remaining -= (void*).sizeof;
682 for (size_t i = 0; i < remaining; i++)
684 byte t = (cast(byte *)p1)[i];
685 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
686 (cast(byte*)p2)[i] = t;
690 @system unittest
692 class _TypeInfo_Dummy : TypeInfo
694 override const(void)[] initializer() const { return []; }
695 @property override size_t tsize() nothrow pure const @safe @nogc { return tsize_val; }
697 size_t tsize_val;
699 auto dummy = new _TypeInfo_Dummy();
700 cast(void)dummy.initializer(); // For coverage completeness
702 int a = 2, b = -2;
703 dummy.swap(&a, &b);
704 // does nothing because tsize is 0
705 assert(a == 2);
706 assert(b == -2);
708 dummy.tsize_val = int.sizeof;
709 dummy.swap(&a, &b);
710 assert(a == -2);
711 assert(b == 2);
713 void* ptr_a = null, ptr_b = cast(void*)1;
714 dummy.tsize_val = (void*).sizeof;
715 dummy.swap(&ptr_a, &ptr_b);
716 assert(ptr_a is cast(void*)1);
717 assert(ptr_b is null);
720 /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
721 null if none. */
722 @property inout(TypeInfo) next() nothrow pure inout @nogc { return null; }
725 * Return default initializer. If the type should be initialized to all
726 * zeros, an array with a null ptr and a length equal to the type size will
727 * be returned. For static arrays, this returns the default initializer for
728 * a single element of the array, use `tsize` to get the correct size.
730 abstract const(void)[] initializer() nothrow pure const @safe @nogc;
732 /** Get flags for type: 1 means GC should scan for pointers,
733 2 means arg of this type is passed in SIMD register(s) if available */
734 @property uint flags() nothrow pure const @safe @nogc { return 0; }
736 /// Get type information on the contents of the type; null if not available
737 const(OffsetTypeInfo)[] offTi() const { return null; }
738 /// Run the destructor on the object and all its sub-objects
739 void destroy(void* p) const {}
740 /// Run the postblit on the object and all its sub-objects
741 void postblit(void* p) const {}
744 /// Return alignment of type
745 @property size_t talign() nothrow pure const @safe @nogc { return tsize; }
747 /** Return internal info on arguments fitting into 8byte.
748 * See X86-64 ABI 3.2.3
750 version (WithArgTypes) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
752 arg1 = this;
753 return 0;
756 /** Return info used by the garbage collector to do precise collection.
758 @property immutable(void)* rtInfo() nothrow pure const @trusted @nogc { return rtinfoHasPointers; } // better safe than sorry
761 @system unittest
763 class _TypeInfo_Dummy : TypeInfo
765 override const(void)[] initializer() const { return []; }
767 auto dummy = new _TypeInfo_Dummy();
768 cast(void)dummy.initializer(); // For coverage completeness
770 assert(dummy.rtInfo() is rtinfoHasPointers);
771 assert(typeid(void).rtInfo() is rtinfoNoPointers);
773 assert(dummy.tsize() == 0);
775 bool gotCaught;
778 dummy.compare(null, null);
779 } catch (Error e)
781 gotCaught = true;
782 assert(e.msg == "TypeInfo.compare is not implemented");
784 assert(gotCaught);
786 assert(dummy.equals(null, null));
787 assert(!dummy.equals(cast(void*)1, null));
790 @system unittest
792 assert(typeid(void).next() is null);
793 assert(typeid(void).offTi() is null);
794 assert(typeid(void).tsize() == 1);
796 version (WithArgTypes)
798 TypeInfo ti1;
799 TypeInfo ti2;
800 assert(typeid(void).argTypes(ti1, ti2) == 0);
801 assert(typeid(void) is ti1);
803 assert(ti1 !is null);
804 assert(ti2 is null);
808 @system unittest
810 class _ZypeInfo_Dummy : TypeInfo
812 override const(void)[] initializer() const { return []; }
814 auto dummy2 = new _ZypeInfo_Dummy();
815 cast(void)dummy2.initializer(); // For coverage completeness
817 assert(typeid(void) > dummy2);
818 assert(dummy2 < typeid(void));
821 @safe unittest
823 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
824 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
826 class _TypeInfo_Dummy : TypeInfo
828 override const(void)[] initializer() const { return []; }
831 auto dummy = new _TypeInfo_Dummy();
832 cast(void)dummy.initializer(); // For coverage completeness
834 assert(dummy.toString() == fqn_unittest ~ "._TypeInfo_Dummy");
835 assert(dummy.toHash() == hashOf(dummy.toString()));
836 assert(dummy.getHash(null) == 0);
839 class TypeInfo_Enum : TypeInfo
841 override string toString() const pure { return name; }
843 override bool opEquals(Object o)
845 if (this is o)
846 return true;
847 auto c = cast(const TypeInfo_Enum)o;
848 return c && this.name == c.name &&
849 this.base == c.base;
852 @system unittest
854 enum E { A, B, C }
855 enum EE { A, B, C }
857 assert(typeid(E).opEquals(typeid(E)));
858 assert(!typeid(E).opEquals(typeid(EE)));
861 override size_t getHash(scope const void* p) const { return base.getHash(p); }
863 @system unittest
865 enum E { A, B, C }
866 E e1 = E.A;
867 E e2 = E.B;
869 assert(typeid(E).getHash(&e1) == hashOf(E.A));
870 assert(typeid(E).getHash(&e2) == hashOf(E.B));
872 enum ES : string { A = "foo", B = "bar" }
873 ES es1 = ES.A;
874 ES es2 = ES.B;
876 assert(typeid(ES).getHash(&es1) == hashOf("foo"));
877 assert(typeid(ES).getHash(&es2) == hashOf("bar"));
880 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
882 @system unittest
884 enum E { A, B, C }
886 E e1 = E.A;
887 E e2 = E.B;
889 assert(typeid(E).equals(&e1, &e1));
890 assert(!typeid(E).equals(&e1, &e2));
893 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
895 @system unittest
897 enum E { A, B, C }
899 E e1 = E.A;
900 E e2 = E.B;
902 assert(typeid(E).compare(&e1, &e1) == 0);
903 assert(typeid(E).compare(&e1, &e2) < 0);
904 assert(typeid(E).compare(&e2, &e1) > 0);
907 override @property size_t tsize() nothrow pure const { return base.tsize; }
909 @safe unittest
911 enum E { A, B, C }
912 enum ES : string { A = "a", B = "b", C = "c"}
914 assert(typeid(E).tsize == E.sizeof);
915 assert(typeid(ES).tsize == ES.sizeof);
916 assert(typeid(E).tsize != ES.sizeof);
919 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
921 @system unittest
923 enum E { A, B, C }
925 E e1 = E.A;
926 E e2 = E.B;
928 typeid(E).swap(&e1, &e2);
929 assert(e1 == E.B);
930 assert(e2 == E.A);
933 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
935 @system unittest
937 enum E { A, B, C }
939 assert(typeid(E).next is null);
942 override @property uint flags() nothrow pure const { return base.flags; }
944 @safe unittest
946 enum E { A, B, C }
948 assert(typeid(E).flags == 0);
951 override const(OffsetTypeInfo)[] offTi() const { return base.offTi; }
953 @system unittest
955 enum E { A, B, C }
957 assert(typeid(E).offTi is null);
960 override void destroy(void* p) const { return base.destroy(p); }
961 override void postblit(void* p) const { return base.postblit(p); }
963 override const(void)[] initializer() const
965 return m_init.length ? m_init : base.initializer();
968 override @property size_t talign() nothrow pure const { return base.talign; }
970 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
972 return base.argTypes(arg1, arg2);
975 override @property immutable(void)* rtInfo() const { return base.rtInfo; }
977 TypeInfo base;
978 string name;
979 void[] m_init;
982 @safe unittest
984 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
985 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
987 enum E { A, B, C }
988 enum EE { A, B, C }
990 assert(typeid(E).toString() == fqn_unittest ~ ".E");
994 @safe unittest // https://issues.dlang.org/show_bug.cgi?id=12233
996 static assert(is(typeof(TypeInfo.init) == TypeInfo));
997 assert(TypeInfo.init is null);
1001 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
1002 class TypeInfo_Pointer : TypeInfo
1004 override string toString() const { return m_next.toString() ~ "*"; }
1006 override bool opEquals(Object o)
1008 if (this is o)
1009 return true;
1010 auto c = cast(const TypeInfo_Pointer)o;
1011 return c && this.m_next == c.m_next;
1014 override size_t getHash(scope const void* p) @trusted const
1016 size_t addr = cast(size_t) *cast(const void**)p;
1017 return addr ^ (addr >> 4);
1020 override bool equals(in void* p1, in void* p2) const
1022 return *cast(void**)p1 == *cast(void**)p2;
1025 override int compare(in void* p1, in void* p2) const
1027 const v1 = *cast(void**) p1, v2 = *cast(void**) p2;
1028 return (v1 > v2) - (v1 < v2);
1031 override @property size_t tsize() nothrow pure const
1033 return (void*).sizeof;
1036 override const(void)[] initializer() const @trusted
1038 return (cast(void *)null)[0 .. (void*).sizeof];
1041 override void swap(void* p1, void* p2) const
1043 void* tmp = *cast(void**)p1;
1044 *cast(void**)p1 = *cast(void**)p2;
1045 *cast(void**)p2 = tmp;
1048 override @property inout(TypeInfo) next() nothrow pure inout { return m_next; }
1049 override @property uint flags() nothrow pure const { return 1; }
1051 TypeInfo m_next;
1054 class TypeInfo_Array : TypeInfo
1056 override string toString() const { return value.toString() ~ "[]"; }
1058 override bool opEquals(Object o)
1060 if (this is o)
1061 return true;
1062 auto c = cast(const TypeInfo_Array)o;
1063 return c && this.value == c.value;
1066 override size_t getHash(scope const void* p) @trusted const
1068 void[] a = *cast(void[]*)p;
1069 return getArrayHash(value, a.ptr, a.length);
1072 override bool equals(in void* p1, in void* p2) const
1074 void[] a1 = *cast(void[]*)p1;
1075 void[] a2 = *cast(void[]*)p2;
1076 if (a1.length != a2.length)
1077 return false;
1078 size_t sz = value.tsize;
1079 for (size_t i = 0; i < a1.length; i++)
1081 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
1082 return false;
1084 return true;
1087 override int compare(in void* p1, in void* p2) const
1089 void[] a1 = *cast(void[]*)p1;
1090 void[] a2 = *cast(void[]*)p2;
1091 size_t sz = value.tsize;
1092 size_t len = a1.length;
1094 if (a2.length < len)
1095 len = a2.length;
1096 for (size_t u = 0; u < len; u++)
1098 immutable int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
1099 if (result)
1100 return result;
1102 return (a1.length > a2.length) - (a1.length < a2.length);
1105 override @property size_t tsize() nothrow pure const
1107 return (void[]).sizeof;
1110 override const(void)[] initializer() const @trusted
1112 return (cast(void *)null)[0 .. (void[]).sizeof];
1115 override void swap(void* p1, void* p2) const
1117 void[] tmp = *cast(void[]*)p1;
1118 *cast(void[]*)p1 = *cast(void[]*)p2;
1119 *cast(void[]*)p2 = tmp;
1122 TypeInfo value;
1124 override @property inout(TypeInfo) next() nothrow pure inout
1126 return value;
1129 override @property uint flags() nothrow pure const { return 1; }
1131 override @property size_t talign() nothrow pure const
1133 return (void[]).alignof;
1136 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1138 arg1 = typeid(size_t);
1139 arg2 = typeid(void*);
1140 return 0;
1143 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(void[]); }
1146 class TypeInfo_StaticArray : TypeInfo
1148 override string toString() const
1150 import core.internal.string : unsignedToTempString;
1152 char[20] tmpBuff = void;
1153 const lenString = unsignedToTempString(len, tmpBuff);
1155 return (() @trusted => cast(string) (value.toString() ~ "[" ~ lenString ~ "]"))();
1158 override bool opEquals(Object o)
1160 if (this is o)
1161 return true;
1162 auto c = cast(const TypeInfo_StaticArray)o;
1163 return c && this.len == c.len &&
1164 this.value == c.value;
1167 override size_t getHash(scope const void* p) @trusted const
1169 return getArrayHash(value, p, len);
1172 override bool equals(in void* p1, in void* p2) const
1174 size_t sz = value.tsize;
1176 for (size_t u = 0; u < len; u++)
1178 if (!value.equals(p1 + u * sz, p2 + u * sz))
1179 return false;
1181 return true;
1184 override int compare(in void* p1, in void* p2) const
1186 size_t sz = value.tsize;
1188 for (size_t u = 0; u < len; u++)
1190 immutable int result = value.compare(p1 + u * sz, p2 + u * sz);
1191 if (result)
1192 return result;
1194 return 0;
1197 override @property size_t tsize() nothrow pure const
1199 return len * value.tsize;
1202 override void swap(void* p1, void* p2) const
1204 import core.stdc.string : memcpy;
1206 size_t remaining = value.tsize * len;
1207 void[size_t.sizeof * 4] buffer = void;
1208 while (remaining > buffer.length)
1210 memcpy(buffer.ptr, p1, buffer.length);
1211 memcpy(p1, p2, buffer.length);
1212 memcpy(p2, buffer.ptr, buffer.length);
1213 p1 += buffer.length;
1214 p2 += buffer.length;
1215 remaining -= buffer.length;
1217 memcpy(buffer.ptr, p1, remaining);
1218 memcpy(p1, p2, remaining);
1219 memcpy(p2, buffer.ptr, remaining);
1222 override const(void)[] initializer() nothrow pure const
1224 return value.initializer();
1227 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
1228 override @property uint flags() nothrow pure const { return value.flags; }
1230 override void destroy(void* p) const
1232 immutable sz = value.tsize;
1233 p += sz * len;
1234 foreach (i; 0 .. len)
1236 p -= sz;
1237 value.destroy(p);
1241 override void postblit(void* p) const
1243 immutable sz = value.tsize;
1244 foreach (i; 0 .. len)
1246 value.postblit(p);
1247 p += sz;
1251 TypeInfo value;
1252 size_t len;
1254 override @property size_t talign() nothrow pure const
1256 return value.talign;
1259 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1261 arg1 = typeid(void*);
1262 return 0;
1265 // just return the rtInfo of the element, we have no generic type T to run RTInfo!T on
1266 override @property immutable(void)* rtInfo() nothrow pure const @safe { return value.rtInfo(); }
1269 // https://issues.dlang.org/show_bug.cgi?id=21315
1270 @system unittest
1272 int[16] a, b;
1273 foreach (int i; 0 .. 16)
1275 a[i] = i;
1276 b[i] = ~i;
1278 typeid(int[16]).swap(&a, &b);
1279 foreach (int i; 0 .. 16)
1281 assert(a[i] == ~i);
1282 assert(b[i] == i);
1286 class TypeInfo_AssociativeArray : TypeInfo
1288 override string toString() const
1290 return value.toString() ~ "[" ~ key.toString() ~ "]";
1293 override bool opEquals(Object o)
1295 if (this is o)
1296 return true;
1297 auto c = cast(const TypeInfo_AssociativeArray)o;
1298 return c && this.key == c.key &&
1299 this.value == c.value;
1302 override bool equals(in void* p1, in void* p2) @trusted const
1304 return !!_aaEqual(this, *cast(const AA*) p1, *cast(const AA*) p2);
1307 override hash_t getHash(scope const void* p) nothrow @trusted const
1309 return _aaGetHash(cast(AA*)p, this);
1312 // BUG: need to add the rest of the functions
1314 override @property size_t tsize() nothrow pure const
1316 return (char[int]).sizeof;
1319 override const(void)[] initializer() const @trusted
1321 return (cast(void *)null)[0 .. (char[int]).sizeof];
1324 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
1325 override @property uint flags() nothrow pure const { return 1; }
1327 TypeInfo value;
1328 TypeInfo key;
1330 override @property size_t talign() nothrow pure const
1332 return (char[int]).alignof;
1335 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1337 arg1 = typeid(void*);
1338 return 0;
1342 class TypeInfo_Vector : TypeInfo
1344 override string toString() const { return "__vector(" ~ base.toString() ~ ")"; }
1346 override bool opEquals(Object o)
1348 if (this is o)
1349 return true;
1350 auto c = cast(const TypeInfo_Vector)o;
1351 return c && this.base == c.base;
1354 override size_t getHash(scope const void* p) const { return base.getHash(p); }
1355 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
1356 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
1357 override @property size_t tsize() nothrow pure const { return base.tsize; }
1358 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
1360 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
1361 override @property uint flags() nothrow pure const { return 2; /* passed in SIMD register */ }
1363 override const(void)[] initializer() nothrow pure const
1365 return base.initializer();
1368 override @property size_t talign() nothrow pure const { return 16; }
1370 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1372 return base.argTypes(arg1, arg2);
1375 TypeInfo base;
1378 class TypeInfo_Function : TypeInfo
1380 override string toString() const pure @trusted
1382 import core.demangle : demangleType;
1384 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
1385 SafeDemangleFunctionType demangle = cast(SafeDemangleFunctionType) &demangleType;
1387 return cast(string) demangle(deco);
1390 override bool opEquals(Object o)
1392 if (this is o)
1393 return true;
1394 auto c = cast(const TypeInfo_Function)o;
1395 return c && this.deco == c.deco;
1398 // BUG: need to add the rest of the functions
1400 override @property size_t tsize() nothrow pure const
1402 return 0; // no size for functions
1405 override const(void)[] initializer() const @safe
1407 return null;
1410 override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
1412 TypeInfo next;
1415 * Mangled function type string
1417 string deco;
1420 @safe unittest
1422 abstract class C
1424 void func();
1425 void func(int a);
1426 int func(int a, int b);
1429 alias functionTypes = typeof(__traits(getVirtualMethods, C, "func"));
1430 assert(typeid(functionTypes[0]).toString() == "void function()");
1431 assert(typeid(functionTypes[1]).toString() == "void function(int)");
1432 assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
1435 @system unittest
1437 abstract class C
1439 void func();
1440 void func(int a);
1443 alias functionTypes = typeof(__traits(getVirtualMethods, C, "func"));
1445 Object obj = typeid(functionTypes[0]);
1446 assert(obj.opEquals(typeid(functionTypes[0])));
1447 assert(typeid(functionTypes[0]) == typeid(functionTypes[0]));
1448 assert(typeid(functionTypes[0]) != typeid(functionTypes[1]));
1450 assert(typeid(functionTypes[0]).tsize() == 0);
1451 assert(typeid(functionTypes[0]).initializer() is null);
1452 assert(typeid(functionTypes[0]).rtInfo() is null);
1455 class TypeInfo_Delegate : TypeInfo
1457 override string toString() const pure @trusted
1459 import core.demangle : demangleType;
1461 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
1462 SafeDemangleFunctionType demangle = cast(SafeDemangleFunctionType) &demangleType;
1464 return cast(string) demangle(deco);
1467 @safe unittest
1469 double sqr(double x) { return x * x; }
1470 sqr(double.init); // for coverage completeness
1472 auto delegate_str = "double delegate(double) pure nothrow @nogc @safe";
1474 assert(typeid(typeof(&sqr)).toString() == delegate_str);
1475 assert(delegate_str.hashOf() == typeid(typeof(&sqr)).hashOf());
1476 assert(typeid(typeof(&sqr)).toHash() == typeid(typeof(&sqr)).hashOf());
1478 int g;
1480 alias delegate_type = typeof((int a, int b) => a + b + g);
1481 delegate_str = "int delegate(int, int) pure nothrow @nogc @safe";
1483 assert(typeid(delegate_type).toString() == delegate_str);
1484 assert(delegate_str.hashOf() == typeid(delegate_type).hashOf());
1485 assert(typeid(delegate_type).toHash() == typeid(delegate_type).hashOf());
1488 override bool opEquals(Object o)
1490 if (this is o)
1491 return true;
1492 auto c = cast(const TypeInfo_Delegate)o;
1493 return c && this.deco == c.deco;
1496 @system unittest
1498 double sqr(double x) { return x * x; }
1499 int dbl(int x) { return x + x; }
1500 sqr(double.init); // for coverage completeness
1501 dbl(int.init); // for coverage completeness
1503 Object obj = typeid(typeof(&sqr));
1504 assert(obj.opEquals(typeid(typeof(&sqr))));
1505 assert(typeid(typeof(&sqr)) == typeid(typeof(&sqr)));
1506 assert(typeid(typeof(&dbl)) != typeid(typeof(&sqr)));
1509 override size_t getHash(scope const void* p) @trusted const
1511 return hashOf(*cast(const void delegate() *)p);
1514 override bool equals(in void* p1, in void* p2) const
1516 auto dg1 = *cast(void delegate()*)p1;
1517 auto dg2 = *cast(void delegate()*)p2;
1518 return dg1 == dg2;
1521 override int compare(in void* p1, in void* p2) const
1523 auto dg1 = *cast(void delegate()*)p1;
1524 auto dg2 = *cast(void delegate()*)p2;
1526 if (dg1 < dg2)
1527 return -1;
1528 else if (dg1 > dg2)
1529 return 1;
1530 else
1531 return 0;
1534 override @property size_t tsize() nothrow pure const
1536 alias dg = int delegate();
1537 return dg.sizeof;
1540 override const(void)[] initializer() const @trusted
1542 return (cast(void *)null)[0 .. (int delegate()).sizeof];
1545 override @property uint flags() nothrow pure const { return 1; }
1547 TypeInfo next;
1548 string deco;
1550 override @property size_t talign() nothrow pure const
1552 alias dg = int delegate();
1553 return dg.alignof;
1556 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1558 arg1 = typeid(void*);
1559 arg2 = typeid(void*);
1560 return 0;
1563 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(int delegate()); }
1566 private extern (C) Object _d_newclass(const TypeInfo_Class ci);
1567 private extern (C) int _d_isbaseof(scope TypeInfo_Class child,
1568 scope const TypeInfo_Class parent) @nogc nothrow pure @safe; // rt.cast_
1571 * Runtime type information about a class.
1572 * Can be retrieved from an object instance by using the
1573 * $(DDSUBLINK spec/expression,typeid_expressions,typeid expression).
1575 class TypeInfo_Class : TypeInfo
1577 override string toString() const pure { return name; }
1579 override bool opEquals(const TypeInfo o) const
1581 if (this is o)
1582 return true;
1583 auto c = cast(const TypeInfo_Class)o;
1584 return c && this.name == c.name;
1587 override size_t getHash(scope const void* p) @trusted const
1589 auto o = *cast(Object*)p;
1590 return o ? o.toHash() : 0;
1593 override bool equals(in void* p1, in void* p2) const
1595 Object o1 = *cast(Object*)p1;
1596 Object o2 = *cast(Object*)p2;
1598 return (o1 is o2) || (o1 && o1.opEquals(o2));
1601 override int compare(in void* p1, in void* p2) const
1603 Object o1 = *cast(Object*)p1;
1604 Object o2 = *cast(Object*)p2;
1605 int c = 0;
1607 // Regard null references as always being "less than"
1608 if (o1 !is o2)
1610 if (o1)
1612 if (!o2)
1613 c = 1;
1614 else
1615 c = o1.opCmp(o2);
1617 else
1618 c = -1;
1620 return c;
1623 override @property size_t tsize() nothrow pure const
1625 return Object.sizeof;
1628 override const(void)[] initializer() nothrow pure const @safe
1630 return m_init;
1633 override @property uint flags() nothrow pure const { return 1; }
1635 override @property const(OffsetTypeInfo)[] offTi() nothrow pure const
1637 return m_offTi;
1640 final @property auto info() @safe @nogc nothrow pure const return { return this; }
1641 final @property auto typeinfo() @safe @nogc nothrow pure const return { return this; }
1643 byte[] m_init; /** class static initializer
1644 * (init.length gives size in bytes of class)
1646 string name; /// class name
1647 void*[] vtbl; /// virtual function pointer table
1648 Interface[] interfaces; /// interfaces this class implements
1649 TypeInfo_Class base; /// base class
1650 void* destructor;
1651 void function(Object) classInvariant;
1652 enum ClassFlags : ushort
1654 isCOMclass = 0x1,
1655 noPointers = 0x2,
1656 hasOffTi = 0x4,
1657 hasCtor = 0x8,
1658 hasGetMembers = 0x10,
1659 hasTypeInfo = 0x20,
1660 isAbstract = 0x40,
1661 isCPPclass = 0x80,
1662 hasDtor = 0x100,
1663 hasNameSig = 0x200,
1665 ClassFlags m_flags;
1666 ushort depth; /// inheritance distance from Object
1667 void* deallocator;
1668 OffsetTypeInfo[] m_offTi;
1669 void function(Object) defaultConstructor; // default Constructor
1671 immutable(void)* m_RTInfo; // data for precise GC
1672 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
1674 uint[4] nameSig; /// unique signature for `name`
1677 * Search all modules for TypeInfo_Class corresponding to classname.
1678 * Returns: null if not found
1680 static const(TypeInfo_Class) find(const scope char[] classname)
1682 foreach (m; ModuleInfo)
1684 if (m)
1686 //writefln("module %s, %d", m.name, m.localClasses.length);
1687 foreach (c; m.localClasses)
1689 if (c is null)
1690 continue;
1691 //writefln("\tclass %s", c.name);
1692 if (c.name == classname)
1693 return c;
1697 return null;
1701 * Create instance of Object represented by 'this'.
1703 Object create() const
1705 if (m_flags & 8 && !defaultConstructor)
1706 return null;
1707 if (m_flags & 64) // abstract
1708 return null;
1709 Object o = _d_newclass(this);
1710 if (m_flags & 8 && defaultConstructor)
1712 defaultConstructor(o);
1714 return o;
1718 * Returns true if the class described by `child` derives from or is
1719 * the class described by this `TypeInfo_Class`. Always returns false
1720 * if the argument is null.
1722 * Params:
1723 * child = TypeInfo for some class
1724 * Returns:
1725 * true if the class described by `child` derives from or is the
1726 * class described by this `TypeInfo_Class`.
1728 final bool isBaseOf(scope const TypeInfo_Class child) const @nogc nothrow pure @trusted
1730 if (m_init.length)
1732 // If this TypeInfo_Class represents an actual class we only need
1733 // to check the child and its direct ancestors.
1734 for (auto ti = cast() child; ti !is null; ti = ti.base)
1735 if (ti is this)
1736 return true;
1737 return false;
1739 else
1741 // If this TypeInfo_Class is the .info field of a TypeInfo_Interface
1742 // we also need to recursively check the child's interfaces.
1743 return child !is null && _d_isbaseof(cast() child, this);
1748 alias ClassInfo = TypeInfo_Class;
1750 @safe unittest
1752 // Bugzilla 14401
1753 static class X
1755 int a;
1758 assert(typeid(X).initializer is typeid(X).m_init);
1759 assert(typeid(X).initializer.length == typeid(const(X)).initializer.length);
1760 assert(typeid(X).initializer.length == typeid(shared(X)).initializer.length);
1761 assert(typeid(X).initializer.length == typeid(immutable(X)).initializer.length);
1764 class TypeInfo_Interface : TypeInfo
1766 override string toString() const pure { return info.name; }
1768 override bool opEquals(Object o)
1770 if (this is o)
1771 return true;
1772 auto c = cast(const TypeInfo_Interface)o;
1773 return c && this.info.name == typeid(c).name;
1776 override size_t getHash(scope const void* p) @trusted const
1778 if (!*cast(void**)p)
1780 return 0;
1782 Interface* pi = **cast(Interface ***)*cast(void**)p;
1783 Object o = cast(Object)(*cast(void**)p - pi.offset);
1784 assert(o);
1785 return o.toHash();
1788 override bool equals(in void* p1, in void* p2) const
1790 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1791 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1792 pi = **cast(Interface ***)*cast(void**)p2;
1793 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1795 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
1798 override int compare(in void* p1, in void* p2) const
1800 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1801 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1802 pi = **cast(Interface ***)*cast(void**)p2;
1803 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1804 int c = 0;
1806 // Regard null references as always being "less than"
1807 if (o1 != o2)
1809 if (o1)
1811 if (!o2)
1812 c = 1;
1813 else
1814 c = o1.opCmp(o2);
1816 else
1817 c = -1;
1819 return c;
1822 override @property size_t tsize() nothrow pure const
1824 return Object.sizeof;
1827 override const(void)[] initializer() const @trusted
1829 return (cast(void *)null)[0 .. Object.sizeof];
1832 override @property uint flags() nothrow pure const { return 1; }
1834 TypeInfo_Class info;
1837 * Returns true if the class described by `child` derives from the
1838 * interface described by this `TypeInfo_Interface`. Always returns
1839 * false if the argument is null.
1841 * Params:
1842 * child = TypeInfo for some class
1843 * Returns:
1844 * true if the class described by `child` derives from the
1845 * interface described by this `TypeInfo_Interface`.
1847 final bool isBaseOf(scope const TypeInfo_Class child) const @nogc nothrow pure @trusted
1849 return child !is null && _d_isbaseof(cast() child, this.info);
1853 * Returns true if the interface described by `child` derives from
1854 * or is the interface described by this `TypeInfo_Interface`.
1855 * Always returns false if the argument is null.
1857 * Params:
1858 * child = TypeInfo for some interface
1859 * Returns:
1860 * true if the interface described by `child` derives from or is
1861 * the interface described by this `TypeInfo_Interface`.
1863 final bool isBaseOf(scope const TypeInfo_Interface child) const @nogc nothrow pure @trusted
1865 return child !is null && _d_isbaseof(cast() child.info, this.info);
1869 @safe unittest
1871 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
1872 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
1874 interface I {}
1876 assert(fqn_unittest ~ ".I" == typeid(I).info.name);
1877 assert((fqn_unittest ~ ".I").hashOf() == typeid(I).hashOf());
1878 assert(typeid(I).toHash() == typeid(I).hashOf());
1881 class TypeInfo_Struct : TypeInfo
1883 override string toString() const { return name; }
1885 override size_t toHash() const
1887 return hashOf(this.mangledName);
1890 override bool opEquals(Object o)
1892 if (this is o)
1893 return true;
1894 auto s = cast(const TypeInfo_Struct)o;
1895 return s && this.mangledName == s.mangledName;
1898 override size_t getHash(scope const void* p) @trusted pure nothrow const
1900 assert(p);
1901 if (xtoHash)
1903 return (*xtoHash)(p);
1905 else
1907 return hashOf(p[0 .. initializer().length]);
1911 override bool equals(in void* p1, in void* p2) @trusted pure nothrow const
1913 import core.stdc.string : memcmp;
1915 if (!p1 || !p2)
1916 return false;
1917 else if (xopEquals)
1919 const dg = _memberFunc(p1, xopEquals);
1920 return dg.xopEquals(p2);
1922 else if (p1 == p2)
1923 return true;
1924 else
1925 // BUG: relies on the GC not moving objects
1926 return memcmp(p1, p2, initializer().length) == 0;
1929 override int compare(in void* p1, in void* p2) @trusted pure nothrow const
1931 import core.stdc.string : memcmp;
1933 // Regard null references as always being "less than"
1934 if (p1 != p2)
1936 if (p1)
1938 if (!p2)
1939 return true;
1940 else if (xopCmp)
1942 const dg = _memberFunc(p1, xopCmp);
1943 return dg.xopCmp(p2);
1945 else
1946 // BUG: relies on the GC not moving objects
1947 return memcmp(p1, p2, initializer().length);
1949 else
1950 return -1;
1952 return 0;
1955 override @property size_t tsize() nothrow pure const
1957 return initializer().length;
1960 override const(void)[] initializer() nothrow pure const @safe
1962 return m_init;
1965 override @property uint flags() nothrow pure const { return m_flags; }
1967 override @property size_t talign() nothrow pure const { return m_align; }
1969 final override void destroy(void* p) const
1971 if (xdtor)
1973 if (m_flags & StructFlags.isDynamicType)
1974 (*xdtorti)(p, this);
1975 else
1976 (*xdtor)(p);
1980 override void postblit(void* p) const
1982 if (xpostblit)
1983 (*xpostblit)(p);
1986 string mangledName;
1988 final @property string name() nothrow const @trusted
1990 import core.demangle : demangleType;
1992 if (mangledName is null) // e.g., opaque structs
1993 return null;
1995 const key = cast(const void*) this; // faster lookup than TypeInfo_Struct, at the cost of potential duplicates per binary
1996 static string[typeof(key)] demangledNamesCache; // per thread
1998 // not nothrow:
1999 //return demangledNamesCache.require(key, cast(string) demangleType(mangledName));
2001 if (auto pDemangled = key in demangledNamesCache)
2002 return *pDemangled;
2004 const demangled = cast(string) demangleType(mangledName);
2005 demangledNamesCache[key] = demangled;
2006 return demangled;
2009 void[] m_init; // initializer; m_init.ptr == null if 0 initialize
2011 @safe pure nothrow
2013 size_t function(in void*) xtoHash;
2014 bool function(in void*, in void*) xopEquals;
2015 int function(in void*, in void*) xopCmp;
2016 string function(in void*) xtoString;
2018 enum StructFlags : uint
2020 hasPointers = 0x1,
2021 isDynamicType = 0x2, // built at runtime, needs type info in xdtor
2023 StructFlags m_flags;
2025 union
2027 void function(void*) xdtor;
2028 void function(void*, const TypeInfo_Struct ti) xdtorti;
2030 void function(void*) xpostblit;
2032 uint m_align;
2034 override @property immutable(void)* rtInfo() nothrow pure const @safe { return m_RTInfo; }
2036 version (WithArgTypes)
2038 override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2040 arg1 = m_arg1;
2041 arg2 = m_arg2;
2042 return 0;
2044 TypeInfo m_arg1;
2045 TypeInfo m_arg2;
2047 immutable(void)* m_RTInfo; // data for precise GC
2049 // The xopEquals and xopCmp members are function pointers to member
2050 // functions, which is not guaranteed to share the same ABI, as it is not
2051 // known whether the `this` parameter is the first or second argument.
2052 // This wrapper is to convert it to a delegate which will always pass the
2053 // `this` parameter in the correct way.
2054 private struct _memberFunc
2056 union
2058 struct // delegate
2060 const void* ptr;
2061 const void* funcptr;
2063 @safe pure nothrow
2065 bool delegate(in void*) xopEquals;
2066 int delegate(in void*) xopCmp;
2072 @system unittest
2074 struct S
2076 bool opEquals(ref const S rhs) const
2078 return false;
2081 S s;
2082 assert(!typeid(S).equals(&s, &s));
2085 class TypeInfo_Tuple : TypeInfo
2087 TypeInfo[] elements;
2089 override string toString() const
2091 string s = "(";
2092 foreach (i, element; elements)
2094 if (i)
2095 s ~= ',';
2096 s ~= element.toString();
2098 s ~= ")";
2099 return s;
2102 override bool opEquals(Object o)
2104 if (this is o)
2105 return true;
2107 auto t = cast(const TypeInfo_Tuple)o;
2108 if (t && elements.length == t.elements.length)
2110 for (size_t i = 0; i < elements.length; i++)
2112 if (elements[i] != t.elements[i])
2113 return false;
2115 return true;
2117 return false;
2120 override size_t getHash(scope const void* p) const
2122 assert(0);
2125 override bool equals(in void* p1, in void* p2) const
2127 assert(0);
2130 override int compare(in void* p1, in void* p2) const
2132 assert(0);
2135 override @property size_t tsize() nothrow pure const
2137 assert(0);
2140 override const(void)[] initializer() const @trusted
2142 assert(0);
2145 override void swap(void* p1, void* p2) const
2147 assert(0);
2150 override void destroy(void* p) const
2152 assert(0);
2155 override void postblit(void* p) const
2157 assert(0);
2160 override @property size_t talign() nothrow pure const
2162 assert(0);
2165 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2167 assert(0);
2171 class TypeInfo_Const : TypeInfo
2173 override string toString() const
2175 return cast(string) ("const(" ~ base.toString() ~ ")");
2178 //override bool opEquals(Object o) { return base.opEquals(o); }
2179 override bool opEquals(Object o)
2181 if (this is o)
2182 return true;
2184 if (typeid(this) != typeid(o))
2185 return false;
2187 auto t = cast(TypeInfo_Const)o;
2188 return base.opEquals(t.base);
2191 override size_t getHash(scope const void *p) const { return base.getHash(p); }
2192 override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); }
2193 override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); }
2194 override @property size_t tsize() nothrow pure const { return base.tsize; }
2195 override void swap(void *p1, void *p2) const { return base.swap(p1, p2); }
2197 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
2198 override @property uint flags() nothrow pure const { return base.flags; }
2200 override const(void)[] initializer() nothrow pure const
2202 return base.initializer();
2205 override @property size_t talign() nothrow pure const { return base.talign; }
2207 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2209 return base.argTypes(arg1, arg2);
2212 TypeInfo base;
2215 class TypeInfo_Invariant : TypeInfo_Const
2217 override string toString() const
2219 return cast(string) ("immutable(" ~ base.toString() ~ ")");
2223 class TypeInfo_Shared : TypeInfo_Const
2225 override string toString() const
2227 return cast(string) ("shared(" ~ base.toString() ~ ")");
2231 class TypeInfo_Inout : TypeInfo_Const
2233 override string toString() const
2235 return cast(string) ("inout(" ~ base.toString() ~ ")");
2239 // Contents of Moduleinfo._flags
2240 enum
2242 MIctorstart = 0x1, // we've started constructing it
2243 MIctordone = 0x2, // finished construction
2244 MIstandalone = 0x4, // module ctor does not depend on other module
2245 // ctors being done first
2246 MItlsctor = 8,
2247 MItlsdtor = 0x10,
2248 MIctor = 0x20,
2249 MIdtor = 0x40,
2250 MIxgetMembers = 0x80,
2251 MIictor = 0x100,
2252 MIunitTest = 0x200,
2253 MIimportedModules = 0x400,
2254 MIlocalClasses = 0x800,
2255 MIname = 0x1000,
2258 /*****************************************
2259 * An instance of ModuleInfo is generated into the object file for each compiled module.
2261 * It provides access to various aspects of the module.
2262 * It is not generated for betterC.
2264 struct ModuleInfo
2266 uint _flags; // MIxxxx
2267 uint _index; // index into _moduleinfo_array[]
2269 version (all)
2271 deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
2272 void opAssign(const scope ModuleInfo m) { _flags = m._flags; _index = m._index; }
2274 else
2276 @disable this();
2279 const:
2280 private void* addrOf(int flag) return nothrow pure @nogc
2283 assert(flag >= MItlsctor && flag <= MIname);
2284 assert(!(flag & (flag - 1)) && !(flag & ~(flag - 1) << 1));
2288 import core.stdc.string : strlen;
2290 void* p = cast(void*)&this + ModuleInfo.sizeof;
2292 if (flags & MItlsctor)
2294 if (flag == MItlsctor) return p;
2295 p += typeof(tlsctor).sizeof;
2297 if (flags & MItlsdtor)
2299 if (flag == MItlsdtor) return p;
2300 p += typeof(tlsdtor).sizeof;
2302 if (flags & MIctor)
2304 if (flag == MIctor) return p;
2305 p += typeof(ctor).sizeof;
2307 if (flags & MIdtor)
2309 if (flag == MIdtor) return p;
2310 p += typeof(dtor).sizeof;
2312 if (flags & MIxgetMembers)
2314 if (flag == MIxgetMembers) return p;
2315 p += typeof(xgetMembers).sizeof;
2317 if (flags & MIictor)
2319 if (flag == MIictor) return p;
2320 p += typeof(ictor).sizeof;
2322 if (flags & MIunitTest)
2324 if (flag == MIunitTest) return p;
2325 p += typeof(unitTest).sizeof;
2327 if (flags & MIimportedModules)
2329 if (flag == MIimportedModules) return p;
2330 p += size_t.sizeof + *cast(size_t*)p * typeof(importedModules[0]).sizeof;
2332 if (flags & MIlocalClasses)
2334 if (flag == MIlocalClasses) return p;
2335 p += size_t.sizeof + *cast(size_t*)p * typeof(localClasses[0]).sizeof;
2337 if (true || flags & MIname) // always available for now
2339 if (flag == MIname) return p;
2340 p += strlen(cast(immutable char*)p);
2342 assert(0);
2345 @property uint index() nothrow pure @nogc { return _index; }
2347 @property uint flags() nothrow pure @nogc { return _flags; }
2349 /************************
2350 * Returns:
2351 * module constructor for thread locals, `null` if there isn't one
2353 @property void function() tlsctor() nothrow pure @nogc
2355 return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null;
2358 /************************
2359 * Returns:
2360 * module destructor for thread locals, `null` if there isn't one
2362 @property void function() tlsdtor() nothrow pure @nogc
2364 return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null;
2367 /*****************************
2368 * Returns:
2369 * address of a module's `const(MemberInfo)[] getMembers(string)` function, `null` if there isn't one
2371 @property void* xgetMembers() nothrow pure @nogc
2373 return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null;
2376 /************************
2377 * Returns:
2378 * module constructor, `null` if there isn't one
2380 @property void function() ctor() nothrow pure @nogc
2382 return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null;
2385 /************************
2386 * Returns:
2387 * module destructor, `null` if there isn't one
2389 @property void function() dtor() nothrow pure @nogc
2391 return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null;
2394 /************************
2395 * Returns:
2396 * module order independent constructor, `null` if there isn't one
2398 @property void function() ictor() nothrow pure @nogc
2400 return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null;
2403 /*************
2404 * Returns:
2405 * address of function that runs the module's unittests, `null` if there isn't one
2407 @property void function() unitTest() nothrow pure @nogc
2409 return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null;
2412 /****************
2413 * Returns:
2414 * array of pointers to the ModuleInfo's of modules imported by this one
2416 @property immutable(ModuleInfo*)[] importedModules() return nothrow pure @nogc
2418 if (flags & MIimportedModules)
2420 auto p = cast(size_t*)addrOf(MIimportedModules);
2421 return (cast(immutable(ModuleInfo*)*)(p + 1))[0 .. *p];
2423 return null;
2426 /****************
2427 * Returns:
2428 * array of TypeInfo_Class references for classes defined in this module
2430 @property TypeInfo_Class[] localClasses() return nothrow pure @nogc
2432 if (flags & MIlocalClasses)
2434 auto p = cast(size_t*)addrOf(MIlocalClasses);
2435 return (cast(TypeInfo_Class*)(p + 1))[0 .. *p];
2437 return null;
2440 /********************
2441 * Returns:
2442 * name of module, `null` if no name
2444 @property string name() return nothrow pure @nogc
2446 import core.stdc.string : strlen;
2448 auto p = cast(immutable char*) addrOf(MIname);
2449 return p[0 .. strlen(p)];
2452 static int opApply(scope int delegate(ModuleInfo*) dg)
2454 import core.internal.traits : externDFunc;
2455 alias moduleinfos_apply = externDFunc!("rt.minfo.moduleinfos_apply",
2456 int function(scope int delegate(immutable(ModuleInfo*))));
2457 // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
2458 return moduleinfos_apply(
2459 (immutable(ModuleInfo*)m) => dg(cast(ModuleInfo*)m));
2463 @system unittest
2465 ModuleInfo* m1;
2466 foreach (m; ModuleInfo)
2468 m1 = m;
2472 ///////////////////////////////////////////////////////////////////////////////
2473 // Throwable
2474 ///////////////////////////////////////////////////////////////////////////////
2478 * The base class of all thrown objects.
2480 * All thrown objects must inherit from Throwable. Class $(D Exception), which
2481 * derives from this class, represents the category of thrown objects that are
2482 * safe to catch and handle. In principle, one should not catch Throwable
2483 * objects that are not derived from $(D Exception), as they represent
2484 * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
2485 * when these errors are thrown, making it unsafe to continue execution after
2486 * catching them.
2488 class Throwable : Object
2490 interface TraceInfo
2492 int opApply(scope int delegate(ref const(char[]))) const;
2493 int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
2494 string toString() const;
2497 alias TraceDeallocator = void function(TraceInfo) nothrow;
2499 string msg; /// A message describing the error.
2502 * The _file name of the D source code corresponding with
2503 * where the error was thrown from.
2505 string file;
2507 * The _line number of the D source code corresponding with
2508 * where the error was thrown from.
2510 size_t line;
2513 * The stack trace of where the error happened. This is an opaque object
2514 * that can either be converted to $(D string), or iterated over with $(D
2515 * foreach) to extract the items in the stack trace (as strings).
2517 TraceInfo info;
2520 * If set, this is used to deallocate the TraceInfo on destruction.
2522 TraceDeallocator infoDeallocator;
2526 * A reference to the _next error in the list. This is used when a new
2527 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2528 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2529 * field.
2531 private Throwable nextInChain;
2533 private uint _refcount; // 0 : allocated by GC
2534 // 1 : allocated by _d_newThrowable()
2535 // 2.. : reference count + 1
2538 * Returns:
2539 * A reference to the _next error in the list. This is used when a new
2540 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2541 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2542 * field.
2544 @property inout(Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; }
2547 * Replace next in chain with `tail`.
2548 * Use `chainTogether` instead if at all possible.
2550 @property void next(Throwable tail) @safe scope pure nothrow @nogc
2552 if (tail && tail._refcount)
2553 ++tail._refcount; // increment the replacement *first*
2555 auto n = nextInChain;
2556 nextInChain = null; // sever the tail before deleting it
2558 if (n && n._refcount)
2559 _d_delThrowable(n); // now delete the old tail
2561 nextInChain = tail; // and set the new tail
2565 * Returns:
2566 * mutable reference to the reference count, which is
2567 * 0 - allocated by the GC, 1 - allocated by _d_newThrowable(),
2568 * and >=2 which is the reference count + 1
2569 * Note:
2570 * Marked as `@system` to discourage casual use of it.
2572 @system @nogc final pure nothrow ref uint refcount() return { return _refcount; }
2575 * Loop over the chain of Throwables.
2577 int opApply(scope int delegate(Throwable) dg)
2579 int result = 0;
2580 for (Throwable t = this; t; t = t.nextInChain)
2582 result = dg(t);
2583 if (result)
2584 break;
2586 return result;
2590 * Append `e2` to chain of exceptions that starts with `e1`.
2591 * Params:
2592 * e1 = start of chain (can be null)
2593 * e2 = second part of chain (can be null)
2594 * Returns:
2595 * Throwable that is at the start of the chain; null if both `e1` and `e2` are null
2597 static @__future @system @nogc pure nothrow Throwable chainTogether(return scope Throwable e1, return scope Throwable e2)
2599 if (!e1)
2600 return e2;
2601 if (!e2)
2602 return e1;
2603 if (e2.refcount())
2604 ++e2.refcount();
2606 for (auto e = e1; 1; e = e.nextInChain)
2608 if (!e.nextInChain)
2610 e.nextInChain = e2;
2611 break;
2614 return e1;
2617 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2619 this.msg = msg;
2620 this.nextInChain = nextInChain;
2621 if (nextInChain && nextInChain._refcount)
2622 ++nextInChain._refcount;
2623 //this.info = _d_traceContext();
2626 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2628 this(msg, nextInChain);
2629 this.file = file;
2630 this.line = line;
2631 //this.info = _d_traceContext();
2634 @trusted nothrow ~this()
2636 if (nextInChain && nextInChain._refcount)
2637 _d_delThrowable(nextInChain);
2638 // handle owned traceinfo
2639 if (infoDeallocator !is null)
2641 infoDeallocator(info);
2642 info = null; // avoid any kind of dangling pointers if we can help
2643 // it.
2648 * Overrides $(D Object.toString) and returns the error message.
2649 * Internally this forwards to the $(D toString) overload that
2650 * takes a $(D_PARAM sink) delegate.
2652 override string toString()
2654 string s;
2655 toString((in buf) { s ~= buf; });
2656 return s;
2660 * The Throwable hierarchy uses a toString overload that takes a
2661 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
2662 * performed in certain error situations. Override this $(D
2663 * toString) method to customize the error message.
2665 void toString(scope void delegate(in char[]) sink) const
2667 import core.internal.string : unsignedToTempString;
2669 char[20] tmpBuff = void;
2671 sink(typeid(this).name);
2672 sink("@"); sink(file);
2673 sink("("); sink(unsignedToTempString(line, tmpBuff)); sink(")");
2675 if (msg.length)
2677 sink(": "); sink(msg);
2679 if (info)
2683 sink("\n----------------");
2684 foreach (t; info)
2686 sink("\n"); sink(t);
2689 catch (Throwable)
2691 // ignore more errors
2697 * Get the message describing the error.
2699 * This getter is an alternative way to access the Exception's message,
2700 * with the added advantage of being override-able in subclasses.
2701 * Subclasses are hence free to do their own memory managements without
2702 * being tied to the requirement of providing a `string` in a field.
2704 * The default behavior is to return the `Throwable.msg` field.
2706 * Returns:
2707 * A message representing the cause of the `Throwable`
2709 @__future const(char)[] message() const @safe nothrow
2711 return this.msg;
2717 * The base class of all errors that are safe to catch and handle.
2719 * In principle, only thrown objects derived from this class are safe to catch
2720 * inside a $(D catch) block. Thrown objects not derived from Exception
2721 * represent runtime errors that should not be caught, as certain runtime
2722 * guarantees may not hold, making it unsafe to continue program execution.
2724 class Exception : Throwable
2728 * Creates a new instance of Exception. The nextInChain parameter is used
2729 * internally and should always be $(D null) when passed by user code.
2730 * This constructor does not automatically throw the newly-created
2731 * Exception; the $(D throw) expression should be used for that purpose.
2733 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
2735 super(msg, file, line, nextInChain);
2738 @nogc @safe pure nothrow this(string msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__)
2740 super(msg, file, line, nextInChain);
2745 @safe unittest
2747 bool gotCaught;
2750 throw new Exception("msg");
2752 catch (Exception e)
2754 gotCaught = true;
2755 assert(e.msg == "msg");
2757 assert(gotCaught);
2760 @system unittest
2763 auto e = new Exception("msg");
2764 assert(e.file == __FILE__);
2765 assert(e.line == __LINE__ - 2);
2766 assert(e.nextInChain is null);
2767 assert(e.msg == "msg");
2771 auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
2772 assert(e.file == "hello");
2773 assert(e.line == 42);
2774 assert(e.nextInChain !is null);
2775 assert(e.msg == "msg");
2779 auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
2780 assert(e.file == "hello");
2781 assert(e.line == 42);
2782 assert(e.nextInChain !is null);
2783 assert(e.msg == "msg");
2787 auto e = new Exception("message");
2788 assert(e.message == "message");
2794 * The base class of all unrecoverable runtime errors.
2796 * This represents the category of $(D Throwable) objects that are $(B not)
2797 * safe to catch and handle. In principle, one should not catch Error
2798 * objects, as they represent unrecoverable runtime errors.
2799 * Certain runtime guarantees may fail to hold when these errors are
2800 * thrown, making it unsafe to continue execution after catching them.
2802 class Error : Throwable
2805 * Creates a new instance of Error. The nextInChain parameter is used
2806 * internally and should always be $(D null) when passed by user code.
2807 * This constructor does not automatically throw the newly-created
2808 * Error; the $(D throw) statement should be used for that purpose.
2810 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2812 super(msg, nextInChain);
2813 bypassedException = null;
2816 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2818 super(msg, file, line, nextInChain);
2819 bypassedException = null;
2822 /** The first $(D Exception) which was bypassed when this Error was thrown,
2823 or $(D null) if no $(D Exception)s were pending. */
2824 Throwable bypassedException;
2828 @system unittest
2830 bool gotCaught;
2833 throw new Error("msg");
2835 catch (Error e)
2837 gotCaught = true;
2838 assert(e.msg == "msg");
2840 assert(gotCaught);
2843 @safe unittest
2846 auto e = new Error("msg");
2847 assert(e.file is null);
2848 assert(e.line == 0);
2849 assert(e.nextInChain is null);
2850 assert(e.msg == "msg");
2851 assert(e.bypassedException is null);
2855 auto e = new Error("msg", new Exception("It's an Exception!"));
2856 assert(e.file is null);
2857 assert(e.line == 0);
2858 assert(e.nextInChain !is null);
2859 assert(e.msg == "msg");
2860 assert(e.bypassedException is null);
2864 auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
2865 assert(e.file == "hello");
2866 assert(e.line == 42);
2867 assert(e.nextInChain !is null);
2868 assert(e.msg == "msg");
2869 assert(e.bypassedException is null);
2873 extern (C)
2875 // from druntime/src/rt/aaA.d
2877 private struct AA { void* impl; }
2878 // size_t _aaLen(in AA aa) pure nothrow @nogc;
2879 private void* _aaGetY(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow;
2880 private void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow;
2881 // inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey);
2882 inout(void[]) _aaValues(inout AA aa, const size_t keysz, const size_t valsz, const TypeInfo tiValueArray) pure nothrow;
2883 inout(void[]) _aaKeys(inout AA aa, const size_t keysz, const TypeInfo tiKeyArray) pure nothrow;
2884 void* _aaRehash(AA* paa, const scope TypeInfo keyti) pure nothrow;
2885 void _aaClear(AA aa) pure nothrow;
2887 // alias _dg_t = extern(D) int delegate(void*);
2888 // int _aaApply(AA aa, size_t keysize, _dg_t dg);
2890 // alias _dg2_t = extern(D) int delegate(void*, void*);
2891 // int _aaApply2(AA aa, size_t keysize, _dg2_t dg);
2893 private struct AARange { AA impl; size_t idx; }
2894 AARange _aaRange(AA aa) pure nothrow @nogc @safe;
2895 bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe;
2896 void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe;
2897 void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe;
2898 void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe;
2900 int _aaEqual(scope const TypeInfo tiRaw, scope const AA aa1, scope const AA aa2);
2901 hash_t _aaGetHash(scope const AA* aa, scope const TypeInfo tiRaw) nothrow;
2904 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
2905 This is a typesystem hole, however this is existing hole.
2906 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
2907 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
2909 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure;
2912 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
2914 return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
2917 // Lower an Associative Array to a newaa struct for static initialization.
2918 auto _aaAsStruct(K, V)(V[K] aa) @safe
2920 import core.internal.newaa : makeAA;
2921 assert(__ctfe);
2922 return makeAA!(K, V)(aa);
2925 alias AssociativeArray(Key, Value) = Value[Key];
2927 /***********************************
2928 * Removes all remaining keys and values from an associative array.
2929 * Params:
2930 * aa = The associative array.
2932 void clear(Value, Key)(Value[Key] aa) @trusted
2934 _aaClear(*cast(AA *) &aa);
2937 /** ditto */
2938 void clear(Value, Key)(Value[Key]* aa) @trusted
2940 _aaClear(*cast(AA *) aa);
2944 @safe unittest
2946 auto aa = ["k1": 2];
2947 aa.clear;
2948 assert("k1" !in aa);
2951 // Issue 20559
2952 @system unittest
2954 static class Foo
2956 int[string] aa;
2957 alias aa this;
2960 auto v = new Foo();
2961 v["Hello World"] = 42;
2962 v.clear;
2963 assert("Hello World" !in v);
2965 // Test for T*
2966 static assert(!__traits(compiles, (&v).clear));
2967 static assert( __traits(compiles, (*(&v)).clear));
2970 /***********************************
2971 * Reorganizes the associative array in place so that lookups are more
2972 * efficient.
2973 * Params:
2974 * aa = The associative array.
2975 * Returns:
2976 * The rehashed associative array.
2978 T rehash(T : Value[Key], Value, Key)(T aa)
2980 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
2981 return aa;
2984 /** ditto */
2985 T rehash(T : Value[Key], Value, Key)(T* aa)
2987 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
2988 return *aa;
2991 /** ditto */
2992 T rehash(T : shared Value[Key], Value, Key)(T aa)
2994 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
2995 return aa;
2998 /** ditto */
2999 T rehash(T : shared Value[Key], Value, Key)(T* aa)
3001 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
3002 return *aa;
3005 /***********************************
3006 * Creates a new associative array of the same size and copies the contents of
3007 * the associative array into it.
3008 * Params:
3009 * aa = The associative array.
3011 V[K] dup(T : V[K], K, V)(T aa)
3013 //pragma(msg, "K = ", K, ", V = ", V);
3015 // Bug10720 - check whether V is copyable
3016 static assert(is(typeof({ V v = aa[K.init]; })),
3017 "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");
3019 V[K] result;
3021 //foreach (k, ref v; aa)
3022 // result[k] = v; // Bug13701 - won't work if V is not mutable
3024 ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow
3026 import core.stdc.string : memcpy;
3028 void* pv = _aaGetY(cast(AA*)&result, typeid(V[K]), V.sizeof, &k);
3029 memcpy(pv, &v, V.sizeof);
3030 return *cast(V*)pv;
3033 foreach (k, ref v; aa)
3035 static if (!__traits(hasPostblit, V))
3036 duplicateElem(k, v);
3037 else static if (__traits(isStaticArray, V))
3038 _doPostblit(duplicateElem(k, v)[]);
3039 else static if (!is(typeof(v.__xpostblit())) && is(immutable V == immutable UV, UV))
3040 (() @trusted => *cast(UV*) &duplicateElem(k, v))().__xpostblit();
3041 else
3042 duplicateElem(k, v).__xpostblit();
3045 return result;
3048 /** ditto */
3049 V[K] dup(T : V[K], K, V)(T* aa)
3051 return (*aa).dup;
3055 @safe unittest
3057 auto aa = ["k1": 2];
3058 auto a2 = aa.dup;
3059 aa["k2"] = 3;
3060 assert("k2" !in a2);
3063 // this should never be made public.
3064 private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe
3066 // ensure we are dealing with a genuine AA.
3067 static if (is(const(V[K]) == const(T)))
3068 alias realAA = aa;
3069 else
3070 const(V[K]) realAA = aa;
3071 return _aaRange(() @trusted { return *cast(AA*)&realAA; } ());
3074 /***********************************
3075 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3076 * which will iterate over the keys of the associative array. The keys are
3077 * returned by reference.
3079 * If structural changes are made to the array (removing or adding keys), all
3080 * ranges previously obtained through this function are invalidated. The
3081 * following example program will dereference a null pointer:
3083 *---
3084 * import std.stdio : writeln;
3086 * auto dict = ["k1": 1, "k2": 2];
3087 * auto keyRange = dict.byKey;
3088 * dict.clear;
3089 * writeln(keyRange.front); // Segmentation fault
3090 *---
3092 * Params:
3093 * aa = The associative array.
3094 * Returns:
3095 * A forward range referencing the keys of the associative array.
3097 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3099 import core.internal.traits : substInout;
3101 static struct Result
3103 AARange r;
3105 pure nothrow @nogc:
3106 @property bool empty() @safe { return _aaRangeEmpty(r); }
3107 @property ref front() @trusted
3109 return *cast(substInout!K*) _aaRangeFrontKey(r);
3111 void popFront() @safe { _aaRangePopFront(r); }
3112 @property Result save() { return this; }
3115 return Result(_aaToRange(aa));
3118 /** ditto */
3119 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
3121 return (*aa).byKey();
3125 @safe unittest
3127 auto dict = [1: "v1", 2: "v2"];
3128 int sum;
3129 foreach (v; dict.byKey)
3130 sum += v;
3132 assert(sum == 3);
3135 /***********************************
3136 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3137 * which will iterate over the values of the associative array. The values are
3138 * returned by reference.
3140 * If structural changes are made to the array (removing or adding keys), all
3141 * ranges previously obtained through this function are invalidated. The
3142 * following example program will dereference a null pointer:
3144 *---
3145 * import std.stdio : writeln;
3147 * auto dict = ["k1": 1, "k2": 2];
3148 * auto valueRange = dict.byValue;
3149 * dict.clear;
3150 * writeln(valueRange.front); // Segmentation fault
3151 *---
3153 * Params:
3154 * aa = The associative array.
3155 * Returns:
3156 * A forward range referencing the values of the associative array.
3158 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3160 import core.internal.traits : substInout;
3162 static struct Result
3164 AARange r;
3166 pure nothrow @nogc:
3167 @property bool empty() @safe { return _aaRangeEmpty(r); }
3168 @property ref front() @trusted
3170 return *cast(substInout!V*) _aaRangeFrontValue(r);
3172 void popFront() @safe { _aaRangePopFront(r); }
3173 @property Result save() { return this; }
3176 return Result(_aaToRange(aa));
3179 /** ditto */
3180 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3182 return (*aa).byValue();
3186 @safe unittest
3188 auto dict = ["k1": 1, "k2": 2];
3189 int sum;
3190 foreach (v; dict.byValue)
3191 sum += v;
3193 assert(sum == 3);
3196 /***********************************
3197 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3198 * which will iterate over the key-value pairs of the associative array. The
3199 * returned pairs are represented by an opaque type with `.key` and `.value`
3200 * properties for accessing references to the key and value of the pair,
3201 * respectively.
3203 * If structural changes are made to the array (removing or adding keys), all
3204 * ranges previously obtained through this function are invalidated. The
3205 * following example program will dereference a null pointer:
3207 *---
3208 * import std.stdio : writeln;
3210 * auto dict = ["k1": 1, "k2": 2];
3211 * auto kvRange = dict.byKeyValue;
3212 * dict.clear;
3213 * writeln(kvRange.front.key, ": ", kvRange.front.value); // Segmentation fault
3214 *---
3216 * Note that this is a low-level interface to iterating over the associative
3217 * array and is not compatible withth the
3218 * $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) type in Phobos.
3219 * For compatibility with `Tuple`, use
3220 * $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead.
3222 * Params:
3223 * aa = The associative array.
3224 * Returns:
3225 * A forward range referencing the pairs of the associative array.
3227 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3229 import core.internal.traits : substInout;
3231 static struct Result
3233 AARange r;
3235 pure nothrow @nogc:
3236 @property bool empty() @safe { return _aaRangeEmpty(r); }
3237 @property auto front()
3239 static struct Pair
3241 // We save the pointers here so that the Pair we return
3242 // won't mutate when Result.popFront is called afterwards.
3243 private void* keyp;
3244 private void* valp;
3246 @property ref key() inout @trusted
3248 return *cast(substInout!K*) keyp;
3250 @property ref value() inout @trusted
3252 return *cast(substInout!V*) valp;
3255 return Pair(_aaRangeFrontKey(r),
3256 _aaRangeFrontValue(r));
3258 void popFront() @safe { return _aaRangePopFront(r); }
3259 @property Result save() { return this; }
3262 return Result(_aaToRange(aa));
3265 /** ditto */
3266 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3268 return (*aa).byKeyValue();
3272 @safe unittest
3274 auto dict = ["k1": 1, "k2": 2];
3275 int sum;
3276 foreach (e; dict.byKeyValue)
3278 assert(e.key[1] == e.value + '0');
3279 sum += e.value;
3282 assert(sum == 3);
3285 /***********************************
3286 * Returns a newly allocated dynamic array containing a copy of the keys from
3287 * the associative array.
3288 * Params:
3289 * aa = The associative array.
3290 * Returns:
3291 * A dynamic array containing a copy of the keys.
3293 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
3295 // ensure we are dealing with a genuine AA.
3296 static if (is(const(Value[Key]) == const(T)))
3297 alias realAA = aa;
3298 else
3299 const(Value[Key]) realAA = aa;
3300 auto res = () @trusted {
3301 auto a = cast(void[])_aaKeys(*cast(inout(AA)*)&realAA, Key.sizeof, typeid(Key[]));
3302 return *cast(Key[]*)&a;
3303 }();
3304 static if (__traits(hasPostblit, Key))
3305 _doPostblit(res);
3306 return res;
3309 /** ditto */
3310 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
3312 return (*aa).keys;
3316 @safe unittest
3318 auto aa = [1: "v1", 2: "v2"];
3319 int sum;
3320 foreach (k; aa.keys)
3321 sum += k;
3323 assert(sum == 3);
3326 @safe unittest
3328 static struct S
3330 string str;
3331 void[][string] dict;
3332 alias dict this;
3335 auto s = S("a");
3336 assert(s.keys.length == 0);
3339 @safe unittest
3341 @safe static struct Key
3343 string str;
3344 this(this) @safe {}
3346 string[Key] aa;
3347 static assert(__traits(compiles, {
3348 void test() @safe {
3349 const _ = aa.keys;
3351 }));
3354 @safe unittest
3356 static struct Key
3358 string str;
3359 this(this) @system {}
3361 string[Key] aa;
3362 static assert(!__traits(compiles, {
3363 void test() @safe {
3364 const _ = aa.keys;
3366 }));
3369 /***********************************
3370 * Returns a newly allocated dynamic array containing a copy of the values from
3371 * the associative array.
3372 * Params:
3373 * aa = The associative array.
3374 * Returns:
3375 * A dynamic array containing a copy of the values.
3377 Value[] values(T : Value[Key], Value, Key)(T aa) @property
3379 // ensure we are dealing with a genuine AA.
3380 static if (is(const(Value[Key]) == const(T)))
3381 alias realAA = aa;
3382 else
3383 const(Value[Key]) realAA = aa;
3384 auto res = () @trusted {
3385 auto a = cast(void[])_aaValues(*cast(inout(AA)*)&realAA, Key.sizeof, Value.sizeof, typeid(Value[]));
3386 return *cast(Value[]*)&a;
3387 }();
3388 static if (__traits(hasPostblit, Value))
3389 _doPostblit(res);
3390 return res;
3393 /** ditto */
3394 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
3396 return (*aa).values;
3400 @safe unittest
3402 auto aa = ["k1": 1, "k2": 2];
3403 int sum;
3404 foreach (e; aa.values)
3405 sum += e;
3407 assert(sum == 3);
3410 @safe unittest
3412 static struct S
3414 string str;
3415 void[][string] dict;
3416 alias dict this;
3419 auto s = S("a");
3420 assert(s.values.length == 0);
3423 @safe unittest
3425 @safe static struct Value
3427 string str;
3428 this(this) @safe {}
3430 Value[string] aa;
3431 static assert(__traits(compiles, {
3432 void test() @safe {
3433 const _ = aa.values;
3435 }));
3438 @safe unittest
3440 static struct Value
3442 string str;
3443 this(this) @system {}
3445 Value[string] aa;
3446 static assert(!__traits(compiles, {
3447 void test() @safe {
3448 const _ = aa.values;
3450 }));
3453 /***********************************
3454 * Looks up key; if it exists returns corresponding value else evaluates and
3455 * returns defaultValue.
3456 * Params:
3457 * aa = The associative array.
3458 * key = The key.
3459 * defaultValue = The default value.
3460 * Returns:
3461 * The value.
3463 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)
3465 auto p = key in aa;
3466 return p ? *p : defaultValue;
3469 /** ditto */
3470 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
3472 return (*aa).get(key, defaultValue);
3476 @safe unittest
3478 auto aa = ["k1": 1];
3479 assert(aa.get("k1", 0) == 1);
3480 assert(aa.get("k2", 0) == 0);
3483 /***********************************
3484 * Looks up key; if it exists returns corresponding value else evaluates
3485 * value, adds it to the associative array and returns it.
3486 * Params:
3487 * aa = The associative array.
3488 * key = The key.
3489 * value = The required value.
3490 * Returns:
3491 * The value.
3493 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
3495 bool found;
3496 // if key is @safe-ly copyable, `require` can infer @safe
3497 static if (isSafeCopyable!K)
3499 auto p = () @trusted
3501 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3502 } ();
3504 else
3506 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3508 if (found)
3509 return *p;
3510 else
3512 *p = value; // Not `return (*p = value)` since if `=` is overloaded
3513 return *p; // this might not return a ref to the left-hand side.
3518 @safe unittest
3520 auto aa = ["k1": 1];
3521 assert(aa.require("k1", 0) == 1);
3522 assert(aa.require("k2", 0) == 0);
3523 assert(aa["k2"] == 0);
3526 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test.
3527 private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); }));
3529 /***********************************
3530 * Calls `create` if `key` doesn't exist in the associative array,
3531 * otherwise calls `update`.
3532 * `create` returns a corresponding value for `key`.
3533 * `update` accepts a key parameter. If it returns a value, the value is
3534 * set for `key`.
3535 * Params:
3536 * aa = The associative array.
3537 * key = The key.
3538 * create = The callable to create a value for `key`.
3539 * Must return V.
3540 * update = The callable to call if `key` exists.
3541 * Takes a K argument, returns a V or void.
3543 void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
3544 if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof(update(aa[K.init])) == void)))
3546 bool found;
3547 // if key is @safe-ly copyable, `update` may infer @safe
3548 static if (isSafeCopyable!K)
3550 auto p = () @trusted
3552 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3553 } ();
3555 else
3557 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3559 if (!found)
3560 *p = create();
3561 else
3563 static if (is(typeof(update(*p)) == void))
3564 update(*p);
3565 else
3566 *p = update(*p);
3571 @safe unittest
3573 int[string] aa;
3575 // create
3576 aa.update("key",
3577 () => 1,
3578 (int) {} // not executed
3580 assert(aa["key"] == 1);
3582 // update value by ref
3583 aa.update("key",
3584 () => 0, // not executed
3585 (ref int v) {
3586 v += 1;
3588 assert(aa["key"] == 2);
3590 // update from return value
3591 aa.update("key",
3592 () => 0, // not executed
3593 (int v) => v * 2
3595 assert(aa["key"] == 4);
3597 // 'update' without changing value
3598 aa.update("key",
3599 () => 0, // not executed
3600 (int) {
3601 // do something else
3603 assert(aa["key"] == 4);
3606 @safe unittest
3608 static struct S
3610 int x;
3611 @nogc nothrow pure:
3612 this(this) @system {}
3614 @safe const:
3615 // stubs
3616 bool opEquals(S rhs) { assert(0); }
3617 size_t toHash() { assert(0); }
3620 int[string] aai;
3621 static assert(is(typeof(() @safe { aai.require("a", 1234); })));
3622 static assert(is(typeof(() @safe { aai.update("a", { return 1234; }, (ref int x) { x++; return x; }); })));
3624 S[string] aas;
3625 static assert(is(typeof(() { aas.require("a", S(1234)); })));
3626 static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3627 static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3629 int[S] aais;
3630 static assert(is(typeof(() { aais.require(S(1234), 1234); })));
3631 static assert(is(typeof(() { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3632 static assert(!is(typeof(() @safe { aais.require(S(1234), 1234); })));
3633 static assert(!is(typeof(() @safe { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3636 @safe unittest
3638 struct S0
3640 int opCall(ref int v)
3642 return v + 1;
3646 struct S1
3648 int opCall()()
3650 return -2;
3653 T opCall(T)(ref T v)
3655 return v + 1;
3659 int[string] a = ["2" : 1];
3660 a.update("2", () => -1, S0.init);
3661 assert(a["2"] == 2);
3662 a.update("0", () => -1, S0.init);
3663 assert(a["0"] == -1);
3664 a.update("2", S1.init, S1.init);
3665 assert(a["2"] == 3);
3666 a.update("1", S1.init, S1.init);
3667 assert(a["1"] == -2);
3670 @system unittest
3672 int[string] aa;
3674 foreach (n; 0 .. 2)
3675 aa.update("k1", {
3676 return 7;
3677 }, (ref int v) {
3678 return v + 3;
3680 assert(aa["k1"] == 10);
3683 version (CoreDdoc)
3685 // This lets DDoc produce better documentation.
3688 Calculates the hash value of `arg` with an optional `seed` initial value.
3689 The result might not be equal to `typeid(T).getHash(&arg)`.
3691 Params:
3692 arg = argument to calculate the hash value of
3693 seed = optional `seed` value (may be used for hash chaining)
3695 Return: calculated hash value of `arg`
3697 size_t hashOf(T)(auto ref T arg, size_t seed)
3699 static import core.internal.hash;
3700 return core.internal.hash.hashOf(arg, seed);
3702 /// ditto
3703 size_t hashOf(T)(auto ref T arg)
3705 static import core.internal.hash;
3706 return core.internal.hash.hashOf(arg);
3709 @safe unittest
3711 auto h1 = "my.string".hashOf;
3712 assert(h1 == "my.string".hashOf);
3715 else
3717 public import core.internal.hash : hashOf;
3721 @system unittest
3723 class MyObject
3725 size_t myMegaHash() const @safe pure nothrow
3727 return 42;
3730 struct Test
3732 int a;
3733 string b;
3734 MyObject c;
3735 size_t toHash() const pure nothrow
3737 size_t hash = a.hashOf();
3738 hash = b.hashOf(hash);
3739 size_t h1 = c.myMegaHash();
3740 hash = h1.hashOf(hash); //Mix two hash values
3741 return hash;
3746 bool _xopEquals(in void*, in void*)
3748 throw new Error("TypeInfo.equals is not implemented");
3751 bool _xopCmp(in void*, in void*)
3753 throw new Error("TypeInfo.compare is not implemented");
3756 /******************************************
3757 * Create RTInfo for type T
3760 template RTInfoImpl(size_t[] pointerBitmap)
3762 immutable size_t[pointerBitmap.length] RTInfoImpl = pointerBitmap[];
3765 template NoPointersBitmapPayload(size_t N)
3767 enum size_t[N] NoPointersBitmapPayload = 0;
3770 template RTInfo(T)
3772 enum pointerBitmap = __traits(getPointerBitmap, T);
3773 static if (pointerBitmap[1 .. $] == NoPointersBitmapPayload!(pointerBitmap.length - 1))
3774 enum RTInfo = rtinfoNoPointers;
3775 else
3776 enum RTInfo = RTInfoImpl!(pointerBitmap).ptr;
3780 * shortcuts for the precise GC, also generated by the compiler
3781 * used instead of the actual pointer bitmap
3783 enum immutable(void)* rtinfoNoPointers = null;
3784 enum immutable(void)* rtinfoHasPointers = cast(void*)1;
3786 // Helper functions
3788 private inout(TypeInfo) getElement(return scope inout TypeInfo value) @trusted pure nothrow
3790 TypeInfo element = cast() value;
3791 for (;;)
3793 if (auto qualified = cast(TypeInfo_Const) element)
3794 element = qualified.base;
3795 else if (auto redefined = cast(TypeInfo_Enum) element)
3796 element = redefined.base;
3797 else if (auto staticArray = cast(TypeInfo_StaticArray) element)
3798 element = staticArray.value;
3799 else if (auto vector = cast(TypeInfo_Vector) element)
3800 element = vector.base;
3801 else
3802 break;
3804 return cast(inout) element;
3807 private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr, const size_t count) @trusted nothrow
3809 if (!count)
3810 return 0;
3812 const size_t elementSize = element.tsize;
3813 if (!elementSize)
3814 return 0;
3816 static bool hasCustomToHash(const scope TypeInfo value) @trusted pure nothrow
3818 const element = getElement(value);
3820 if (const struct_ = cast(const TypeInfo_Struct) element)
3821 return !!struct_.xtoHash;
3823 return cast(const TypeInfo_Array) element
3824 || cast(const TypeInfo_AssociativeArray) element
3825 || cast(const ClassInfo) element
3826 || cast(const TypeInfo_Interface) element;
3829 if (!hasCustomToHash(element))
3830 return hashOf(ptr[0 .. elementSize * count]);
3832 size_t hash = 0;
3833 foreach (size_t i; 0 .. count)
3834 hash = hashOf(element.getHash(ptr + i * elementSize), hash);
3835 return hash;
3838 /// Provide the .dup array property.
3839 @property auto dup(T)(T[] a)
3840 if (!is(const(T) : T))
3842 import core.internal.traits : Unconst;
3843 import core.internal.array.duplication : _dup;
3844 static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
3845 " to "~Unconst!T.stringof~" in dup.");
3847 return _dup!(T, Unconst!T)(a);
3851 @safe unittest
3853 auto arr = [1, 2];
3854 auto arr2 = arr.dup;
3855 arr[0] = 0;
3856 assert(arr == [0, 2]);
3857 assert(arr2 == [1, 2]);
3860 /// ditto
3861 // const overload to support implicit conversion to immutable (unique result, see DIP29)
3862 @property T[] dup(T)(const(T)[] a)
3863 if (is(const(T) : T))
3865 import core.internal.array.duplication : _dup;
3866 return _dup!(const(T), T)(a);
3870 /// Provide the .idup array property.
3871 @property immutable(T)[] idup(T)(T[] a)
3873 import core.internal.array.duplication : _dup;
3874 static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
3875 " to immutable in idup.");
3876 return _dup!(T, immutable(T))(a);
3879 /// ditto
3880 @property immutable(T)[] idup(T:void)(const(T)[] a)
3882 return a.dup;
3886 @safe unittest
3888 char[] arr = ['a', 'b', 'c'];
3889 string s = arr.idup;
3890 arr[0] = '.';
3891 assert(s == "abc");
3894 // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
3895 // necessary for now to prevent breaking code.
3896 private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
3899 (Property) Gets the current _capacity of a slice. The _capacity is the size
3900 that the slice can grow to before the underlying array must be
3901 reallocated or extended.
3903 If an append must reallocate a slice with no possibility of extension, then
3904 `0` is returned. This happens when the slice references a static array, or
3905 if another slice references elements past the end of the current slice.
3907 Note: The _capacity of a slice may be impacted by operations on other slices.
3909 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
3911 return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr);
3915 @safe unittest
3917 //Static array slice: no capacity
3918 int[4] sarray = [1, 2, 3, 4];
3919 int[] slice = sarray[];
3920 assert(sarray.capacity == 0);
3921 //Appending to slice will reallocate to a new array
3922 slice ~= 5;
3923 assert(slice.capacity >= 5);
3925 //Dynamic array slices
3926 int[] a = [1, 2, 3, 4];
3927 int[] b = a[1 .. $];
3928 int[] c = a[1 .. $ - 1];
3929 debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation
3931 assert(a.capacity != 0);
3932 assert(a.capacity == b.capacity + 1); //both a and b share the same tail
3934 assert(c.capacity == 0); //an append to c must relocate c.
3938 Reserves capacity for a slice. The capacity is the size
3939 that the slice can grow to before the underlying array must be
3940 reallocated or extended.
3942 Returns: The new capacity of the array (which may be larger than
3943 the requested capacity).
3945 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
3947 if (__ctfe)
3948 return newcapacity;
3949 else
3950 return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr);
3954 @safe unittest
3956 //Static array slice: no capacity. Reserve relocates.
3957 int[4] sarray = [1, 2, 3, 4];
3958 int[] slice = sarray[];
3959 auto u = slice.reserve(8);
3960 assert(u >= 8);
3961 assert(&sarray[0] !is &slice[0]);
3962 assert(slice.capacity == u);
3964 //Dynamic array slices
3965 int[] a = [1, 2, 3, 4];
3966 a.reserve(8); //prepare a for appending 4 more items
3967 auto p = &a[0];
3968 u = a.capacity;
3969 a ~= [5, 6, 7, 8];
3970 assert(p == &a[0]); //a should not have been reallocated
3971 assert(u == a.capacity); //a should not have been extended
3974 // https://issues.dlang.org/show_bug.cgi?id=12330, reserve() at CTFE time
3975 @safe unittest
3977 int[] foo() {
3978 int[] result;
3979 auto a = result.reserve = 5;
3980 assert(a == 5);
3981 return result;
3983 enum r = foo();
3986 // Issue 6646: should be possible to use array.reserve from SafeD.
3987 @safe unittest
3989 int[] a;
3990 a.reserve(10);
3993 // HACK: This is a lie. `_d_arrayshrinkfit` is not `nothrow`, but this lie is necessary
3994 // for now to prevent breaking code.
3995 private extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow;
3998 Assume that it is safe to append to this array. Appends made to this array
3999 after calling this function may append in place, even if the array was a
4000 slice of a larger array to begin with.
4002 Use this only when it is certain there are no elements in use beyond the
4003 array in the memory block. If there are, those elements will be
4004 overwritten by appending to this array.
4006 Warning: Calling this function, and then using references to data located after the
4007 given array results in undefined behavior.
4009 Returns:
4010 The input is returned.
4012 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
4014 _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
4015 return arr;
4019 @system unittest
4021 int[] a = [1, 2, 3, 4];
4023 // Without assumeSafeAppend. Appending relocates.
4024 int[] b = a [0 .. 3];
4025 b ~= 5;
4026 assert(a.ptr != b.ptr);
4028 debug(SENTINEL) {} else
4030 // With assumeSafeAppend. Appending overwrites.
4031 int[] c = a [0 .. 3];
4032 c.assumeSafeAppend() ~= 5;
4033 assert(a.ptr == c.ptr);
4037 @system unittest
4039 int[] arr;
4040 auto newcap = arr.reserve(2000);
4041 assert(newcap >= 2000);
4042 assert(newcap == arr.capacity);
4043 auto ptr = arr.ptr;
4044 foreach (i; 0..2000)
4045 arr ~= i;
4046 assert(ptr == arr.ptr);
4047 arr = arr[0..1];
4048 arr.assumeSafeAppend();
4049 arr ~= 5;
4050 assert(ptr == arr.ptr);
4053 @system unittest
4055 int[] arr = [1, 2, 3];
4056 void foo(ref int[] i)
4058 i ~= 5;
4060 arr = arr[0 .. 2];
4061 foo(assumeSafeAppend(arr)); //pass by ref
4062 assert(arr[]==[1, 2, 5]);
4063 arr = arr[0 .. 1].assumeSafeAppend(); //pass by value
4066 // https://issues.dlang.org/show_bug.cgi?id=10574
4067 @system unittest
4069 int[] a;
4070 immutable(int[]) b;
4071 auto a2 = &assumeSafeAppend(a);
4072 auto b2 = &assumeSafeAppend(b);
4073 auto a3 = assumeSafeAppend(a[]);
4074 auto b3 = assumeSafeAppend(b[]);
4075 assert(is(typeof(*a2) == int[]));
4076 assert(is(typeof(*b2) == immutable(int[])));
4077 assert(is(typeof(a3) == int[]));
4078 assert(is(typeof(b3) == immutable(int[])));
4081 private void _doPostblit(T)(T[] arr)
4083 // infer static postblit type, run postblit if any
4084 static if (__traits(hasPostblit, T))
4086 static if (__traits(isStaticArray, T) && is(T : E[], E))
4087 _doPostblit(cast(E[]) arr);
4088 else static if (!is(typeof(arr[0].__xpostblit())) && is(immutable T == immutable U, U))
4089 foreach (ref elem; (() @trusted => cast(U[]) arr)())
4090 elem.__xpostblit();
4091 else
4092 foreach (ref elem; arr)
4093 elem.__xpostblit();
4098 Destroys the given object and optionally resets to initial state. It's used to
4099 _destroy an object, calling its destructor or finalizer so it no longer
4100 references any other objects. It does $(I not) initiate a GC cycle or free
4101 any GC memory.
4102 If `initialize` is supplied `false`, the object is considered invalid after
4103 destruction, and should not be referenced.
4105 void destroy(bool initialize = true, T)(ref T obj) if (is(T == struct))
4107 import core.internal.destruction : destructRecurse;
4109 destructRecurse(obj);
4111 static if (initialize)
4113 import core.internal.lifetime : emplaceInitializer;
4114 emplaceInitializer(obj); // emplace T.init
4118 @safe unittest
4120 struct A { string s = "A"; }
4121 A a = {s: "B"};
4122 assert(a.s == "B");
4123 a.destroy;
4124 assert(a.s == "A");
4127 nothrow @safe @nogc unittest
4130 struct A { string s = "A"; }
4131 A a;
4132 a.s = "asd";
4133 destroy!false(a);
4134 assert(a.s == "asd");
4135 destroy(a);
4136 assert(a.s == "A");
4139 static int destroyed = 0;
4140 struct C
4142 string s = "C";
4143 ~this() nothrow @safe @nogc
4145 destroyed ++;
4149 struct B
4151 C c;
4152 string s = "B";
4153 ~this() nothrow @safe @nogc
4155 destroyed ++;
4158 B a;
4159 a.s = "asd";
4160 a.c.s = "jkl";
4161 destroy!false(a);
4162 assert(destroyed == 2);
4163 assert(a.s == "asd");
4164 assert(a.c.s == "jkl" );
4165 destroy(a);
4166 assert(destroyed == 4);
4167 assert(a.s == "B");
4168 assert(a.c.s == "C" );
4172 private extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true) nothrow;
4174 /// ditto
4175 void destroy(bool initialize = true, T)(T obj) if (is(T == class))
4177 static if (__traits(getLinkage, T) == "C++")
4179 static if (__traits(hasMember, T, "__xdtor"))
4180 obj.__xdtor();
4182 static if (initialize)
4184 const initializer = __traits(initSymbol, T);
4185 (cast(void*)obj)[0 .. initializer.length] = initializer[];
4188 else
4190 // Bypass overloaded opCast
4191 auto ptr = (() @trusted => *cast(void**) &obj)();
4192 rt_finalize2(ptr, true, initialize);
4196 /// ditto
4197 void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
4199 static assert(__traits(getLinkage, T) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage, T) ~ ") interface");
4201 destroy!initialize(cast(Object)obj);
4204 /// Reference type demonstration
4205 @system unittest
4207 class C
4209 struct Agg
4211 static int dtorCount;
4213 int x = 10;
4214 ~this() { dtorCount++; }
4217 static int dtorCount;
4219 string s = "S";
4220 Agg a;
4221 ~this() { dtorCount++; }
4224 C c = new C();
4225 assert(c.dtorCount == 0); // destructor not yet called
4226 assert(c.s == "S"); // initial state `c.s` is `"S"`
4227 assert(c.a.dtorCount == 0); // destructor not yet called
4228 assert(c.a.x == 10); // initial state `c.a.x` is `10`
4229 c.s = "T";
4230 c.a.x = 30;
4231 assert(c.s == "T"); // `c.s` is `"T"`
4232 destroy(c);
4233 assert(c.dtorCount == 1); // `c`'s destructor was called
4234 assert(c.s == "S"); // `c.s` is back to its inital state, `"S"`
4235 assert(c.a.dtorCount == 1); // `c.a`'s destructor was called
4236 assert(c.a.x == 10); // `c.a.x` is back to its inital state, `10`
4239 /// C++ classes work too
4240 @system unittest
4242 extern (C++) class CPP
4244 struct Agg
4246 __gshared int dtorCount;
4248 int x = 10;
4249 ~this() { dtorCount++; }
4252 __gshared int dtorCount;
4254 string s = "S";
4255 Agg a;
4256 ~this() { dtorCount++; }
4259 CPP cpp = new CPP();
4260 assert(cpp.dtorCount == 0); // destructor not yet called
4261 assert(cpp.s == "S"); // initial state `cpp.s` is `"S"`
4262 assert(cpp.a.dtorCount == 0); // destructor not yet called
4263 assert(cpp.a.x == 10); // initial state `cpp.a.x` is `10`
4264 cpp.s = "T";
4265 cpp.a.x = 30;
4266 assert(cpp.s == "T"); // `cpp.s` is `"T"`
4267 destroy!false(cpp); // destroy without initialization
4268 assert(cpp.dtorCount == 1); // `cpp`'s destructor was called
4269 assert(cpp.s == "T"); // `cpp.s` is not initialized
4270 assert(cpp.a.dtorCount == 1); // `cpp.a`'s destructor was called
4271 assert(cpp.a.x == 30); // `cpp.a.x` is not initialized
4272 destroy(cpp);
4273 assert(cpp.dtorCount == 2); // `cpp`'s destructor was called again
4274 assert(cpp.s == "S"); // `cpp.s` is back to its inital state, `"S"`
4275 assert(cpp.a.dtorCount == 2); // `cpp.a`'s destructor was called again
4276 assert(cpp.a.x == 10); // `cpp.a.x` is back to its inital state, `10`
4279 /// Value type demonstration
4280 @safe unittest
4282 int i;
4283 assert(i == 0); // `i`'s initial state is `0`
4284 i = 1;
4285 assert(i == 1); // `i` changed to `1`
4286 destroy!false(i);
4287 assert(i == 1); // `i` was not initialized
4288 destroy(i);
4289 assert(i == 0); // `i` is back to its initial state `0`
4292 /// Nested struct type
4293 @system unittest
4295 int dtorCount;
4296 struct A
4298 int i;
4299 ~this()
4301 dtorCount++; // capture local variable
4304 A a = A(5);
4305 destroy!false(a);
4306 assert(dtorCount == 1);
4307 assert(a.i == 5);
4309 destroy(a);
4310 assert(dtorCount == 2);
4311 assert(a.i == 0);
4313 // the context pointer is now null
4314 // restore it so the dtor can run
4315 import core.lifetime : emplace;
4316 emplace(&a, A(0));
4317 // dtor also called here
4320 @system unittest
4322 extern(C++)
4323 static class C
4325 void* ptr;
4326 this() {}
4329 destroy!false(new C());
4330 destroy!true(new C());
4333 @system unittest
4335 // class with an `alias this`
4336 class A
4338 static int dtorCount;
4339 ~this()
4341 dtorCount++;
4345 class B
4347 A a;
4348 alias a this;
4349 this()
4351 a = new A;
4353 static int dtorCount;
4354 ~this()
4356 dtorCount++;
4359 auto b = new B;
4360 assert(A.dtorCount == 0);
4361 assert(B.dtorCount == 0);
4362 destroy(b);
4363 assert(A.dtorCount == 0);
4364 assert(B.dtorCount == 1);
4366 auto a = new A;
4367 destroy(a);
4368 assert(A.dtorCount == 1);
4371 @system unittest
4373 interface I { }
4375 class A: I { string s = "A"; this() {} }
4376 auto a = new A, b = new A;
4377 a.s = b.s = "asd";
4378 destroy(a);
4379 assert(a.s == "A");
4381 I i = b;
4382 destroy(i);
4383 assert(b.s == "A");
4386 static bool destroyed = false;
4387 class B: I
4389 string s = "B";
4390 this() {}
4391 ~this()
4393 destroyed = true;
4396 auto a = new B, b = new B;
4397 a.s = b.s = "asd";
4398 destroy(a);
4399 assert(destroyed);
4400 assert(a.s == "B");
4402 destroyed = false;
4403 I i = b;
4404 destroy(i);
4405 assert(destroyed);
4406 assert(b.s == "B");
4408 // this test is invalid now that the default ctor is not run after clearing
4409 version (none)
4411 class C
4413 string s;
4414 this()
4416 s = "C";
4419 auto a = new C;
4420 a.s = "asd";
4421 destroy(a);
4422 assert(a.s == "C");
4426 nothrow @safe @nogc unittest
4429 struct A { string s = "A"; }
4430 A a;
4431 a.s = "asd";
4432 destroy!false(a);
4433 assert(a.s == "asd");
4434 destroy(a);
4435 assert(a.s == "A");
4438 static int destroyed = 0;
4439 struct C
4441 string s = "C";
4442 ~this() nothrow @safe @nogc
4444 destroyed ++;
4448 struct B
4450 C c;
4451 string s = "B";
4452 ~this() nothrow @safe @nogc
4454 destroyed ++;
4457 B a;
4458 a.s = "asd";
4459 a.c.s = "jkl";
4460 destroy!false(a);
4461 assert(destroyed == 2);
4462 assert(a.s == "asd");
4463 assert(a.c.s == "jkl" );
4464 destroy(a);
4465 assert(destroyed == 4);
4466 assert(a.s == "B");
4467 assert(a.c.s == "C" );
4471 nothrow unittest
4473 // Bugzilla 20049: Test to ensure proper behavior of `nothrow` destructors
4474 class C
4476 static int dtorCount = 0;
4477 this() nothrow {}
4478 ~this() nothrow { dtorCount++; }
4481 auto c = new C;
4482 destroy(c);
4483 assert(C.dtorCount == 1);
4486 // https://issues.dlang.org/show_bug.cgi?id=22832
4487 nothrow unittest
4489 static struct A {}
4490 static class B
4492 A opCast(T : A)() { return A(); }
4495 destroy(B.init);
4498 // make sure destroy!false skips re-initialization
4499 unittest
4501 static struct S { int x; }
4502 static class C { int x; }
4503 static extern(C++) class Cpp { int x; }
4505 static void test(T)(T inst)
4507 inst.x = 123;
4508 destroy!false(inst);
4509 assert(inst.x == 123, T.stringof);
4512 test(S());
4513 test(new C());
4514 test(new Cpp());
4517 /// ditto
4518 void destroy(bool initialize = true, T)(ref T obj)
4519 if (__traits(isStaticArray, T))
4521 foreach_reverse (ref e; obj[])
4522 destroy!initialize(e);
4525 @safe unittest
4527 int[2] a;
4528 a[0] = 1;
4529 a[1] = 2;
4530 destroy!false(a);
4531 assert(a == [ 1, 2 ]);
4532 destroy(a);
4533 assert(a == [ 0, 0 ]);
4536 @safe unittest
4538 static struct vec2f {
4539 float[2] values;
4540 alias values this;
4543 vec2f v;
4544 destroy!(true, vec2f)(v);
4547 @system unittest
4549 // Bugzilla 15009
4550 static string op;
4551 static struct S
4553 int x;
4554 this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; }
4555 this(this) { op ~= "P" ~ cast(char)('0'+x); }
4556 ~this() { op ~= "D" ~ cast(char)('0'+x); }
4560 S[2] a1 = [S(1), S(2)];
4561 op = "";
4563 assert(op == "D2D1"); // built-in scope destruction
4565 S[2] a1 = [S(1), S(2)];
4566 op = "";
4567 destroy(a1);
4568 assert(op == "D2D1"); // consistent with built-in behavior
4572 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
4573 op = "";
4575 assert(op == "D4D3D2D1");
4577 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
4578 op = "";
4579 destroy(a2);
4580 assert(op == "D4D3D2D1", op);
4584 // https://issues.dlang.org/show_bug.cgi?id=19218
4585 @system unittest
4587 static struct S
4589 static dtorCount = 0;
4590 ~this() { ++dtorCount; }
4593 static interface I
4595 ref S[3] getArray();
4596 alias getArray this;
4599 static class C : I
4601 static dtorCount = 0;
4602 ~this() { ++dtorCount; }
4604 S[3] a;
4605 alias a this;
4607 ref S[3] getArray() { return a; }
4610 C c = new C();
4611 destroy(c);
4612 assert(S.dtorCount == 3);
4613 assert(C.dtorCount == 1);
4615 I i = new C();
4616 destroy(i);
4617 assert(S.dtorCount == 6);
4618 assert(C.dtorCount == 2);
4621 /// ditto
4622 void destroy(bool initialize = true, T)(ref T obj)
4623 if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T))
4625 static if (initialize)
4626 obj = T.init;
4629 @safe unittest
4632 int a = 42;
4633 destroy!false(a);
4634 assert(a == 42);
4635 destroy(a);
4636 assert(a == 0);
4639 float a = 42;
4640 destroy!false(a);
4641 assert(a == 42);
4642 destroy(a);
4643 assert(a != a); // isnan
4647 @safe unittest
4649 // Bugzilla 14746
4650 static struct HasDtor
4652 ~this() { assert(0); }
4654 static struct Owner
4656 HasDtor* ptr;
4657 alias ptr this;
4660 Owner o;
4661 assert(o.ptr is null);
4662 destroy(o); // must not reach in HasDtor.__dtor()
4665 /* ************************************************************************
4666 COMPILER SUPPORT
4667 The compiler lowers certain expressions to instantiations of the following
4668 templates. They must be implicitly imported, which is why they are here
4669 in this file. They must also be `public` as they must be visible from the
4670 scope in which they are instantiated. They are explicitly undocumented as
4671 they are only intended to be instantiated by the compiler, not the user.
4672 **************************************************************************/
4674 public import core.internal.entrypoint : _d_cmain;
4676 public import core.internal.array.appending : _d_arrayappendT;
4677 version (D_ProfileGC)
4679 public import core.internal.array.appending : _d_arrayappendTTrace;
4680 public import core.internal.array.appending : _d_arrayappendcTXTrace;
4681 public import core.internal.array.concatenation : _d_arraycatnTXTrace;
4682 public import core.lifetime : _d_newitemTTrace;
4683 public import core.internal.array.construction : _d_newarrayTTrace;
4684 public import core.internal.array.construction : _d_newarraymTXTrace;
4686 public import core.internal.array.appending : _d_arrayappendcTX;
4687 public import core.internal.array.comparison : __cmp;
4688 public import core.internal.array.equality : __equals;
4689 public import core.internal.array.casting: __ArrayCast;
4690 public import core.internal.array.concatenation : _d_arraycatnTX;
4691 public import core.internal.array.construction : _d_arrayctor;
4692 public import core.internal.array.construction : _d_arraysetctor;
4693 public import core.internal.array.construction : _d_newarrayT;
4694 public import core.internal.array.construction : _d_newarraymTX;
4695 public import core.internal.array.arrayassign : _d_arrayassign_l;
4696 public import core.internal.array.arrayassign : _d_arrayassign_r;
4697 public import core.internal.array.arrayassign : _d_arraysetassign;
4698 public import core.internal.array.capacity: _d_arraysetlengthTImpl;
4700 public import core.internal.dassert: _d_assert_fail;
4702 public import core.internal.destruction: __ArrayDtor;
4704 public import core.internal.moving: __move_post_blt;
4706 public import core.internal.postblit: __ArrayPostblit;
4708 public import core.internal.switch_: __switch;
4709 public import core.internal.switch_: __switch_error;
4711 public import core.lifetime : _d_delstructImpl;
4712 public import core.lifetime : _d_newThrowable;
4713 public import core.lifetime : _d_newclassT;
4714 public import core.lifetime : _d_newclassTTrace;
4715 public import core.lifetime : _d_newitemT;
4717 public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
4719 // Compare class and interface objects for ordering.
4720 int __cmp(C1, C2)(C1 lhs, C2 rhs)
4721 if ((is(C1 : const(Object)) || (is(C1 == interface) && (__traits(getLinkage, C1) == "D"))) &&
4722 (is(C2 : const(Object)) || (is(C2 == interface) && (__traits(getLinkage, C2) == "D"))))
4724 static if (is(C1 == typeof(null)) && is(C2 == typeof(null)))
4726 return 0;
4728 else static if (is(C1 == typeof(null)))
4730 // Regard null references as always being "less than"
4731 return -1;
4733 else static if (is(C2 == typeof(null)))
4735 return 1;
4737 else
4739 if (lhs is rhs)
4740 return 0;
4741 if (lhs is null)
4742 return -1;
4743 if (rhs is null)
4744 return 1;
4745 return lhs.opCmp(rhs);
4749 // objects
4750 @safe unittest
4752 class C
4754 int i;
4755 this(int i) { this.i = i; }
4757 override int opCmp(Object c) const @safe
4759 return i - (cast(C)c).i;
4763 auto c1 = new C(1);
4764 auto c2 = new C(2);
4765 assert(__cmp(c1, null) > 0);
4766 assert(__cmp(null, c1) < 0);
4767 assert(__cmp(c1, c1) == 0);
4768 assert(__cmp(c1, c2) < 0);
4769 assert(__cmp(c2, c1) > 0);
4771 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
4772 assert(__cmp([c2, c2], [c1, c1]) > 0);
4775 // structs
4776 @safe unittest
4778 struct C
4780 ubyte i;
4781 this(ubyte i) { this.i = i; }
4784 auto c1 = C(1);
4785 auto c2 = C(2);
4787 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
4788 assert(__cmp([c2, c2], [c1, c1]) > 0);
4789 assert(__cmp([c2, c2], [c2, c1]) > 0);
4792 @safe unittest
4794 auto a = "hello"c;
4796 assert(a > "hel");
4797 assert(a >= "hel");
4798 assert(a < "helloo");
4799 assert(a <= "helloo");
4800 assert(a > "betty");
4801 assert(a >= "betty");
4802 assert(a == "hello");
4803 assert(a <= "hello");
4804 assert(a >= "hello");
4805 assert(a < "я");
4808 // Used in Exception Handling LSDA tables to 'wrap' C++ type info
4809 // so it can be distinguished from D TypeInfo
4810 class __cpp_type_info_ptr
4812 void* ptr; // opaque pointer to C++ RTTI type info
4815 // Compiler hook into the runtime implementation of array (vector) operations.
4816 template _arrayOp(Args...)
4818 import core.internal.array.operations;
4819 alias _arrayOp = arrayOp!Args;
4822 public import core.builtins : __ctfeWrite;
4826 Provides an "inline import", i.e. an `import` that is only available for a
4827 limited lookup. For example:
4830 void fun(imported!"std.stdio".File input)
4832 ... use File from std.stdio normally ...
4836 There is no need to import `std.stdio` at top level, so `fun` carries its own
4837 dependencies. The same approach can be used for template constraints:
4840 void fun(T)(imported!"std.stdio".File input, T value)
4841 if (imported!"std.traits".isIntegral!T)
4847 An inline import may be used in conjunction with the `with` statement as well.
4848 Inside the scope controlled by `with`, all symbols in the imported module are
4849 made available:
4852 void fun()
4854 with (imported!"std.datetime")
4855 with (imported!"std.stdio")
4857 Clock.currTime.writeln;
4862 The advantages of inline imports over top-level uses of the `import` declaration
4863 are the following:
4865 $(UL
4866 $(LI The `imported` template specifies dependencies at declaration level, not at
4867 module level. This allows reasoning about the dependency cost of declarations in
4868 separation instead of aggregated at module level.)
4869 $(LI Declarations using `imported` are easier to move around because they don't
4870 require top-level context, making for simpler and quicker refactorings.)
4871 $(LI Declarations using `imported` scale better with templates. This is because
4872 templates that are not instantiated do not have their parameters and constraints
4873 instantiated, so additional modules are not imported without necessity. This
4874 makes the cost of unused templates negligible. Dependencies are pulled on a need
4875 basis depending on the declarations used by client code.)
4878 The use of `imported` also has drawbacks:
4880 $(UL
4881 $(LI If most declarations in a module need the same imports, then factoring them
4882 at top level, outside the declarations, is simpler than repeating them.)
4883 $(LI Traditional dependency-tracking tools such as make and other build systems
4884 assume file-level dependencies and need special tooling (such as rdmd) in order
4885 to work efficiently.)
4886 $(LI Dependencies at the top of a module are easier to inspect quickly than
4887 dependencies spread throughout the module.)
4890 See_Also: The $(HTTP forum.dlang.org/post/tzqzmqhankrkbrfsrmbo@forum.dlang.org,
4891 forum discussion) that led to the creation of the `imported` facility. Credit is
4892 due to Daniel Nielsen and Dominikus Dittes Scherkl.
4895 template imported(string moduleName)
4897 mixin("import imported = " ~ moduleName ~ ";");