2 * $(SCRIPT inhibitQuickIndex = 1;)
5 * $(TR $(TH Category) $(TH Symbols))
6 * $(TR $(TD Arrays) $(TD
7 * $(MYREF assumeSafeAppend)
9 * $(A #.dup.2, $(TT dup))
13 * $(TR $(TD Associative arrays) $(TD
26 * $(TR $(TD General) $(TD
32 * $(TR $(TD Classes) $(TD
39 * $(TR $(TD Type info) $(TD
42 * $(MYREF OffsetTypeInfo)
44 * $(MYREF rtinfoNoPointers)
46 * $(MYREF TypeInfo_Class)
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
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)
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.
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().
89 // No TypeInfo-based core.vararg.va_arg().
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
101 else version (iOS
) {}
102 else version (TVOS
) {}
103 else version (WatchOS
) {}
104 else version = WithArgTypes
;
108 * All D class objects inherit from Object.
113 * Convert Object to a human readable string.
117 return typeid(this).name
;
122 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
123 enum fqn_unittest
= "object.Object." ~ unittest_sym_name
; // object.__unittest_LX_CY
127 Object obj
= new Object
;
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.
155 * $(TR $(TD this < obj) $(TD < 0))
156 * $(TR $(TD this == obj) $(TD 0))
157 * $(TR $(TD this > obj) $(TD > 0))
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
);
171 Object obj
= new Object
;
176 obj
.opCmp(new Object
);
181 assert(e
.msg
== "need opCmp for class object.Object");
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.
198 * // the typed overload first. It can use all the attribute you want
199 * bool opEquals(const Child c) const @safe pure nothrow @nogc
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);
214 bool opEquals(Object o
)
226 * Create instance of class specified by the fully qualified name
228 * The class must either have no constructors or have
229 * a default constructor.
244 * auto c = cast(C)Object.factory("foo.bar.C");
245 * assert(c !is null && c.x == 10);
249 static Object
factory(string classname
)
251 auto ci
= TypeInfo_Class
.find(classname
);
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. */
300 // General case => symmetric calls to method opEquals
301 return rhs
.opEquals(lhs
);
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
; } }
320 assert(f
== f
); // both null
322 assert(f
== f
); // both aliased to the same object
325 /// If either is null => non-equal
328 class F
{ int flag
; this(int flag
) { this.flag
= flag
; } }
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`
347 bool opEquals(const F o
) const @safe nothrow pure
349 return flag
== o
.flag
;
354 assert(new F(0) == new F(0));
355 assert(!(new F(0) == new F(1)));
358 /// General case => symmetric calls to method opEquals
361 int fEquals
, gEquals
;
374 this(int flag
) { super(flag
); }
376 bool opEquals(const Base o
) @safe
379 return flag
== o
.flag
;
385 this(int flag
) { super(flag
); }
387 bool opEquals(const Base o
) @safe
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.
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
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);
432 Base b3
= new Base(1);
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);
445 Object o3
= new Base(1);
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
458 this(int member
, int member2
) pure @safe nothrow @nogc
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
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);
504 static assert(testThroughChild());
507 // To cover const Object opEquals
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
520 static shared class C
{ bool opEquals(const(shared(C
)) rhs
) const shared { return true;}}
521 const(C
) c
= new 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.
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
));
543 shared Object obj1
= new Object
;
548 shared C obj2
= new shared(C
);
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.
566 /// Class info returned by `typeid` for this interface (not for containing class)
567 TypeInfo_Class classinfo
;
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).
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
)
603 auto ti
= cast(TypeInfo
) rhs
;
606 return __cmp(this.toString(), ti
.toString());
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
629 return ti
&& this.toString() == ti
.toString();
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.
643 * p = pointer to start of instance of the type
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
655 /// Compares two instances for equality.
656 bool equals(in void* p1
, in void* p2
) const { return p1
== p2
; }
658 /// Compares two instances for <, ==, or >.
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
;
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
; }
699 auto dummy
= new _TypeInfo_Dummy();
700 cast(void)dummy
.initializer(); // For coverage completeness
704 // does nothing because tsize is 0
708 dummy
.tsize_val
= int.sizeof
;
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,
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
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
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);
778 dummy
.compare(null, null);
782 assert(e
.msg
== "TypeInfo.compare is not implemented");
786 assert(dummy
.equals(null, null));
787 assert(!dummy
.equals(cast(void*)1, null));
792 assert(typeid(void).next() is null);
793 assert(typeid(void).offTi() is null);
794 assert(typeid(void).tsize() == 1);
796 version (WithArgTypes
)
800 assert(typeid(void).argTypes(ti1
, ti2
) == 0);
801 assert(typeid(void) is ti1
);
803 assert(ti1
!is null);
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));
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
)
847 auto c
= cast(const TypeInfo_Enum
)o
;
848 return c
&& this.name
== c
.name
&&
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
); }
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" }
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
); }
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
); }
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
; }
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
); }
928 typeid(E
).swap(&e1
, &e2
);
933 override @property inout(TypeInfo
) next() nothrow pure inout { return base
.next
; }
939 assert(typeid(E
).next
is null);
942 override @property uint flags() nothrow pure const { return base
.flags
; }
948 assert(typeid(E
).flags
== 0);
951 override const(OffsetTypeInfo
)[] offTi() const { return base
.offTi
; }
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
; }
984 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
985 enum fqn_unittest
= "object." ~ unittest_sym_name
; // object.__unittest_LX_CY
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
)
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; }
1054 class TypeInfo_Array
: TypeInfo
1056 override string
toString() const { return value
.toString() ~ "[]"; }
1058 override bool opEquals(Object o
)
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
)
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
))
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
)
1096 for (size_t u
= 0; u
< len
; u
++)
1098 immutable int result
= value
.compare(a1
.ptr
+ u
* sz
, a2
.ptr
+ u
* sz
);
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
;
1124 override @property inout(TypeInfo
) next() nothrow pure inout
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*);
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
)
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
))
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
);
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
;
1234 foreach (i
; 0 .. len
)
1241 override void postblit(void* p
) const
1243 immutable sz
= value
.tsize
;
1244 foreach (i
; 0 .. 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*);
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
1273 foreach (int i
; 0 .. 16)
1278 typeid(int[16]).swap(&a
, &b
);
1279 foreach (int i
; 0 .. 16)
1286 class TypeInfo_AssociativeArray
: TypeInfo
1288 override string
toString() const
1290 return value
.toString() ~ "[" ~ key
.toString() ~ "]";
1293 override bool opEquals(Object o
)
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; }
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*);
1342 class TypeInfo_Vector
: TypeInfo
1344 override string
toString() const { return "__vector(" ~ base
.toString() ~ ")"; }
1346 override bool opEquals(Object o
)
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
);
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
)
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
1410 override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers
; }
1415 * Mangled function type string
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)");
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
);
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());
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
)
1492 auto c
= cast(const TypeInfo_Delegate
)o
;
1493 return c
&& this.deco
== c
.deco
;
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
;
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
;
1534 override @property size_t
tsize() nothrow pure const
1536 alias dg
= int delegate();
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; }
1550 override @property size_t
talign() nothrow pure const
1552 alias dg
= int delegate();
1556 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1558 arg1
= typeid(void*);
1559 arg2
= typeid(void*);
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
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
;
1607 // Regard null references as always being "less than"
1623 override @property size_t
tsize() nothrow pure const
1625 return Object
.sizeof
;
1628 override const(void)[] initializer() nothrow pure const @safe
1633 override @property uint flags() nothrow pure const { return 1; }
1635 override @property const(OffsetTypeInfo
)[] offTi() nothrow pure const
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
1651 void function(Object
) classInvariant
;
1652 enum ClassFlags
: ushort
1658 hasGetMembers
= 0x10,
1666 ushort depth
; /// inheritance distance from Object
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
)
1686 //writefln("module %s, %d", m.name, m.localClasses.length);
1687 foreach (c
; m
.localClasses
)
1691 //writefln("\tclass %s", c.name);
1692 if (c
.name
== classname
)
1701 * Create instance of Object represented by 'this'.
1703 Object
create() const
1705 if (m_flags
& 8 && !defaultConstructor
)
1707 if (m_flags
& 64) // abstract
1709 Object o
= _d_newclass(this);
1710 if (m_flags
& 8 && defaultConstructor
)
1712 defaultConstructor(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.
1723 * child = TypeInfo for some class
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
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
)
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
;
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
)
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
)
1782 Interface
* pi
= **cast(Interface
***)*cast(void**)p
;
1783 Object o
= cast(Object
)(*cast(void**)p
- pi
.offset
);
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
);
1806 // Regard null references as always being "less than"
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.
1842 * child = TypeInfo for some class
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.
1858 * child = TypeInfo for some interface
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
);
1871 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
1872 enum fqn_unittest
= "object." ~ unittest_sym_name
; // object.__unittest_LX_CY
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
)
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
1903 return (*xtoHash
)(p
);
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
;
1919 const dg
= _memberFunc(p1
, xopEquals
);
1920 return dg
.xopEquals(p2
);
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"
1942 const dg
= _memberFunc(p1
, xopCmp
);
1943 return dg
.xopCmp(p2
);
1946 // BUG: relies on the GC not moving objects
1947 return memcmp(p1
, p2
, initializer().length
);
1955 override @property size_t
tsize() nothrow pure const
1957 return initializer().length
;
1960 override const(void)[] initializer() nothrow pure const @safe
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
1973 if (m_flags
& StructFlags
.isDynamicType
)
1974 (*xdtorti
)(p
, this);
1980 override void postblit(void* p
) const
1988 final @property string
name() nothrow const @trusted
1990 import core
.demangle
: demangleType
;
1992 if (mangledName
is null) // e.g., opaque structs
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
1999 //return demangledNamesCache.require(key, cast(string) demangleType(mangledName));
2001 if (auto pDemangled
= key
in demangledNamesCache
)
2004 const demangled
= cast(string
) demangleType(mangledName
);
2005 demangledNamesCache
[key
] = demangled
;
2009 void[] m_init
; // initializer; m_init.ptr == null if 0 initialize
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
2021 isDynamicType
= 0x2, // built at runtime, needs type info in xdtor
2023 StructFlags m_flags
;
2027 void function(void*) xdtor
;
2028 void function(void*, const TypeInfo_Struct ti
) xdtorti
;
2030 void function(void*) xpostblit
;
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
)
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
2061 const void* funcptr
;
2065 bool delegate(in void*) xopEquals
;
2066 int delegate(in void*) xopCmp
;
2076 bool opEquals(ref const S rhs
) const
2082 assert(!typeid(S
).equals(&s
, &s
));
2085 class TypeInfo_Tuple
: TypeInfo
2087 TypeInfo
[] elements
;
2089 override string
toString() const
2092 foreach (i
, element
; elements
)
2096 s
~= element
.toString();
2102 override bool opEquals(Object o
)
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
])
2120 override size_t
getHash(scope const void* p
) const
2125 override bool equals(in void* p1
, in void* p2
) const
2130 override int compare(in void* p1
, in void* p2
) const
2135 override @property size_t
tsize() nothrow pure const
2140 override const(void)[] initializer() const @trusted
2145 override void swap(void* p1
, void* p2
) const
2150 override void destroy(void* p
) const
2155 override void postblit(void* p
) const
2160 override @property size_t
talign() nothrow pure const
2165 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
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
)
2184 if (typeid(this) != typeid(o
))
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
);
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
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
2250 MIxgetMembers
= 0x80,
2253 MIimportedModules
= 0x400,
2254 MIlocalClasses
= 0x800,
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.
2266 uint _flags
; // MIxxxx
2267 uint _index
; // index into _moduleinfo_array[]
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
; }
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
;
2304 if (flag
== MIctor
) return p
;
2305 p
+= typeof(ctor
).sizeof
;
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
);
2345 @property uint index() nothrow pure @nogc { return _index
; }
2347 @property uint flags() nothrow pure @nogc { return _flags
; }
2349 /************************
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 /************************
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 /*****************************
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 /************************
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 /************************
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 /************************
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;
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;
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
];
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
];
2440 /********************
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
));
2466 foreach (m
; ModuleInfo
)
2472 ///////////////////////////////////////////////////////////////////////////////
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
2488 class Throwable
: Object
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.
2507 * The _line number of the D source code corresponding with
2508 * where the error was thrown from.
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).
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
2531 private Throwable nextInChain
;
2533 private uint _refcount
; // 0 : allocated by GC
2534 // 1 : allocated by _d_newThrowable()
2535 // 2.. : reference count + 1
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
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
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
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
)
2580 for (Throwable t
= this; t
; t
= t
.nextInChain
)
2590 * Append `e2` to chain of exceptions that starts with `e1`.
2592 * e1 = start of chain (can be null)
2593 * e2 = second part of chain (can be null)
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
)
2606 for (auto e
= e1
; 1; e
= e
.nextInChain
)
2617 @nogc @safe pure nothrow this(string msg
, Throwable nextInChain
= null)
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
);
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
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()
2655 toString((in buf
) { s
~= buf
; });
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(")");
2677 sink(": "); sink(msg
);
2683 sink("\n----------------");
2686 sink("\n"); sink(t
);
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.
2707 * A message representing the cause of the `Throwable`
2709 @__future const(char)[] message() const @safe nothrow
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
);
2750 throw new Exception("msg");
2755 assert(e
.msg
== "msg");
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
;
2833 throw new Error("msg");
2838 assert(e
.msg
== "msg");
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);
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
;
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.
2930 * aa = The associative array.
2932 void clear(Value
, Key
)(Value
[Key
] aa
) @trusted
2934 _aaClear(*cast(AA
*) &aa
);
2938 void clear(Value
, Key
)(Value
[Key
]* aa
) @trusted
2940 _aaClear(*cast(AA
*) aa
);
2946 auto aa
= ["k1": 2];
2948 assert("k1" !in aa
);
2961 v
["Hello World"] = 42;
2963 assert("Hello World" !in v
);
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
2974 * aa = The associative array.
2976 * The rehashed associative array.
2978 T
rehash(T
: Value
[Key
], Value
, Key
)(T aa
)
2980 _aaRehash(cast(AA
*)&aa
, typeid(Value
[Key
]));
2985 T
rehash(T
: Value
[Key
], Value
, Key
)(T
* aa
)
2987 _aaRehash(cast(AA
*)aa
, typeid(Value
[Key
]));
2992 T
rehash(T
: shared Value
[Key
], Value
, Key
)(T aa
)
2994 _aaRehash(cast(AA
*)&aa
, typeid(Value
[Key
]));
2999 T
rehash(T
: shared Value
[Key
], Value
, Key
)(T
* aa
)
3001 _aaRehash(cast(AA
*)aa
, typeid(Value
[Key
]));
3005 /***********************************
3006 * Creates a new associative array of the same size and copies the contents of
3007 * the associative array into it.
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");
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
);
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();
3042 duplicateElem(k
, v
).__xpostblit();
3049 V
[K
] dup(T
: V
[K
], K
, V
)(T
* aa
)
3057 auto aa
= ["k1": 2];
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
)))
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:
3084 * import std.stdio : writeln;
3086 * auto dict = ["k1": 1, "k2": 2];
3087 * auto keyRange = dict.byKey;
3089 * writeln(keyRange.front); // Segmentation fault
3093 * aa = The associative array.
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
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
));
3119 auto byKey(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3121 return (*aa
).byKey();
3127 auto dict
= [1: "v1", 2: "v2"];
3129 foreach (v
; dict
.byKey
)
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:
3145 * import std.stdio : writeln;
3147 * auto dict = ["k1": 1, "k2": 2];
3148 * auto valueRange = dict.byValue;
3150 * writeln(valueRange.front); // Segmentation fault
3154 * aa = The associative array.
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
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
));
3180 auto byValue(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3182 return (*aa
).byValue();
3188 auto dict
= ["k1": 1, "k2": 2];
3190 foreach (v
; dict
.byValue
)
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,
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:
3208 * import std.stdio : writeln;
3210 * auto dict = ["k1": 1, "k2": 2];
3211 * auto kvRange = dict.byKeyValue;
3213 * writeln(kvRange.front.key, ": ", kvRange.front.value); // Segmentation fault
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.
3223 * aa = The associative array.
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
3236 @property bool empty() @safe { return _aaRangeEmpty(r
); }
3237 @property auto front()
3241 // We save the pointers here so that the Pair we return
3242 // won't mutate when Result.popFront is called afterwards.
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
));
3266 auto byKeyValue(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3268 return (*aa
).byKeyValue();
3274 auto dict
= ["k1": 1, "k2": 2];
3276 foreach (e
; dict
.byKeyValue
)
3278 assert(e
.key
[1] == e
.value
+ '0');
3285 /***********************************
3286 * Returns a newly allocated dynamic array containing a copy of the keys from
3287 * the associative array.
3289 * aa = The associative array.
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
)))
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
;
3304 static if (__traits(hasPostblit
, Key
))
3310 Key
[] keys(T
: Value
[Key
], Value
, Key
)(T
*aa
) @property
3318 auto aa
= [1: "v1", 2: "v2"];
3320 foreach (k
; aa
.keys
)
3331 void[][string
] dict
;
3336 assert(s
.keys
.length
== 0);
3341 @safe static struct Key
3347 static assert(__traits(compiles
, {
3359 this(this) @system {}
3362 static assert(!__traits(compiles
, {
3369 /***********************************
3370 * Returns a newly allocated dynamic array containing a copy of the values from
3371 * the associative array.
3373 * aa = The associative array.
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
)))
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
;
3388 static if (__traits(hasPostblit
, Value
))
3394 Value
[] values(T
: Value
[Key
], Value
, Key
)(T
*aa
) @property
3396 return (*aa
).values
;
3402 auto aa
= ["k1": 1, "k2": 2];
3404 foreach (e
; aa
.values
)
3415 void[][string
] dict
;
3420 assert(s
.values
.length
== 0);
3425 @safe static struct Value
3431 static assert(__traits(compiles
, {
3433 const _
= aa
.values
;
3443 this(this) @system {}
3446 static assert(!__traits(compiles
, {
3448 const _
= aa
.values
;
3453 /***********************************
3454 * Looks up key; if it exists returns corresponding value else evaluates and
3455 * returns defaultValue.
3457 * aa = The associative array.
3459 * defaultValue = The default value.
3463 inout(V
) get(K
, V
)(inout(V
[K
]) aa
, K key
, lazy inout(V
) defaultValue
)
3466 return p ?
*p
: defaultValue
;
3470 inout(V
) get(K
, V
)(inout(V
[K
])* aa
, K key
, lazy inout(V
) defaultValue
)
3472 return (*aa
).get(key
, defaultValue
);
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.
3487 * aa = The associative array.
3489 * value = The required value.
3493 ref V
require(K
, V
)(ref V
[K
] aa
, K key
, lazy V value
= V
.init
)
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
);
3506 auto p
= cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
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.
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
3536 * aa = The associative array.
3538 * create = The callable to create a value for `key`.
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)))
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
);
3557 auto p
= cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
3563 static if (is(typeof(update(*p
)) == void))
3578 (int) {} // not executed
3580 assert(aa
["key"] == 1);
3582 // update value by ref
3584 () => 0, // not executed
3588 assert(aa
["key"] == 2);
3590 // update from return value
3592 () => 0, // not executed
3595 assert(aa
["key"] == 4);
3597 // 'update' without changing value
3599 () => 0, // not executed
3601 // do something else
3603 assert(aa
["key"] == 4);
3612 this(this) @system {}
3616 bool opEquals(S rhs
) { assert(0); }
3617 size_t
toHash() { assert(0); }
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
; }); })));
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
; }); })));
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
; }); })));
3640 int opCall(ref int v
)
3653 T
opCall(T
)(ref T v
)
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);
3680 assert(aa
["k1"] == 10);
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)`.
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
);
3703 size_t
hashOf(T
)(auto ref T arg
)
3705 static import core
.internal
.hash
;
3706 return core
.internal
.hash
.hashOf(arg
);
3711 auto h1
= "my.string".hashOf
;
3712 assert(h1
== "my.string".hashOf
);
3717 public import core
.internal
.hash
: hashOf
;
3725 size_t
myMegaHash() const @safe pure nothrow
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
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;
3772 enum pointerBitmap
= __traits(getPointerBitmap
, T
);
3773 static if (pointerBitmap
[1 .. $] == NoPointersBitmapPayload
!(pointerBitmap
.length
- 1))
3774 enum RTInfo
= rtinfoNoPointers
;
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;
3788 private inout(TypeInfo
) getElement(return scope inout TypeInfo value
) @trusted pure nothrow
3790 TypeInfo element
= cast() value
;
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
;
3804 return cast(inout) element
;
3807 private size_t
getArrayHash(const scope TypeInfo element
, const scope void* ptr
, const size_t count
) @trusted nothrow
3812 const size_t elementSize
= element
.tsize
;
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
]);
3833 foreach (size_t i
; 0 .. count
)
3834 hash
= hashOf(element
.getHash(ptr
+ i
* elementSize
), 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
);
3854 auto arr2
= arr
.dup
;
3856 assert(arr
== [0, 2]);
3857 assert(arr2
== [1, 2]);
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
);
3880 @property immutable(T
)[] idup(T
:void)(const(T
)[] a
)
3888 char[] arr
= ['a', 'b', 'c'];
3889 string s
= arr
.idup
;
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
);
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
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
3950 return _d_arraysetcapacity(typeid(T
[]), newcapacity
, cast(void[]*)&arr
);
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);
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
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
3979 auto a
= result
.reserve
= 5;
3986 // Issue 6646: should be possible to use array.reserve from SafeD.
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.
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
));
4021 int[] a
= [1, 2, 3, 4];
4023 // Without assumeSafeAppend. Appending relocates.
4024 int[] b
= a
[0 .. 3];
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
);
4040 auto newcap
= arr
.reserve(2000);
4041 assert(newcap
>= 2000);
4042 assert(newcap
== arr
.capacity
);
4044 foreach (i
; 0..2000)
4046 assert(ptr
== arr
.ptr
);
4048 arr
.assumeSafeAppend();
4050 assert(ptr
== arr
.ptr
);
4055 int[] arr
= [1, 2, 3];
4056 void foo(ref int[] i
)
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
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
)())
4092 foreach (ref elem
; arr
)
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
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
4120 struct A
{ string s
= "A"; }
4127 nothrow @safe @nogc unittest
4130 struct A
{ string s
= "A"; }
4134 assert(a
.s
== "asd");
4139 static int destroyed
= 0;
4143 ~this() nothrow @safe @nogc
4153 ~this() nothrow @safe @nogc
4162 assert(destroyed
== 2);
4163 assert(a
.s
== "asd");
4164 assert(a
.c
.s
== "jkl" );
4166 assert(destroyed
== 4);
4168 assert(a
.c
.s
== "C" );
4172 private extern (C
) void rt_finalize2(void* p
, bool det
= true, bool resetMemory
= true) nothrow;
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"))
4182 static if (initialize
)
4184 const initializer
= __traits(initSymbol
, T
);
4185 (cast(void*)obj
)[0 .. initializer
.length
] = initializer
[];
4190 // Bypass overloaded opCast
4191 auto ptr
= (() @trusted => *cast(void**) &obj
)();
4192 rt_finalize2(ptr
, true, initialize
);
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
4211 static int dtorCount
;
4214 ~this() { dtorCount
++; }
4217 static int dtorCount
;
4221 ~this() { dtorCount
++; }
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`
4231 assert(c
.s
== "T"); // `c.s` is `"T"`
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
4242 extern (C
++) class CPP
4246 __gshared
int dtorCount
;
4249 ~this() { dtorCount
++; }
4252 __gshared
int dtorCount
;
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`
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
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
4283 assert(i
== 0); // `i`'s initial state is `0`
4285 assert(i
== 1); // `i` changed to `1`
4287 assert(i
== 1); // `i` was not initialized
4289 assert(i
== 0); // `i` is back to its initial state `0`
4292 /// Nested struct type
4301 dtorCount
++; // capture local variable
4306 assert(dtorCount
== 1);
4310 assert(dtorCount
== 2);
4313 // the context pointer is now null
4314 // restore it so the dtor can run
4315 import core
.lifetime
: emplace
;
4317 // dtor also called here
4329 destroy
!false(new C());
4330 destroy
!true(new C());
4335 // class with an `alias this`
4338 static int dtorCount
;
4353 static int dtorCount
;
4360 assert(A
.dtorCount
== 0);
4361 assert(B
.dtorCount
== 0);
4363 assert(A
.dtorCount
== 0);
4364 assert(B
.dtorCount
== 1);
4368 assert(A
.dtorCount
== 1);
4375 class A
: I
{ string s
= "A"; this() {} }
4376 auto a
= new A
, b
= new A
;
4386 static bool destroyed
= false;
4396 auto a
= new B
, b
= new B
;
4408 // this test is invalid now that the default ctor is not run after clearing
4426 nothrow @safe @nogc unittest
4429 struct A
{ string s
= "A"; }
4433 assert(a
.s
== "asd");
4438 static int destroyed
= 0;
4442 ~this() nothrow @safe @nogc
4452 ~this() nothrow @safe @nogc
4461 assert(destroyed
== 2);
4462 assert(a
.s
== "asd");
4463 assert(a
.c
.s
== "jkl" );
4465 assert(destroyed
== 4);
4467 assert(a
.c
.s
== "C" );
4473 // Bugzilla 20049: Test to ensure proper behavior of `nothrow` destructors
4476 static int dtorCount
= 0;
4478 ~this() nothrow { dtorCount
++; }
4483 assert(C
.dtorCount
== 1);
4486 // https://issues.dlang.org/show_bug.cgi?id=22832
4492 A
opCast(T
: A
)() { return A(); }
4498 // make sure destroy!false skips re-initialization
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
)
4508 destroy
!false(inst
);
4509 assert(inst
.x
== 123, T
.stringof
);
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
);
4531 assert(a
== [ 1, 2 ]);
4533 assert(a
== [ 0, 0 ]);
4538 static struct vec2f
{
4544 destroy
!(true, vec2f
)(v
);
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)];
4563 assert(op
== "D2D1"); // built-in scope destruction
4565 S
[2] a1
= [S(1), S(2)];
4568 assert(op
== "D2D1"); // consistent with built-in behavior
4572 S
[2][2] a2
= [[S(1), S(2)], [S(3), S(4)]];
4575 assert(op
== "D4D3D2D1");
4577 S
[2][2] a2
= [[S(1), S(2)], [S(3), S(4)]];
4580 assert(op
== "D4D3D2D1", op
);
4584 // https://issues.dlang.org/show_bug.cgi?id=19218
4589 static dtorCount
= 0;
4590 ~this() { ++dtorCount
; }
4595 ref S
[3] getArray();
4596 alias getArray
this;
4601 static dtorCount
= 0;
4602 ~this() { ++dtorCount
; }
4607 ref S
[3] getArray() { return a
; }
4612 assert(S
.dtorCount
== 3);
4613 assert(C
.dtorCount
== 1);
4617 assert(S
.dtorCount
== 6);
4618 assert(C
.dtorCount
== 2);
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
)
4643 assert(a
!= a
); // isnan
4650 static struct HasDtor
4652 ~this() { assert(0); }
4661 assert(o
.ptr
is null);
4662 destroy(o
); // must not reach in HasDtor.__dtor()
4665 /* ************************************************************************
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)))
4728 else static if (is(C1
== typeof(null)))
4730 // Regard null references as always being "less than"
4733 else static if (is(C2
== typeof(null)))
4745 return lhs
.opCmp(rhs
);
4755 this(int i
) { this.i
= i
; }
4757 override int opCmp(Object c
) const @safe
4759 return i
- (cast(C
)c
).i
;
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);
4781 this(ubyte i
) { this.i
= i
; }
4787 assert(__cmp([c1
, c1
][], [c2
, c2
][]) < 0);
4788 assert(__cmp([c2
, c2
], [c1
, c1
]) > 0);
4789 assert(__cmp([c2
, c2
], [c2
, c1
]) > 0);
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");
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
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
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:
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
~ ";");