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).
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 void setSameMutex(shared Object ownee
, shared Object owner
)
531 import core
.atomic
: atomicLoad
;
532 _d_setSameMutex(atomicLoad(ownee
), atomicLoad(owner
));
537 shared Object obj1
= new Object
;
542 shared C obj2
= new shared(C
);
545 assert(obj1
.__monitor
!= obj2
.__monitor
);
546 assert(obj1
.__monitor
is null);
548 setSameMutex(obj1
, obj2
);
549 assert(obj1
.__monitor
== obj2
.__monitor
);
550 assert(obj1
.__monitor
!is null);
554 * Information about an interface.
555 * When an object is accessed via an interface, an Interface* appears as the
556 * first entry in its vtbl.
560 /// Class info returned by `typeid` for this interface (not for containing class)
561 TypeInfo_Class classinfo
;
563 size_t offset
; /// offset to Interface 'this' from Object 'this'
567 * Array of pairs giving the offset and type information for each
568 * member in an aggregate.
570 struct OffsetTypeInfo
572 size_t offset
; /// Offset of member from start of object
573 TypeInfo ti
; /// TypeInfo for this member
577 * Runtime type information about a type.
578 * Can be retrieved for any type using a
579 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
583 override string
toString() const @safe nothrow
585 return typeid(this).name
;
588 override size_t
toHash() @trusted const nothrow
590 return hashOf(this.toString());
593 override int opCmp(Object rhs
)
597 auto ti
= cast(TypeInfo
) rhs
;
600 return __cmp(this.toString(), ti
.toString());
605 assert(typeid(void) <= typeid(void));
606 assert(typeid(void).opCmp(null));
607 assert(!typeid(void).opCmp(typeid(void)));
610 override bool opEquals(Object o
)
612 return opEquals(cast(TypeInfo
) o
);
615 bool opEquals(const TypeInfo ti
) @safe nothrow const
617 /* TypeInfo instances are singletons, but duplicates can exist
618 * across DLL's. Therefore, comparing for a name match is
623 return ti
&& this.toString() == ti
.toString();
628 auto anotherObj
= new Object();
630 assert(typeid(void).opEquals(typeid(void)));
631 assert(typeid(void) != anotherObj
); // calling .opEquals here directly is a type mismatch
635 * Computes a hash of the instance of a type.
637 * p = pointer to start of instance of the type
641 * fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
643 size_t
getHash(scope const void* p
) @trusted nothrow const
645 // by default, do not assume anything about the type
649 /// Compares two instances for equality.
650 bool equals(in void* p1
, in void* p2
) const { return p1
== p2
; }
652 /// Compares two instances for <, ==, or >.
653 int compare(in void* p1
, in void* p2
) const { return _xopCmp(p1
, p2
); }
655 /// Returns size of the type.
656 @property size_t
tsize() nothrow pure const @safe @nogc { return 0; }
658 /// Swaps two instances of the type.
659 void swap(void* p1
, void* p2
) const
661 size_t remaining
= tsize
;
662 // If the type might contain pointers perform the swap in pointer-sized
663 // chunks in case a garbage collection pass interrupts this function.
664 if ((cast(size_t
) p1 |
cast(size_t
) p2
) % (void*).alignof
== 0)
666 while (remaining
>= (void*).sizeof
)
668 void* tmp
= *cast(void**) p1
;
669 *cast(void**) p1
= *cast(void**) p2
;
670 *cast(void**) p2
= tmp
;
671 p1
+= (void*).sizeof
;
672 p2
+= (void*).sizeof
;
673 remaining
-= (void*).sizeof
;
676 for (size_t i
= 0; i
< remaining
; i
++)
678 byte t
= (cast(byte *)p1
)[i
];
679 (cast(byte*)p1
)[i
] = (cast(byte*)p2
)[i
];
680 (cast(byte*)p2
)[i
] = t
;
686 class _TypeInfo_Dummy
: TypeInfo
688 override const(void)[] initializer() const { return []; }
689 @property override size_t
tsize() nothrow pure const @safe @nogc { return tsize_val
; }
693 auto dummy
= new _TypeInfo_Dummy();
694 cast(void)dummy
.initializer(); // For coverage completeness
698 // does nothing because tsize is 0
702 dummy
.tsize_val
= int.sizeof
;
707 void* ptr_a
= null, ptr_b
= cast(void*)1;
708 dummy
.tsize_val
= (void*).sizeof
;
709 dummy
.swap(&ptr_a
, &ptr_b
);
710 assert(ptr_a
is cast(void*)1);
711 assert(ptr_b
is null);
714 /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
716 @property inout(TypeInfo
) next() nothrow pure inout @nogc { return null; }
719 * Return default initializer. If the type should be initialized to all
720 * zeros, an array with a null ptr and a length equal to the type size will
721 * be returned. For static arrays, this returns the default initializer for
722 * a single element of the array, use `tsize` to get the correct size.
724 abstract const(void)[] initializer() nothrow pure const @safe @nogc;
726 /** Get flags for type: 1 means GC should scan for pointers,
727 2 means arg of this type is passed in SIMD register(s) if available */
728 @property uint flags() nothrow pure const @safe @nogc { return 0; }
730 /// Get type information on the contents of the type; null if not available
731 const(OffsetTypeInfo
)[] offTi() const { return null; }
732 /// Run the destructor on the object and all its sub-objects
733 void destroy(void* p
) const {}
734 /// Run the postblit on the object and all its sub-objects
735 void postblit(void* p
) const {}
738 /// Return alignment of type
739 @property size_t
talign() nothrow pure const @safe @nogc { return tsize
; }
741 /** Return internal info on arguments fitting into 8byte.
742 * See X86-64 ABI 3.2.3
744 version (WithArgTypes
) int argTypes(out TypeInfo arg1
, out TypeInfo arg2
) @safe nothrow
750 /** Return info used by the garbage collector to do precise collection.
752 @property immutable(void)* rtInfo() nothrow pure const @trusted @nogc { return rtinfoHasPointers
; } // better safe than sorry
757 class _TypeInfo_Dummy
: TypeInfo
759 override const(void)[] initializer() const { return []; }
761 auto dummy
= new _TypeInfo_Dummy();
762 cast(void)dummy
.initializer(); // For coverage completeness
764 assert(dummy
.rtInfo() is rtinfoHasPointers
);
765 assert(typeid(void).rtInfo() is rtinfoNoPointers
);
767 assert(dummy
.tsize() == 0);
772 dummy
.compare(null, null);
776 assert(e
.msg
== "TypeInfo.compare is not implemented");
780 assert(dummy
.equals(null, null));
781 assert(!dummy
.equals(cast(void*)1, null));
786 assert(typeid(void).next() is null);
787 assert(typeid(void).offTi() is null);
788 assert(typeid(void).tsize() == 1);
790 version (WithArgTypes
)
794 assert(typeid(void).argTypes(ti1
, ti2
) == 0);
795 assert(typeid(void) is ti1
);
797 assert(ti1
!is null);
804 class _ZypeInfo_Dummy
: TypeInfo
806 override const(void)[] initializer() const { return []; }
808 auto dummy2
= new _ZypeInfo_Dummy();
809 cast(void)dummy2
.initializer(); // For coverage completeness
811 assert(typeid(void) > dummy2
);
812 assert(dummy2
< typeid(void));
817 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
818 enum fqn_unittest
= "object." ~ unittest_sym_name
; // object.__unittest_LX_CY
820 class _TypeInfo_Dummy
: TypeInfo
822 override const(void)[] initializer() const { return []; }
825 auto dummy
= new _TypeInfo_Dummy();
826 cast(void)dummy
.initializer(); // For coverage completeness
828 assert(dummy
.toString() == fqn_unittest
~ "._TypeInfo_Dummy");
829 assert(dummy
.toHash() == hashOf(dummy
.toString()));
830 assert(dummy
.getHash(null) == 0);
833 class TypeInfo_Enum
: TypeInfo
835 override string
toString() const pure { return name
; }
837 override bool opEquals(Object o
)
841 auto c
= cast(const TypeInfo_Enum
)o
;
842 return c
&& this.name
== c
.name
&&
851 assert(typeid(E
).opEquals(typeid(E
)));
852 assert(!typeid(E
).opEquals(typeid(EE
)));
855 override size_t
getHash(scope const void* p
) const { return base
.getHash(p
); }
863 assert(typeid(E
).getHash(&e1
) == hashOf(E
.A
));
864 assert(typeid(E
).getHash(&e2
) == hashOf(E
.B
));
866 enum ES
: string
{ A
= "foo", B
= "bar" }
870 assert(typeid(ES
).getHash(&es1
) == hashOf("foo"));
871 assert(typeid(ES
).getHash(&es2
) == hashOf("bar"));
874 override bool equals(in void* p1
, in void* p2
) const { return base
.equals(p1
, p2
); }
883 assert(typeid(E
).equals(&e1
, &e1
));
884 assert(!typeid(E
).equals(&e1
, &e2
));
887 override int compare(in void* p1
, in void* p2
) const { return base
.compare(p1
, p2
); }
896 assert(typeid(E
).compare(&e1
, &e1
) == 0);
897 assert(typeid(E
).compare(&e1
, &e2
) < 0);
898 assert(typeid(E
).compare(&e2
, &e1
) > 0);
901 override @property size_t
tsize() nothrow pure const { return base
.tsize
; }
906 enum ES
: string
{ A
= "a", B
= "b", C
= "c"}
908 assert(typeid(E
).tsize
== E
.sizeof
);
909 assert(typeid(ES
).tsize
== ES
.sizeof
);
910 assert(typeid(E
).tsize
!= ES
.sizeof
);
913 override void swap(void* p1
, void* p2
) const { return base
.swap(p1
, p2
); }
922 typeid(E
).swap(&e1
, &e2
);
927 override @property inout(TypeInfo
) next() nothrow pure inout { return base
.next
; }
933 assert(typeid(E
).next
is null);
936 override @property uint flags() nothrow pure const { return base
.flags
; }
942 assert(typeid(E
).flags
== 0);
945 override const(OffsetTypeInfo
)[] offTi() const { return base
.offTi
; }
951 assert(typeid(E
).offTi
is null);
954 override void destroy(void* p
) const { return base
.destroy(p
); }
955 override void postblit(void* p
) const { return base
.postblit(p
); }
957 override const(void)[] initializer() const
959 return m_init
.length ? m_init
: base
.initializer();
962 override @property size_t
talign() nothrow pure const { return base
.talign
; }
964 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
966 return base
.argTypes(arg1
, arg2
);
969 override @property immutable(void)* rtInfo() const { return base
.rtInfo
; }
978 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
979 enum fqn_unittest
= "object." ~ unittest_sym_name
; // object.__unittest_LX_CY
984 assert(typeid(E
).toString() == fqn_unittest
~ ".E");
988 @safe unittest // https://issues.dlang.org/show_bug.cgi?id=12233
990 static assert(is(typeof(TypeInfo
.init
) == TypeInfo
));
991 assert(TypeInfo
.init
is null);
995 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
996 class TypeInfo_Pointer
: TypeInfo
998 override string
toString() const { return m_next
.toString() ~ "*"; }
1000 override bool opEquals(Object o
)
1004 auto c
= cast(const TypeInfo_Pointer
)o
;
1005 return c
&& this.m_next
== c
.m_next
;
1008 override size_t
getHash(scope const void* p
) @trusted const
1010 size_t addr
= cast(size_t
) *cast(const void**)p
;
1011 return addr ^
(addr
>> 4);
1014 override bool equals(in void* p1
, in void* p2
) const
1016 return *cast(void**)p1
== *cast(void**)p2
;
1019 override int compare(in void* p1
, in void* p2
) const
1021 const v1
= *cast(void**) p1
, v2
= *cast(void**) p2
;
1022 return (v1
> v2
) - (v1
< v2
);
1025 override @property size_t
tsize() nothrow pure const
1027 return (void*).sizeof
;
1030 override const(void)[] initializer() const @trusted
1032 return (cast(void *)null)[0 .. (void*).sizeof
];
1035 override void swap(void* p1
, void* p2
) const
1037 void* tmp
= *cast(void**)p1
;
1038 *cast(void**)p1
= *cast(void**)p2
;
1039 *cast(void**)p2
= tmp
;
1042 override @property inout(TypeInfo
) next() nothrow pure inout { return m_next
; }
1043 override @property uint flags() nothrow pure const { return 1; }
1048 class TypeInfo_Array
: TypeInfo
1050 override string
toString() const { return value
.toString() ~ "[]"; }
1052 override bool opEquals(Object o
)
1056 auto c
= cast(const TypeInfo_Array
)o
;
1057 return c
&& this.value
== c
.value
;
1060 override size_t
getHash(scope const void* p
) @trusted const
1062 void[] a
= *cast(void[]*)p
;
1063 return getArrayHash(value
, a
.ptr
, a
.length
);
1066 override bool equals(in void* p1
, in void* p2
) const
1068 void[] a1
= *cast(void[]*)p1
;
1069 void[] a2
= *cast(void[]*)p2
;
1070 if (a1
.length
!= a2
.length
)
1072 size_t sz
= value
.tsize
;
1073 for (size_t i
= 0; i
< a1
.length
; i
++)
1075 if (!value
.equals(a1
.ptr
+ i
* sz
, a2
.ptr
+ i
* sz
))
1081 override int compare(in void* p1
, in void* p2
) const
1083 void[] a1
= *cast(void[]*)p1
;
1084 void[] a2
= *cast(void[]*)p2
;
1085 size_t sz
= value
.tsize
;
1086 size_t len
= a1
.length
;
1088 if (a2
.length
< len
)
1090 for (size_t u
= 0; u
< len
; u
++)
1092 immutable int result
= value
.compare(a1
.ptr
+ u
* sz
, a2
.ptr
+ u
* sz
);
1096 return (a1
.length
> a2
.length
) - (a1
.length
< a2
.length
);
1099 override @property size_t
tsize() nothrow pure const
1101 return (void[]).sizeof
;
1104 override const(void)[] initializer() const @trusted
1106 return (cast(void *)null)[0 .. (void[]).sizeof
];
1109 override void swap(void* p1
, void* p2
) const
1111 void[] tmp
= *cast(void[]*)p1
;
1112 *cast(void[]*)p1
= *cast(void[]*)p2
;
1113 *cast(void[]*)p2
= tmp
;
1118 override @property inout(TypeInfo
) next() nothrow pure inout
1123 override @property uint flags() nothrow pure const { return 1; }
1125 override @property size_t
talign() nothrow pure const
1127 return (void[]).alignof
;
1130 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1132 arg1
= typeid(size_t
);
1133 arg2
= typeid(void*);
1137 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo
!(void[]); }
1140 class TypeInfo_StaticArray
: TypeInfo
1142 override string
toString() const
1144 import core
.internal
.string
: unsignedToTempString
;
1146 char[20] tmpBuff
= void;
1147 const lenString
= unsignedToTempString(len
, tmpBuff
);
1149 return (() @trusted => cast(string
) (value
.toString() ~ "[" ~ lenString
~ "]"))();
1152 override bool opEquals(Object o
)
1156 auto c
= cast(const TypeInfo_StaticArray
)o
;
1157 return c
&& this.len
== c
.len
&&
1158 this.value
== c
.value
;
1161 override size_t
getHash(scope const void* p
) @trusted const
1163 return getArrayHash(value
, p
, len
);
1166 override bool equals(in void* p1
, in void* p2
) const
1168 size_t sz
= value
.tsize
;
1170 for (size_t u
= 0; u
< len
; u
++)
1172 if (!value
.equals(p1
+ u
* sz
, p2
+ u
* sz
))
1178 override int compare(in void* p1
, in void* p2
) const
1180 size_t sz
= value
.tsize
;
1182 for (size_t u
= 0; u
< len
; u
++)
1184 immutable int result
= value
.compare(p1
+ u
* sz
, p2
+ u
* sz
);
1191 override @property size_t
tsize() nothrow pure const
1193 return len
* value
.tsize
;
1196 override void swap(void* p1
, void* p2
) const
1198 import core
.stdc
.string
: memcpy
;
1200 size_t remaining
= value
.tsize
* len
;
1201 void[size_t
.sizeof
* 4] buffer
= void;
1202 while (remaining
> buffer
.length
)
1204 memcpy(buffer
.ptr
, p1
, buffer
.length
);
1205 memcpy(p1
, p2
, buffer
.length
);
1206 memcpy(p2
, buffer
.ptr
, buffer
.length
);
1207 p1
+= buffer
.length
;
1208 p2
+= buffer
.length
;
1209 remaining
-= buffer
.length
;
1211 memcpy(buffer
.ptr
, p1
, remaining
);
1212 memcpy(p1
, p2
, remaining
);
1213 memcpy(p2
, buffer
.ptr
, remaining
);
1216 override const(void)[] initializer() nothrow pure const
1218 return value
.initializer();
1221 override @property inout(TypeInfo
) next() nothrow pure inout { return value
; }
1222 override @property uint flags() nothrow pure const { return value
.flags
; }
1224 override void destroy(void* p
) const
1226 immutable sz
= value
.tsize
;
1228 foreach (i
; 0 .. len
)
1235 override void postblit(void* p
) const
1237 immutable sz
= value
.tsize
;
1238 foreach (i
; 0 .. len
)
1248 override @property size_t
talign() nothrow pure const
1250 return value
.talign
;
1253 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1255 arg1
= typeid(void*);
1259 // just return the rtInfo of the element, we have no generic type T to run RTInfo!T on
1260 override @property immutable(void)* rtInfo() nothrow pure const @safe { return value
.rtInfo(); }
1263 // https://issues.dlang.org/show_bug.cgi?id=21315
1267 foreach (int i
; 0 .. 16)
1272 typeid(int[16]).swap(&a
, &b
);
1273 foreach (int i
; 0 .. 16)
1280 class TypeInfo_AssociativeArray
: TypeInfo
1282 override string
toString() const
1284 return value
.toString() ~ "[" ~ key
.toString() ~ "]";
1287 override bool opEquals(Object o
)
1291 auto c
= cast(const TypeInfo_AssociativeArray
)o
;
1292 return c
&& this.key
== c
.key
&&
1293 this.value
== c
.value
;
1296 override bool equals(in void* p1
, in void* p2
) @trusted const
1298 return !!_aaEqual(this, *cast(const AA
*) p1
, *cast(const AA
*) p2
);
1301 override hash_t
getHash(scope const void* p
) nothrow @trusted const
1303 return _aaGetHash(cast(AA
*)p
, this);
1306 // BUG: need to add the rest of the functions
1308 override @property size_t
tsize() nothrow pure const
1310 return (char[int]).sizeof
;
1313 override const(void)[] initializer() const @trusted
1315 return (cast(void *)null)[0 .. (char[int]).sizeof
];
1318 override @property inout(TypeInfo
) next() nothrow pure inout { return value
; }
1319 override @property uint flags() nothrow pure const { return 1; }
1324 override @property size_t
talign() nothrow pure const
1326 return (char[int]).alignof
;
1329 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1331 arg1
= typeid(void*);
1336 class TypeInfo_Vector
: TypeInfo
1338 override string
toString() const { return "__vector(" ~ base
.toString() ~ ")"; }
1340 override bool opEquals(Object o
)
1344 auto c
= cast(const TypeInfo_Vector
)o
;
1345 return c
&& this.base
== c
.base
;
1348 override size_t
getHash(scope const void* p
) const { return base
.getHash(p
); }
1349 override bool equals(in void* p1
, in void* p2
) const { return base
.equals(p1
, p2
); }
1350 override int compare(in void* p1
, in void* p2
) const { return base
.compare(p1
, p2
); }
1351 override @property size_t
tsize() nothrow pure const { return base
.tsize
; }
1352 override void swap(void* p1
, void* p2
) const { return base
.swap(p1
, p2
); }
1354 override @property inout(TypeInfo
) next() nothrow pure inout { return base
.next
; }
1355 override @property uint flags() nothrow pure const { return 2; /* passed in SIMD register */ }
1357 override const(void)[] initializer() nothrow pure const
1359 return base
.initializer();
1362 override @property size_t
talign() nothrow pure const { return 16; }
1364 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1366 return base
.argTypes(arg1
, arg2
);
1372 class TypeInfo_Function
: TypeInfo
1374 override string
toString() const pure @trusted
1376 import core
.demangle
: demangleType
;
1378 alias SafeDemangleFunctionType
= char[] function (const(char)[] buf
, char[] dst
= null) @safe nothrow pure;
1379 SafeDemangleFunctionType demangle
= cast(SafeDemangleFunctionType
) &demangleType
;
1381 return cast(string
) demangle(deco
);
1384 override bool opEquals(Object o
)
1388 auto c
= cast(const TypeInfo_Function
)o
;
1389 return c
&& this.deco
== c
.deco
;
1392 // BUG: need to add the rest of the functions
1394 override @property size_t
tsize() nothrow pure const
1396 return 0; // no size for functions
1399 override const(void)[] initializer() const @safe
1404 override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers
; }
1409 * Mangled function type string
1420 int func(int a
, int b
);
1423 alias functionTypes
= typeof(__traits(getVirtualMethods
, C
, "func"));
1424 assert(typeid(functionTypes
[0]).toString() == "void function()");
1425 assert(typeid(functionTypes
[1]).toString() == "void function(int)");
1426 assert(typeid(functionTypes
[2]).toString() == "int function(int, int)");
1437 alias functionTypes
= typeof(__traits(getVirtualMethods
, C
, "func"));
1439 Object obj
= typeid(functionTypes
[0]);
1440 assert(obj
.opEquals(typeid(functionTypes
[0])));
1441 assert(typeid(functionTypes
[0]) == typeid(functionTypes
[0]));
1442 assert(typeid(functionTypes
[0]) != typeid(functionTypes
[1]));
1444 assert(typeid(functionTypes
[0]).tsize() == 0);
1445 assert(typeid(functionTypes
[0]).initializer() is null);
1446 assert(typeid(functionTypes
[0]).rtInfo() is null);
1449 class TypeInfo_Delegate
: TypeInfo
1451 override string
toString() const pure @trusted
1453 import core
.demangle
: demangleType
;
1455 alias SafeDemangleFunctionType
= char[] function (const(char)[] buf
, char[] dst
= null) @safe nothrow pure;
1456 SafeDemangleFunctionType demangle
= cast(SafeDemangleFunctionType
) &demangleType
;
1458 return cast(string
) demangle(deco
);
1463 double sqr(double x
) { return x
* x
; }
1464 sqr(double.init
); // for coverage completeness
1466 auto delegate_str
= "double delegate(double) pure nothrow @nogc @safe";
1468 assert(typeid(typeof(&sqr
)).toString() == delegate_str
);
1469 assert(delegate_str
.hashOf() == typeid(typeof(&sqr
)).hashOf());
1470 assert(typeid(typeof(&sqr
)).toHash() == typeid(typeof(&sqr
)).hashOf());
1474 alias delegate_type
= typeof((int a
, int b
) => a
+ b
+ g
);
1475 delegate_str
= "int delegate(int, int) pure nothrow @nogc @safe";
1477 assert(typeid(delegate_type
).toString() == delegate_str
);
1478 assert(delegate_str
.hashOf() == typeid(delegate_type
).hashOf());
1479 assert(typeid(delegate_type
).toHash() == typeid(delegate_type
).hashOf());
1482 override bool opEquals(Object o
)
1486 auto c
= cast(const TypeInfo_Delegate
)o
;
1487 return c
&& this.deco
== c
.deco
;
1492 double sqr(double x
) { return x
* x
; }
1493 int dbl(int x
) { return x
+ x
; }
1494 sqr(double.init
); // for coverage completeness
1495 dbl(int.init
); // for coverage completeness
1497 Object obj
= typeid(typeof(&sqr
));
1498 assert(obj
.opEquals(typeid(typeof(&sqr
))));
1499 assert(typeid(typeof(&sqr
)) == typeid(typeof(&sqr
)));
1500 assert(typeid(typeof(&dbl
)) != typeid(typeof(&sqr
)));
1503 override size_t
getHash(scope const void* p
) @trusted const
1505 return hashOf(*cast(const void delegate() *)p
);
1508 override bool equals(in void* p1
, in void* p2
) const
1510 auto dg1
= *cast(void delegate()*)p1
;
1511 auto dg2
= *cast(void delegate()*)p2
;
1515 override int compare(in void* p1
, in void* p2
) const
1517 auto dg1
= *cast(void delegate()*)p1
;
1518 auto dg2
= *cast(void delegate()*)p2
;
1528 override @property size_t
tsize() nothrow pure const
1530 alias dg
= int delegate();
1534 override const(void)[] initializer() const @trusted
1536 return (cast(void *)null)[0 .. (int delegate()).sizeof
];
1539 override @property uint flags() nothrow pure const { return 1; }
1544 override @property size_t
talign() nothrow pure const
1546 alias dg
= int delegate();
1550 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
1552 arg1
= typeid(void*);
1553 arg2
= typeid(void*);
1557 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo
!(int delegate()); }
1560 private extern (C
) Object
_d_newclass(const TypeInfo_Class ci
);
1561 private extern (C
) int _d_isbaseof(scope TypeInfo_Class child
,
1562 scope const TypeInfo_Class parent
) @nogc nothrow pure @safe; // rt.cast_
1565 * Runtime type information about a class.
1566 * Can be retrieved from an object instance by using the
1567 * $(DDSUBLINK spec/expression,typeid_expressions,typeid expression).
1569 class TypeInfo_Class
: TypeInfo
1571 override string
toString() const pure { return name
; }
1573 override bool opEquals(const TypeInfo o
) const
1577 auto c
= cast(const TypeInfo_Class
)o
;
1578 return c
&& this.name
== c
.name
;
1581 override size_t
getHash(scope const void* p
) @trusted const
1583 auto o
= *cast(Object
*)p
;
1584 return o ? o
.toHash() : 0;
1587 override bool equals(in void* p1
, in void* p2
) const
1589 Object o1
= *cast(Object
*)p1
;
1590 Object o2
= *cast(Object
*)p2
;
1592 return (o1
is o2
) ||
(o1
&& o1
.opEquals(o2
));
1595 override int compare(in void* p1
, in void* p2
) const
1597 Object o1
= *cast(Object
*)p1
;
1598 Object o2
= *cast(Object
*)p2
;
1601 // Regard null references as always being "less than"
1617 override @property size_t
tsize() nothrow pure const
1619 return Object
.sizeof
;
1622 override const(void)[] initializer() nothrow pure const @safe
1627 override @property uint flags() nothrow pure const { return 1; }
1629 override @property const(OffsetTypeInfo
)[] offTi() nothrow pure const
1634 final @property auto info() @safe @nogc nothrow pure const return { return this; }
1635 final @property auto typeinfo() @safe @nogc nothrow pure const return { return this; }
1637 byte[] m_init
; /** class static initializer
1638 * (init.length gives size in bytes of class)
1640 string name
; /// class name
1641 void*[] vtbl
; /// virtual function pointer table
1642 Interface
[] interfaces
; /// interfaces this class implements
1643 TypeInfo_Class base
; /// base class
1645 void function(Object
) classInvariant
;
1646 enum ClassFlags
: uint
1652 hasGetMembers
= 0x10,
1660 OffsetTypeInfo
[] m_offTi
;
1661 void function(Object
) defaultConstructor
; // default Constructor
1663 immutable(void)* m_RTInfo
; // data for precise GC
1664 override @property immutable(void)* rtInfo() const { return m_RTInfo
; }
1667 * Search all modules for TypeInfo_Class corresponding to classname.
1668 * Returns: null if not found
1670 static const(TypeInfo_Class
) find(const scope char[] classname
)
1672 foreach (m
; ModuleInfo
)
1676 //writefln("module %s, %d", m.name, m.localClasses.length);
1677 foreach (c
; m
.localClasses
)
1681 //writefln("\tclass %s", c.name);
1682 if (c
.name
== classname
)
1691 * Create instance of Object represented by 'this'.
1693 Object
create() const
1695 if (m_flags
& 8 && !defaultConstructor
)
1697 if (m_flags
& 64) // abstract
1699 Object o
= _d_newclass(this);
1700 if (m_flags
& 8 && defaultConstructor
)
1702 defaultConstructor(o
);
1708 * Returns true if the class described by `child` derives from or is
1709 * the class described by this `TypeInfo_Class`. Always returns false
1710 * if the argument is null.
1713 * child = TypeInfo for some class
1715 * true if the class described by `child` derives from or is the
1716 * class described by this `TypeInfo_Class`.
1718 final bool isBaseOf(scope const TypeInfo_Class child
) const @nogc nothrow pure @trusted
1722 // If this TypeInfo_Class represents an actual class we only need
1723 // to check the child and its direct ancestors.
1724 for (auto ti
= cast() child
; ti
!is null; ti
= ti
.base
)
1731 // If this TypeInfo_Class is the .info field of a TypeInfo_Interface
1732 // we also need to recursively check the child's interfaces.
1733 return child
!is null && _d_isbaseof(cast() child
, this);
1738 alias ClassInfo
= TypeInfo_Class
;
1748 assert(typeid(X
).initializer
is typeid(X
).m_init
);
1749 assert(typeid(X
).initializer
.length
== typeid(const(X
)).initializer
.length
);
1750 assert(typeid(X
).initializer
.length
== typeid(shared(X
)).initializer
.length
);
1751 assert(typeid(X
).initializer
.length
== typeid(immutable(X
)).initializer
.length
);
1754 class TypeInfo_Interface
: TypeInfo
1756 override string
toString() const pure { return info
.name
; }
1758 override bool opEquals(Object o
)
1762 auto c
= cast(const TypeInfo_Interface
)o
;
1763 return c
&& this.info
.name
== typeid(c
).name
;
1766 override size_t
getHash(scope const void* p
) @trusted const
1768 if (!*cast(void**)p
)
1772 Interface
* pi
= **cast(Interface
***)*cast(void**)p
;
1773 Object o
= cast(Object
)(*cast(void**)p
- pi
.offset
);
1778 override bool equals(in void* p1
, in void* p2
) const
1780 Interface
* pi
= **cast(Interface
***)*cast(void**)p1
;
1781 Object o1
= cast(Object
)(*cast(void**)p1
- pi
.offset
);
1782 pi
= **cast(Interface
***)*cast(void**)p2
;
1783 Object o2
= cast(Object
)(*cast(void**)p2
- pi
.offset
);
1785 return o1
== o2 ||
(o1
&& o1
.opCmp(o2
) == 0);
1788 override int compare(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
);
1796 // Regard null references as always being "less than"
1812 override @property size_t
tsize() nothrow pure const
1814 return Object
.sizeof
;
1817 override const(void)[] initializer() const @trusted
1819 return (cast(void *)null)[0 .. Object
.sizeof
];
1822 override @property uint flags() nothrow pure const { return 1; }
1824 TypeInfo_Class info
;
1827 * Returns true if the class described by `child` derives from the
1828 * interface described by this `TypeInfo_Interface`. Always returns
1829 * false if the argument is null.
1832 * child = TypeInfo for some class
1834 * true if the class described by `child` derives from the
1835 * interface described by this `TypeInfo_Interface`.
1837 final bool isBaseOf(scope const TypeInfo_Class child
) const @nogc nothrow pure @trusted
1839 return child
!is null && _d_isbaseof(cast() child
, this.info
);
1843 * Returns true if the interface described by `child` derives from
1844 * or is the interface described by this `TypeInfo_Interface`.
1845 * Always returns false if the argument is null.
1848 * child = TypeInfo for some interface
1850 * true if the interface described by `child` derives from or is
1851 * the interface described by this `TypeInfo_Interface`.
1853 final bool isBaseOf(scope const TypeInfo_Interface child
) const @nogc nothrow pure @trusted
1855 return child
!is null && _d_isbaseof(cast() child
.info
, this.info
);
1861 enum unittest_sym_name
= __traits(identifier
, __traits(parent
, (){}));
1862 enum fqn_unittest
= "object." ~ unittest_sym_name
; // object.__unittest_LX_CY
1866 assert(fqn_unittest
~ ".I" == typeid(I
).info
.name
);
1867 assert((fqn_unittest
~ ".I").hashOf() == typeid(I
).hashOf());
1868 assert(typeid(I
).toHash() == typeid(I
).hashOf());
1871 class TypeInfo_Struct
: TypeInfo
1873 override string
toString() const { return name
; }
1875 override size_t
toHash() const
1877 return hashOf(this.mangledName
);
1880 override bool opEquals(Object o
)
1884 auto s
= cast(const TypeInfo_Struct
)o
;
1885 return s
&& this.mangledName
== s
.mangledName
;
1888 override size_t
getHash(scope const void* p
) @trusted pure nothrow const
1893 return (*xtoHash
)(p
);
1897 return hashOf(p
[0 .. initializer().length
]);
1901 override bool equals(in void* p1
, in void* p2
) @trusted pure nothrow const
1903 import core
.stdc
.string
: memcmp
;
1909 const dg
= _memberFunc(p1
, xopEquals
);
1910 return dg
.xopEquals(p2
);
1915 // BUG: relies on the GC not moving objects
1916 return memcmp(p1
, p2
, initializer().length
) == 0;
1919 override int compare(in void* p1
, in void* p2
) @trusted pure nothrow const
1921 import core
.stdc
.string
: memcmp
;
1923 // Regard null references as always being "less than"
1932 const dg
= _memberFunc(p1
, xopCmp
);
1933 return dg
.xopCmp(p2
);
1936 // BUG: relies on the GC not moving objects
1937 return memcmp(p1
, p2
, initializer().length
);
1945 override @property size_t
tsize() nothrow pure const
1947 return initializer().length
;
1950 override const(void)[] initializer() nothrow pure const @safe
1955 override @property uint flags() nothrow pure const { return m_flags
; }
1957 override @property size_t
talign() nothrow pure const { return m_align
; }
1959 final override void destroy(void* p
) const
1963 if (m_flags
& StructFlags
.isDynamicType
)
1964 (*xdtorti
)(p
, this);
1970 override void postblit(void* p
) const
1978 final @property string
name() nothrow const @trusted
1980 import core
.demangle
: demangleType
;
1982 if (mangledName
is null) // e.g., opaque structs
1985 const key
= cast(const void*) this; // faster lookup than TypeInfo_Struct, at the cost of potential duplicates per binary
1986 static string
[typeof(key
)] demangledNamesCache
; // per thread
1989 //return demangledNamesCache.require(key, cast(string) demangleType(mangledName));
1991 if (auto pDemangled
= key
in demangledNamesCache
)
1994 const demangled
= cast(string
) demangleType(mangledName
);
1995 demangledNamesCache
[key
] = demangled
;
1999 void[] m_init
; // initializer; m_init.ptr == null if 0 initialize
2003 size_t
function(in void*) xtoHash
;
2004 bool function(in void*, in void*) xopEquals
;
2005 int function(in void*, in void*) xopCmp
;
2006 string
function(in void*) xtoString
;
2008 enum StructFlags
: uint
2011 isDynamicType
= 0x2, // built at runtime, needs type info in xdtor
2013 StructFlags m_flags
;
2017 void function(void*) xdtor
;
2018 void function(void*, const TypeInfo_Struct ti
) xdtorti
;
2020 void function(void*) xpostblit
;
2024 override @property immutable(void)* rtInfo() nothrow pure const @safe { return m_RTInfo
; }
2026 version (WithArgTypes
)
2028 override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
2037 immutable(void)* m_RTInfo
; // data for precise GC
2039 // The xopEquals and xopCmp members are function pointers to member
2040 // functions, which is not guaranteed to share the same ABI, as it is not
2041 // known whether the `this` parameter is the first or second argument.
2042 // This wrapper is to convert it to a delegate which will always pass the
2043 // `this` parameter in the correct way.
2044 private struct _memberFunc
2051 const void* funcptr
;
2055 bool delegate(in void*) xopEquals
;
2056 int delegate(in void*) xopCmp
;
2066 bool opEquals(ref const S rhs
) const
2072 assert(!typeid(S
).equals(&s
, &s
));
2075 class TypeInfo_Tuple
: TypeInfo
2077 TypeInfo
[] elements
;
2079 override string
toString() const
2082 foreach (i
, element
; elements
)
2086 s
~= element
.toString();
2092 override bool opEquals(Object o
)
2097 auto t
= cast(const TypeInfo_Tuple
)o
;
2098 if (t
&& elements
.length
== t
.elements
.length
)
2100 for (size_t i
= 0; i
< elements
.length
; i
++)
2102 if (elements
[i
] != t
.elements
[i
])
2110 override size_t
getHash(scope const void* p
) const
2115 override bool equals(in void* p1
, in void* p2
) const
2120 override int compare(in void* p1
, in void* p2
) const
2125 override @property size_t
tsize() nothrow pure const
2130 override const(void)[] initializer() const @trusted
2135 override void swap(void* p1
, void* p2
) const
2140 override void destroy(void* p
) const
2145 override void postblit(void* p
) const
2150 override @property size_t
talign() nothrow pure const
2155 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
2161 class TypeInfo_Const
: TypeInfo
2163 override string
toString() const
2165 return cast(string
) ("const(" ~ base
.toString() ~ ")");
2168 //override bool opEquals(Object o) { return base.opEquals(o); }
2169 override bool opEquals(Object o
)
2174 if (typeid(this) != typeid(o
))
2177 auto t
= cast(TypeInfo_Const
)o
;
2178 return base
.opEquals(t
.base
);
2181 override size_t
getHash(scope const void *p
) const { return base
.getHash(p
); }
2182 override bool equals(in void *p1
, in void *p2
) const { return base
.equals(p1
, p2
); }
2183 override int compare(in void *p1
, in void *p2
) const { return base
.compare(p1
, p2
); }
2184 override @property size_t
tsize() nothrow pure const { return base
.tsize
; }
2185 override void swap(void *p1
, void *p2
) const { return base
.swap(p1
, p2
); }
2187 override @property inout(TypeInfo
) next() nothrow pure inout { return base
.next
; }
2188 override @property uint flags() nothrow pure const { return base
.flags
; }
2190 override const(void)[] initializer() nothrow pure const
2192 return base
.initializer();
2195 override @property size_t
talign() nothrow pure const { return base
.talign
; }
2197 version (WithArgTypes
) override int argTypes(out TypeInfo arg1
, out TypeInfo arg2
)
2199 return base
.argTypes(arg1
, arg2
);
2205 class TypeInfo_Invariant
: TypeInfo_Const
2207 override string
toString() const
2209 return cast(string
) ("immutable(" ~ base
.toString() ~ ")");
2213 class TypeInfo_Shared
: TypeInfo_Const
2215 override string
toString() const
2217 return cast(string
) ("shared(" ~ base
.toString() ~ ")");
2221 class TypeInfo_Inout
: TypeInfo_Const
2223 override string
toString() const
2225 return cast(string
) ("inout(" ~ base
.toString() ~ ")");
2229 // Contents of Moduleinfo._flags
2232 MIctorstart
= 0x1, // we've started constructing it
2233 MIctordone
= 0x2, // finished construction
2234 MIstandalone
= 0x4, // module ctor does not depend on other module
2235 // ctors being done first
2240 MIxgetMembers
= 0x80,
2243 MIimportedModules
= 0x400,
2244 MIlocalClasses
= 0x800,
2248 /*****************************************
2249 * An instance of ModuleInfo is generated into the object file for each compiled module.
2251 * It provides access to various aspects of the module.
2252 * It is not generated for betterC.
2256 uint _flags
; // MIxxxx
2257 uint _index
; // index into _moduleinfo_array[]
2261 deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
2262 void opAssign(const scope ModuleInfo m
) { _flags
= m
._flags
; _index
= m
._index
; }
2270 private void* addrOf(int flag
) return nothrow pure @nogc
2273 assert(flag
>= MItlsctor
&& flag
<= MIname
);
2274 assert(!(flag
& (flag
- 1)) && !(flag
& ~(flag
- 1) << 1));
2278 import core
.stdc
.string
: strlen
;
2280 void* p
= cast(void*)&this + ModuleInfo
.sizeof
;
2282 if (flags
& MItlsctor
)
2284 if (flag
== MItlsctor
) return p
;
2285 p
+= typeof(tlsctor
).sizeof
;
2287 if (flags
& MItlsdtor
)
2289 if (flag
== MItlsdtor
) return p
;
2290 p
+= typeof(tlsdtor
).sizeof
;
2294 if (flag
== MIctor
) return p
;
2295 p
+= typeof(ctor
).sizeof
;
2299 if (flag
== MIdtor
) return p
;
2300 p
+= typeof(dtor
).sizeof
;
2302 if (flags
& MIxgetMembers
)
2304 if (flag
== MIxgetMembers
) return p
;
2305 p
+= typeof(xgetMembers
).sizeof
;
2307 if (flags
& MIictor
)
2309 if (flag
== MIictor
) return p
;
2310 p
+= typeof(ictor
).sizeof
;
2312 if (flags
& MIunitTest
)
2314 if (flag
== MIunitTest
) return p
;
2315 p
+= typeof(unitTest
).sizeof
;
2317 if (flags
& MIimportedModules
)
2319 if (flag
== MIimportedModules
) return p
;
2320 p
+= size_t
.sizeof
+ *cast(size_t
*)p
* typeof(importedModules
[0]).sizeof
;
2322 if (flags
& MIlocalClasses
)
2324 if (flag
== MIlocalClasses
) return p
;
2325 p
+= size_t
.sizeof
+ *cast(size_t
*)p
* typeof(localClasses
[0]).sizeof
;
2327 if (true || flags
& MIname
) // always available for now
2329 if (flag
== MIname
) return p
;
2330 p
+= strlen(cast(immutable char*)p
);
2335 @property uint index() nothrow pure @nogc { return _index
; }
2337 @property uint flags() nothrow pure @nogc { return _flags
; }
2339 /************************
2341 * module constructor for thread locals, `null` if there isn't one
2343 @property void function() tlsctor() nothrow pure @nogc
2345 return flags
& MItlsctor ?
*cast(typeof(return)*)addrOf(MItlsctor
) : null;
2348 /************************
2350 * module destructor for thread locals, `null` if there isn't one
2352 @property void function() tlsdtor() nothrow pure @nogc
2354 return flags
& MItlsdtor ?
*cast(typeof(return)*)addrOf(MItlsdtor
) : null;
2357 /*****************************
2359 * address of a module's `const(MemberInfo)[] getMembers(string)` function, `null` if there isn't one
2361 @property void* xgetMembers() nothrow pure @nogc
2363 return flags
& MIxgetMembers ?
*cast(typeof(return)*)addrOf(MIxgetMembers
) : null;
2366 /************************
2368 * module constructor, `null` if there isn't one
2370 @property void function() ctor() nothrow pure @nogc
2372 return flags
& MIctor ?
*cast(typeof(return)*)addrOf(MIctor
) : null;
2375 /************************
2377 * module destructor, `null` if there isn't one
2379 @property void function() dtor() nothrow pure @nogc
2381 return flags
& MIdtor ?
*cast(typeof(return)*)addrOf(MIdtor
) : null;
2384 /************************
2386 * module order independent constructor, `null` if there isn't one
2388 @property void function() ictor() nothrow pure @nogc
2390 return flags
& MIictor ?
*cast(typeof(return)*)addrOf(MIictor
) : null;
2395 * address of function that runs the module's unittests, `null` if there isn't one
2397 @property void function() unitTest() nothrow pure @nogc
2399 return flags
& MIunitTest ?
*cast(typeof(return)*)addrOf(MIunitTest
) : null;
2404 * array of pointers to the ModuleInfo's of modules imported by this one
2406 @property immutable(ModuleInfo
*)[] importedModules() return nothrow pure @nogc
2408 if (flags
& MIimportedModules
)
2410 auto p
= cast(size_t
*)addrOf(MIimportedModules
);
2411 return (cast(immutable(ModuleInfo
*)*)(p
+ 1))[0 .. *p
];
2418 * array of TypeInfo_Class references for classes defined in this module
2420 @property TypeInfo_Class
[] localClasses() return nothrow pure @nogc
2422 if (flags
& MIlocalClasses
)
2424 auto p
= cast(size_t
*)addrOf(MIlocalClasses
);
2425 return (cast(TypeInfo_Class
*)(p
+ 1))[0 .. *p
];
2430 /********************
2432 * name of module, `null` if no name
2434 @property string
name() return nothrow pure @nogc
2436 import core
.stdc
.string
: strlen
;
2438 auto p
= cast(immutable char*) addrOf(MIname
);
2439 return p
[0 .. strlen(p
)];
2442 static int opApply(scope int delegate(ModuleInfo
*) dg
)
2444 import core
.internal
.traits
: externDFunc
;
2445 alias moduleinfos_apply
= externDFunc
!("rt.minfo.moduleinfos_apply",
2446 int function(scope int delegate(immutable(ModuleInfo
*))));
2447 // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
2448 return moduleinfos_apply(
2449 (immutable(ModuleInfo
*)m
) => dg(cast(ModuleInfo
*)m
));
2456 foreach (m
; ModuleInfo
)
2462 ///////////////////////////////////////////////////////////////////////////////
2464 ///////////////////////////////////////////////////////////////////////////////
2468 * The base class of all thrown objects.
2470 * All thrown objects must inherit from Throwable. Class $(D Exception), which
2471 * derives from this class, represents the category of thrown objects that are
2472 * safe to catch and handle. In principle, one should not catch Throwable
2473 * objects that are not derived from $(D Exception), as they represent
2474 * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
2475 * when these errors are thrown, making it unsafe to continue execution after
2478 class Throwable
: Object
2482 int opApply(scope int delegate(ref const(char[]))) const;
2483 int opApply(scope int delegate(ref size_t
, ref const(char[]))) const;
2484 string
toString() const;
2487 alias TraceDeallocator
= void function(TraceInfo
) nothrow;
2489 string msg
; /// A message describing the error.
2492 * The _file name of the D source code corresponding with
2493 * where the error was thrown from.
2497 * The _line number of the D source code corresponding with
2498 * where the error was thrown from.
2503 * The stack trace of where the error happened. This is an opaque object
2504 * that can either be converted to $(D string), or iterated over with $(D
2505 * foreach) to extract the items in the stack trace (as strings).
2510 * If set, this is used to deallocate the TraceInfo on destruction.
2512 TraceDeallocator infoDeallocator
;
2516 * A reference to the _next error in the list. This is used when a new
2517 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2518 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2521 private Throwable nextInChain
;
2523 private uint _refcount
; // 0 : allocated by GC
2524 // 1 : allocated by _d_newThrowable()
2525 // 2.. : reference count + 1
2529 * A reference to the _next error in the list. This is used when a new
2530 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2531 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2534 @property inout(Throwable
) next() @safe inout return scope pure nothrow @nogc { return nextInChain
; }
2537 * Replace next in chain with `tail`.
2538 * Use `chainTogether` instead if at all possible.
2540 @property void next(Throwable tail
) @safe scope pure nothrow @nogc
2542 if (tail
&& tail
._refcount
)
2543 ++tail
._refcount
; // increment the replacement *first*
2545 auto n
= nextInChain
;
2546 nextInChain
= null; // sever the tail before deleting it
2548 if (n
&& n
._refcount
)
2549 _d_delThrowable(n
); // now delete the old tail
2551 nextInChain
= tail
; // and set the new tail
2556 * mutable reference to the reference count, which is
2557 * 0 - allocated by the GC, 1 - allocated by _d_newThrowable(),
2558 * and >=2 which is the reference count + 1
2560 * Marked as `@system` to discourage casual use of it.
2562 @system @nogc final pure nothrow ref uint refcount() return { return _refcount
; }
2565 * Loop over the chain of Throwables.
2567 int opApply(scope int delegate(Throwable
) dg
)
2570 for (Throwable t
= this; t
; t
= t
.nextInChain
)
2580 * Append `e2` to chain of exceptions that starts with `e1`.
2582 * e1 = start of chain (can be null)
2583 * e2 = second part of chain (can be null)
2585 * Throwable that is at the start of the chain; null if both `e1` and `e2` are null
2587 static @__future @system @nogc pure nothrow Throwable
chainTogether(return scope Throwable e1
, return scope Throwable e2
)
2596 for (auto e
= e1
; 1; e
= e
.nextInChain
)
2607 @nogc @safe pure nothrow this(string msg
, Throwable nextInChain
= null)
2610 this.nextInChain
= nextInChain
;
2611 if (nextInChain
&& nextInChain
._refcount
)
2612 ++nextInChain
._refcount
;
2613 //this.info = _d_traceContext();
2616 @nogc @safe pure nothrow this(string msg
, string file
, size_t line
, Throwable nextInChain
= null)
2618 this(msg
, nextInChain
);
2621 //this.info = _d_traceContext();
2624 @trusted nothrow ~this()
2626 if (nextInChain
&& nextInChain
._refcount
)
2627 _d_delThrowable(nextInChain
);
2628 // handle owned traceinfo
2629 if (infoDeallocator
!is null)
2631 infoDeallocator(info
);
2632 info
= null; // avoid any kind of dangling pointers if we can help
2638 * Overrides $(D Object.toString) and returns the error message.
2639 * Internally this forwards to the $(D toString) overload that
2640 * takes a $(D_PARAM sink) delegate.
2642 override string
toString()
2645 toString((in buf
) { s
~= buf
; });
2650 * The Throwable hierarchy uses a toString overload that takes a
2651 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
2652 * performed in certain error situations. Override this $(D
2653 * toString) method to customize the error message.
2655 void toString(scope void delegate(in char[]) sink
) const
2657 import core
.internal
.string
: unsignedToTempString
;
2659 char[20] tmpBuff
= void;
2661 sink(typeid(this).name
);
2662 sink("@"); sink(file
);
2663 sink("("); sink(unsignedToTempString(line
, tmpBuff
)); sink(")");
2667 sink(": "); sink(msg
);
2673 sink("\n----------------");
2676 sink("\n"); sink(t
);
2681 // ignore more errors
2687 * Get the message describing the error.
2689 * This getter is an alternative way to access the Exception's message,
2690 * with the added advantage of being override-able in subclasses.
2691 * Subclasses are hence free to do their own memory managements without
2692 * being tied to the requirement of providing a `string` in a field.
2694 * The default behavior is to return the `Throwable.msg` field.
2697 * A message representing the cause of the `Throwable`
2699 @__future const(char)[] message() const @safe nothrow
2707 * The base class of all errors that are safe to catch and handle.
2709 * In principle, only thrown objects derived from this class are safe to catch
2710 * inside a $(D catch) block. Thrown objects not derived from Exception
2711 * represent runtime errors that should not be caught, as certain runtime
2712 * guarantees may not hold, making it unsafe to continue program execution.
2714 class Exception
: Throwable
2718 * Creates a new instance of Exception. The nextInChain parameter is used
2719 * internally and should always be $(D null) when passed by user code.
2720 * This constructor does not automatically throw the newly-created
2721 * Exception; the $(D throw) expression should be used for that purpose.
2723 @nogc @safe pure nothrow this(string msg
, string file
= __FILE__
, size_t line
= __LINE__
, Throwable nextInChain
= null)
2725 super(msg
, file
, line
, nextInChain
);
2728 @nogc @safe pure nothrow this(string msg
, Throwable nextInChain
, string file
= __FILE__
, size_t line
= __LINE__
)
2730 super(msg
, file
, line
, nextInChain
);
2740 throw new Exception("msg");
2745 assert(e
.msg
== "msg");
2753 auto e
= new Exception("msg");
2754 assert(e
.file
== __FILE__
);
2755 assert(e
.line
== __LINE__
- 2);
2756 assert(e
.nextInChain
is null);
2757 assert(e
.msg
== "msg");
2761 auto e
= new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
2762 assert(e
.file
== "hello");
2763 assert(e
.line
== 42);
2764 assert(e
.nextInChain
!is null);
2765 assert(e
.msg
== "msg");
2769 auto e
= new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
2770 assert(e
.file
== "hello");
2771 assert(e
.line
== 42);
2772 assert(e
.nextInChain
!is null);
2773 assert(e
.msg
== "msg");
2777 auto e
= new Exception("message");
2778 assert(e
.message
== "message");
2784 * The base class of all unrecoverable runtime errors.
2786 * This represents the category of $(D Throwable) objects that are $(B not)
2787 * safe to catch and handle. In principle, one should not catch Error
2788 * objects, as they represent unrecoverable runtime errors.
2789 * Certain runtime guarantees may fail to hold when these errors are
2790 * thrown, making it unsafe to continue execution after catching them.
2792 class Error
: Throwable
2795 * Creates a new instance of Error. The nextInChain parameter is used
2796 * internally and should always be $(D null) when passed by user code.
2797 * This constructor does not automatically throw the newly-created
2798 * Error; the $(D throw) statement should be used for that purpose.
2800 @nogc @safe pure nothrow this(string msg
, Throwable nextInChain
= null)
2802 super(msg
, nextInChain
);
2803 bypassedException
= null;
2806 @nogc @safe pure nothrow this(string msg
, string file
, size_t line
, Throwable nextInChain
= null)
2808 super(msg
, file
, line
, nextInChain
);
2809 bypassedException
= null;
2812 /** The first $(D Exception) which was bypassed when this Error was thrown,
2813 or $(D null) if no $(D Exception)s were pending. */
2814 Throwable bypassedException
;
2823 throw new Error("msg");
2828 assert(e
.msg
== "msg");
2836 auto e
= new Error("msg");
2837 assert(e
.file
is null);
2838 assert(e
.line
== 0);
2839 assert(e
.nextInChain
is null);
2840 assert(e
.msg
== "msg");
2841 assert(e
.bypassedException
is null);
2845 auto e
= new Error("msg", new Exception("It's an Exception!"));
2846 assert(e
.file
is null);
2847 assert(e
.line
== 0);
2848 assert(e
.nextInChain
!is null);
2849 assert(e
.msg
== "msg");
2850 assert(e
.bypassedException
is null);
2854 auto e
= new Error("msg", "hello", 42, new Exception("It's an Exception!"));
2855 assert(e
.file
== "hello");
2856 assert(e
.line
== 42);
2857 assert(e
.nextInChain
!is null);
2858 assert(e
.msg
== "msg");
2859 assert(e
.bypassedException
is null);
2865 // from druntime/src/rt/aaA.d
2867 private struct AA
{ void* impl
; }
2868 // size_t _aaLen(in AA aa) pure nothrow @nogc;
2869 private void* _aaGetY(scope AA
* paa
, const TypeInfo_AssociativeArray ti
, const size_t valsz
, const scope void* pkey
) pure nothrow;
2870 private void* _aaGetX(scope AA
* paa
, const TypeInfo_AssociativeArray ti
, const size_t valsz
, const scope void* pkey
, out bool found
) pure nothrow;
2871 // inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey);
2872 inout(void[]) _aaValues(inout AA aa
, const size_t keysz
, const size_t valsz
, const TypeInfo tiValueArray
) pure nothrow;
2873 inout(void[]) _aaKeys(inout AA aa
, const size_t keysz
, const TypeInfo tiKeyArray
) pure nothrow;
2874 void* _aaRehash(AA
* paa
, const scope TypeInfo keyti
) pure nothrow;
2875 void _aaClear(AA aa
) pure nothrow;
2877 // alias _dg_t = extern(D) int delegate(void*);
2878 // int _aaApply(AA aa, size_t keysize, _dg_t dg);
2880 // alias _dg2_t = extern(D) int delegate(void*, void*);
2881 // int _aaApply2(AA aa, size_t keysize, _dg2_t dg);
2883 private struct AARange
{ AA impl
; size_t idx
; }
2884 AARange
_aaRange(AA aa
) pure nothrow @nogc @safe;
2885 bool _aaRangeEmpty(AARange r
) pure nothrow @nogc @safe;
2886 void* _aaRangeFrontKey(AARange r
) pure nothrow @nogc @safe;
2887 void* _aaRangeFrontValue(AARange r
) pure nothrow @nogc @safe;
2888 void _aaRangePopFront(ref AARange r
) pure nothrow @nogc @safe;
2890 int _aaEqual(scope const TypeInfo tiRaw
, scope const AA aa1
, scope const AA aa2
);
2891 hash_t
_aaGetHash(scope const AA
* aa
, scope const TypeInfo tiRaw
) nothrow;
2894 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
2895 This is a typesystem hole, however this is existing hole.
2896 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
2897 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
2899 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti
, void[] keys
, void[] values
) pure;
2902 void* aaLiteral(Key
, Value
)(Key
[] keys
, Value
[] values
) @trusted pure
2904 return _d_assocarrayliteralTX(typeid(Value
[Key
]), *cast(void[]*)&keys
, *cast(void[]*)&values
);
2907 // Lower an Associative Array to a newaa struct for static initialization.
2908 auto _aaAsStruct(K
, V
)(V
[K
] aa
) @safe
2910 import core
.internal
.newaa
: makeAA
;
2912 return makeAA
!(K
, V
)(aa
);
2915 alias AssociativeArray(Key
, Value
) = Value
[Key
];
2917 /***********************************
2918 * Removes all remaining keys and values from an associative array.
2920 * aa = The associative array.
2922 void clear(Value
, Key
)(Value
[Key
] aa
) @trusted
2924 _aaClear(*cast(AA
*) &aa
);
2928 void clear(Value
, Key
)(Value
[Key
]* aa
) @trusted
2930 _aaClear(*cast(AA
*) aa
);
2936 auto aa
= ["k1": 2];
2938 assert("k1" !in aa
);
2951 v
["Hello World"] = 42;
2953 assert("Hello World" !in v
);
2956 static assert(!__traits(compiles
, (&v
).clear
));
2957 static assert( __traits(compiles
, (*(&v
)).clear
));
2960 /***********************************
2961 * Reorganizes the associative array in place so that lookups are more
2964 * aa = The associative array.
2966 * The rehashed associative array.
2968 T
rehash(T
: Value
[Key
], Value
, Key
)(T aa
)
2970 _aaRehash(cast(AA
*)&aa
, typeid(Value
[Key
]));
2975 T
rehash(T
: Value
[Key
], Value
, Key
)(T
* aa
)
2977 _aaRehash(cast(AA
*)aa
, typeid(Value
[Key
]));
2982 T
rehash(T
: shared Value
[Key
], Value
, Key
)(T aa
)
2984 _aaRehash(cast(AA
*)&aa
, typeid(Value
[Key
]));
2989 T
rehash(T
: shared Value
[Key
], Value
, Key
)(T
* aa
)
2991 _aaRehash(cast(AA
*)aa
, typeid(Value
[Key
]));
2995 /***********************************
2996 * Creates a new associative array of the same size and copies the contents of
2997 * the associative array into it.
2999 * aa = The associative array.
3001 V
[K
] dup(T
: V
[K
], K
, V
)(T aa
)
3003 //pragma(msg, "K = ", K, ", V = ", V);
3005 // Bug10720 - check whether V is copyable
3006 static assert(is(typeof({ V v
= aa
[K
.init
]; })),
3007 "cannot call " ~ T
.stringof
~ ".dup because " ~ V
.stringof
~ " is not copyable");
3011 //foreach (k, ref v; aa)
3012 // result[k] = v; // Bug13701 - won't work if V is not mutable
3014 ref V
duplicateElem(ref K k
, ref const V v
) @trusted pure nothrow
3016 import core
.stdc
.string
: memcpy
;
3018 void* pv
= _aaGetY(cast(AA
*)&result
, typeid(V
[K
]), V
.sizeof
, &k
);
3019 memcpy(pv
, &v
, V
.sizeof
);
3023 foreach (k
, ref v
; aa
)
3025 static if (!__traits(hasPostblit
, V
))
3026 duplicateElem(k
, v
);
3027 else static if (__traits(isStaticArray
, V
))
3028 _doPostblit(duplicateElem(k
, v
)[]);
3029 else static if (!is(typeof(v
.__xpostblit())) && is(immutable V
== immutable UV
, UV
))
3030 (() @trusted => *cast(UV
*) &duplicateElem(k
, v
))().__xpostblit();
3032 duplicateElem(k
, v
).__xpostblit();
3039 V
[K
] dup(T
: V
[K
], K
, V
)(T
* aa
)
3047 auto aa
= ["k1": 2];
3050 assert("k2" !in a2
);
3053 // this should never be made public.
3054 private AARange
_aaToRange(T
: V
[K
], K
, V
)(ref T aa
) pure nothrow @nogc @safe
3056 // ensure we are dealing with a genuine AA.
3057 static if (is(const(V
[K
]) == const(T
)))
3060 const(V
[K
]) realAA
= aa
;
3061 return _aaRange(() @trusted { return *cast(AA
*)&realAA
; } ());
3064 /***********************************
3065 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3066 * which will iterate over the keys of the associative array. The keys are
3067 * returned by reference.
3069 * If structural changes are made to the array (removing or adding keys), all
3070 * ranges previously obtained through this function are invalidated. The
3071 * following example program will dereference a null pointer:
3074 * import std.stdio : writeln;
3076 * auto dict = ["k1": 1, "k2": 2];
3077 * auto keyRange = dict.byKey;
3079 * writeln(keyRange.front); // Segmentation fault
3083 * aa = The associative array.
3085 * A forward range referencing the keys of the associative array.
3087 auto byKey(T
: V
[K
], K
, V
)(T aa
) pure nothrow @nogc @safe
3089 import core
.internal
.traits
: substInout
;
3091 static struct Result
3096 @property bool empty() @safe { return _aaRangeEmpty(r
); }
3097 @property ref front() @trusted
3099 return *cast(substInout
!K
*) _aaRangeFrontKey(r
);
3101 void popFront() @safe { _aaRangePopFront(r
); }
3102 @property Result
save() { return this; }
3105 return Result(_aaToRange(aa
));
3109 auto byKey(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3111 return (*aa
).byKey();
3117 auto dict
= [1: "v1", 2: "v2"];
3119 foreach (v
; dict
.byKey
)
3125 /***********************************
3126 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3127 * which will iterate over the values of the associative array. The values are
3128 * returned by reference.
3130 * If structural changes are made to the array (removing or adding keys), all
3131 * ranges previously obtained through this function are invalidated. The
3132 * following example program will dereference a null pointer:
3135 * import std.stdio : writeln;
3137 * auto dict = ["k1": 1, "k2": 2];
3138 * auto valueRange = dict.byValue;
3140 * writeln(valueRange.front); // Segmentation fault
3144 * aa = The associative array.
3146 * A forward range referencing the values of the associative array.
3148 auto byValue(T
: V
[K
], K
, V
)(T aa
) pure nothrow @nogc @safe
3150 import core
.internal
.traits
: substInout
;
3152 static struct Result
3157 @property bool empty() @safe { return _aaRangeEmpty(r
); }
3158 @property ref front() @trusted
3160 return *cast(substInout
!V
*) _aaRangeFrontValue(r
);
3162 void popFront() @safe { _aaRangePopFront(r
); }
3163 @property Result
save() { return this; }
3166 return Result(_aaToRange(aa
));
3170 auto byValue(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3172 return (*aa
).byValue();
3178 auto dict
= ["k1": 1, "k2": 2];
3180 foreach (v
; dict
.byValue
)
3186 /***********************************
3187 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3188 * which will iterate over the key-value pairs of the associative array. The
3189 * returned pairs are represented by an opaque type with `.key` and `.value`
3190 * properties for accessing references to the key and value of the pair,
3193 * If structural changes are made to the array (removing or adding keys), all
3194 * ranges previously obtained through this function are invalidated. The
3195 * following example program will dereference a null pointer:
3198 * import std.stdio : writeln;
3200 * auto dict = ["k1": 1, "k2": 2];
3201 * auto kvRange = dict.byKeyValue;
3203 * writeln(kvRange.front.key, ": ", kvRange.front.value); // Segmentation fault
3206 * Note that this is a low-level interface to iterating over the associative
3207 * array and is not compatible withth the
3208 * $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) type in Phobos.
3209 * For compatibility with `Tuple`, use
3210 * $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead.
3213 * aa = The associative array.
3215 * A forward range referencing the pairs of the associative array.
3217 auto byKeyValue(T
: V
[K
], K
, V
)(T aa
) pure nothrow @nogc @safe
3219 import core
.internal
.traits
: substInout
;
3221 static struct Result
3226 @property bool empty() @safe { return _aaRangeEmpty(r
); }
3227 @property auto front()
3231 // We save the pointers here so that the Pair we return
3232 // won't mutate when Result.popFront is called afterwards.
3236 @property ref key() inout @trusted
3238 return *cast(substInout
!K
*) keyp
;
3240 @property ref value() inout @trusted
3242 return *cast(substInout
!V
*) valp
;
3245 return Pair(_aaRangeFrontKey(r
),
3246 _aaRangeFrontValue(r
));
3248 void popFront() @safe { return _aaRangePopFront(r
); }
3249 @property Result
save() { return this; }
3252 return Result(_aaToRange(aa
));
3256 auto byKeyValue(T
: V
[K
], K
, V
)(T
* aa
) pure nothrow @nogc
3258 return (*aa
).byKeyValue();
3264 auto dict
= ["k1": 1, "k2": 2];
3266 foreach (e
; dict
.byKeyValue
)
3268 assert(e
.key
[1] == e
.value
+ '0');
3275 /***********************************
3276 * Returns a newly allocated dynamic array containing a copy of the keys from
3277 * the associative array.
3279 * aa = The associative array.
3281 * A dynamic array containing a copy of the keys.
3283 Key
[] keys(T
: Value
[Key
], Value
, Key
)(T aa
) @property
3285 // ensure we are dealing with a genuine AA.
3286 static if (is(const(Value
[Key
]) == const(T
)))
3289 const(Value
[Key
]) realAA
= aa
;
3290 auto res
= () @trusted {
3291 auto a
= cast(void[])_aaKeys(*cast(inout(AA
)*)&realAA
, Key
.sizeof
, typeid(Key
[]));
3292 return *cast(Key
[]*)&a
;
3294 static if (__traits(hasPostblit
, Key
))
3300 Key
[] keys(T
: Value
[Key
], Value
, Key
)(T
*aa
) @property
3308 auto aa
= [1: "v1", 2: "v2"];
3310 foreach (k
; aa
.keys
)
3321 void[][string
] dict
;
3326 assert(s
.keys
.length
== 0);
3331 @safe static struct Key
3337 static assert(__traits(compiles
, {
3349 this(this) @system {}
3352 static assert(!__traits(compiles
, {
3359 /***********************************
3360 * Returns a newly allocated dynamic array containing a copy of the values from
3361 * the associative array.
3363 * aa = The associative array.
3365 * A dynamic array containing a copy of the values.
3367 Value
[] values(T
: Value
[Key
], Value
, Key
)(T aa
) @property
3369 // ensure we are dealing with a genuine AA.
3370 static if (is(const(Value
[Key
]) == const(T
)))
3373 const(Value
[Key
]) realAA
= aa
;
3374 auto res
= () @trusted {
3375 auto a
= cast(void[])_aaValues(*cast(inout(AA
)*)&realAA
, Key
.sizeof
, Value
.sizeof
, typeid(Value
[]));
3376 return *cast(Value
[]*)&a
;
3378 static if (__traits(hasPostblit
, Value
))
3384 Value
[] values(T
: Value
[Key
], Value
, Key
)(T
*aa
) @property
3386 return (*aa
).values
;
3392 auto aa
= ["k1": 1, "k2": 2];
3394 foreach (e
; aa
.values
)
3405 void[][string
] dict
;
3410 assert(s
.values
.length
== 0);
3415 @safe static struct Value
3421 static assert(__traits(compiles
, {
3423 const _
= aa
.values
;
3433 this(this) @system {}
3436 static assert(!__traits(compiles
, {
3438 const _
= aa
.values
;
3443 /***********************************
3444 * Looks up key; if it exists returns corresponding value else evaluates and
3445 * returns defaultValue.
3447 * aa = The associative array.
3449 * defaultValue = The default value.
3453 inout(V
) get(K
, V
)(inout(V
[K
]) aa
, K key
, lazy inout(V
) defaultValue
)
3456 return p ?
*p
: defaultValue
;
3460 inout(V
) get(K
, V
)(inout(V
[K
])* aa
, K key
, lazy inout(V
) defaultValue
)
3462 return (*aa
).get(key
, defaultValue
);
3468 auto aa
= ["k1": 1];
3469 assert(aa
.get("k1", 0) == 1);
3470 assert(aa
.get("k2", 0) == 0);
3473 /***********************************
3474 * Looks up key; if it exists returns corresponding value else evaluates
3475 * value, adds it to the associative array and returns it.
3477 * aa = The associative array.
3479 * value = The required value.
3483 ref V
require(K
, V
)(ref V
[K
] aa
, K key
, lazy V value
= V
.init
)
3486 // if key is @safe-ly copyable, `require` can infer @safe
3487 static if (isSafeCopyable
!K
)
3489 auto p
= () @trusted
3491 return cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
3496 auto p
= cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
3502 *p
= value
; // Not `return (*p = value)` since if `=` is overloaded
3503 return *p
; // this might not return a ref to the left-hand side.
3510 auto aa
= ["k1": 1];
3511 assert(aa
.require("k1", 0) == 1);
3512 assert(aa
.require("k2", 0) == 0);
3513 assert(aa
["k2"] == 0);
3516 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test.
3517 private enum bool isSafeCopyable(T
) = is(typeof(() @safe { union U
{ T x
; } T
*x
; auto u
= U(*x
); }));
3519 /***********************************
3520 * Calls `create` if `key` doesn't exist in the associative array,
3521 * otherwise calls `update`.
3522 * `create` returns a corresponding value for `key`.
3523 * `update` accepts a key parameter. If it returns a value, the value is
3526 * aa = The associative array.
3528 * create = The callable to create a value for `key`.
3530 * update = The callable to call if `key` exists.
3531 * Takes a K argument, returns a V or void.
3533 void update(K
, V
, C
, U
)(ref V
[K
] aa
, K key
, scope C create
, scope U update
)
3534 if (is(typeof(create()) : V
) && (is(typeof(update(aa
[K
.init
])) : V
) ||
is(typeof(update(aa
[K
.init
])) == void)))
3537 // if key is @safe-ly copyable, `update` may infer @safe
3538 static if (isSafeCopyable
!K
)
3540 auto p
= () @trusted
3542 return cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
3547 auto p
= cast(V
*) _aaGetX(cast(AA
*) &aa
, typeid(V
[K
]), V
.sizeof
, &key
, found
);
3553 static if (is(typeof(update(*p
)) == void))
3568 (int) {} // not executed
3570 assert(aa
["key"] == 1);
3572 // update value by ref
3574 () => 0, // not executed
3578 assert(aa
["key"] == 2);
3580 // update from return value
3582 () => 0, // not executed
3585 assert(aa
["key"] == 4);
3587 // 'update' without changing value
3589 () => 0, // not executed
3591 // do something else
3593 assert(aa
["key"] == 4);
3602 this(this) @system {}
3606 bool opEquals(S rhs
) { assert(0); }
3607 size_t
toHash() { assert(0); }
3611 static assert(is(typeof(() @safe { aai
.require("a", 1234); })));
3612 static assert(is(typeof(() @safe { aai
.update("a", { return 1234; }, (ref int x
) { x
++; return x
; }); })));
3615 static assert(is(typeof(() { aas.require("a", S(1234)); })));
3616 static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s
) { s
.x
++; return s
; }); })));
3617 static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s
) { s
.x
++; return s
; }); })));
3620 static assert(is(typeof(() { aais
.require(S(1234), 1234); })));
3621 static assert(is(typeof(() { aais
.update(S(1234), { return 1234; }, (ref int x
) { x
++; return x
; }); })));
3622 static assert(!is(typeof(() @safe { aais
.require(S(1234), 1234); })));
3623 static assert(!is(typeof(() @safe { aais
.update(S(1234), { return 1234; }, (ref int x
) { x
++; return x
; }); })));
3630 int opCall(ref int v
)
3643 T
opCall(T
)(ref T v
)
3649 int[string
] a
= ["2" : 1];
3650 a
.update("2", () => -1, S0
.init
);
3651 assert(a
["2"] == 2);
3652 a
.update("0", () => -1, S0
.init
);
3653 assert(a
["0"] == -1);
3654 a
.update("2", S1
.init
, S1
.init
);
3655 assert(a
["2"] == 3);
3656 a
.update("1", S1
.init
, S1
.init
);
3657 assert(a
["1"] == -2);
3670 assert(aa
["k1"] == 10);
3675 // This lets DDoc produce better documentation.
3678 Calculates the hash value of `arg` with an optional `seed` initial value.
3679 The result might not be equal to `typeid(T).getHash(&arg)`.
3682 arg = argument to calculate the hash value of
3683 seed = optional `seed` value (may be used for hash chaining)
3685 Return: calculated hash value of `arg`
3687 size_t
hashOf(T
)(auto ref T arg
, size_t seed
)
3689 static import core
.internal
.hash
;
3690 return core
.internal
.hash
.hashOf(arg
, seed
);
3693 size_t
hashOf(T
)(auto ref T arg
)
3695 static import core
.internal
.hash
;
3696 return core
.internal
.hash
.hashOf(arg
);
3701 auto h1
= "my.string".hashOf
;
3702 assert(h1
== "my.string".hashOf
);
3707 public import core
.internal
.hash
: hashOf
;
3715 size_t
myMegaHash() const @safe pure nothrow
3725 size_t
toHash() const pure nothrow
3727 size_t hash
= a
.hashOf();
3728 hash
= b
.hashOf(hash
);
3729 size_t h1
= c
.myMegaHash();
3730 hash
= h1
.hashOf(hash
); //Mix two hash values
3736 bool _xopEquals(in void*, in void*)
3738 throw new Error("TypeInfo.equals is not implemented");
3741 bool _xopCmp(in void*, in void*)
3743 throw new Error("TypeInfo.compare is not implemented");
3746 /******************************************
3747 * Create RTInfo for type T
3750 template RTInfoImpl(size_t
[] pointerBitmap
)
3752 immutable size_t
[pointerBitmap
.length
] RTInfoImpl
= pointerBitmap
[];
3755 template NoPointersBitmapPayload(size_t N
)
3757 enum size_t
[N
] NoPointersBitmapPayload
= 0;
3762 enum pointerBitmap
= __traits(getPointerBitmap
, T
);
3763 static if (pointerBitmap
[1 .. $] == NoPointersBitmapPayload
!(pointerBitmap
.length
- 1))
3764 enum RTInfo
= rtinfoNoPointers
;
3766 enum RTInfo
= RTInfoImpl
!(pointerBitmap
).ptr
;
3770 * shortcuts for the precise GC, also generated by the compiler
3771 * used instead of the actual pointer bitmap
3773 enum immutable(void)* rtinfoNoPointers
= null;
3774 enum immutable(void)* rtinfoHasPointers
= cast(void*)1;
3778 private inout(TypeInfo
) getElement(return scope inout TypeInfo value
) @trusted pure nothrow
3780 TypeInfo element
= cast() value
;
3783 if (auto qualified
= cast(TypeInfo_Const
) element
)
3784 element
= qualified
.base
;
3785 else if (auto redefined
= cast(TypeInfo_Enum
) element
)
3786 element
= redefined
.base
;
3787 else if (auto staticArray
= cast(TypeInfo_StaticArray
) element
)
3788 element
= staticArray
.value
;
3789 else if (auto vector
= cast(TypeInfo_Vector
) element
)
3790 element
= vector
.base
;
3794 return cast(inout) element
;
3797 private size_t
getArrayHash(const scope TypeInfo element
, const scope void* ptr
, const size_t count
) @trusted nothrow
3802 const size_t elementSize
= element
.tsize
;
3806 static bool hasCustomToHash(const scope TypeInfo value
) @trusted pure nothrow
3808 const element
= getElement(value
);
3810 if (const struct_
= cast(const TypeInfo_Struct
) element
)
3811 return !!struct_
.xtoHash
;
3813 return cast(const TypeInfo_Array
) element
3814 ||
cast(const TypeInfo_AssociativeArray
) element
3815 ||
cast(const ClassInfo
) element
3816 ||
cast(const TypeInfo_Interface
) element
;
3819 if (!hasCustomToHash(element
))
3820 return hashOf(ptr
[0 .. elementSize
* count
]);
3823 foreach (size_t i
; 0 .. count
)
3824 hash
= hashOf(element
.getHash(ptr
+ i
* elementSize
), hash
);
3828 /// Provide the .dup array property.
3829 @property auto dup(T
)(T
[] a
)
3830 if (!is(const(T
) : T
))
3832 import core
.internal
.traits
: Unconst
;
3833 import core
.internal
.array
.duplication
: _dup
;
3834 static assert(is(T
: Unconst
!T
), "Cannot implicitly convert type "~T
.stringof
~
3835 " to "~Unconst
!T
.stringof
~" in dup.");
3837 return _dup
!(T
, Unconst
!T
)(a
);
3844 auto arr2
= arr
.dup
;
3846 assert(arr
== [0, 2]);
3847 assert(arr2
== [1, 2]);
3851 // const overload to support implicit conversion to immutable (unique result, see DIP29)
3852 @property T
[] dup(T
)(const(T
)[] a
)
3853 if (is(const(T
) : T
))
3855 import core
.internal
.array
.duplication
: _dup
;
3856 return _dup
!(const(T
), T
)(a
);
3860 /// Provide the .idup array property.
3861 @property immutable(T
)[] idup(T
)(T
[] a
)
3863 import core
.internal
.array
.duplication
: _dup
;
3864 static assert(is(T
: immutable(T
)), "Cannot implicitly convert type "~T
.stringof
~
3865 " to immutable in idup.");
3866 return _dup
!(T
, immutable(T
))(a
);
3870 @property immutable(T
)[] idup(T
:void)(const(T
)[] a
)
3878 char[] arr
= ['a', 'b', 'c'];
3879 string s
= arr
.idup
;
3884 // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
3885 // necessary for now to prevent breaking code.
3886 private extern (C
) size_t
_d_arraysetcapacity(const TypeInfo ti
, size_t newcapacity
, void[]* arrptr
) pure nothrow;
3889 (Property) Gets the current _capacity of a slice. The _capacity is the size
3890 that the slice can grow to before the underlying array must be
3891 reallocated or extended.
3893 If an append must reallocate a slice with no possibility of extension, then
3894 `0` is returned. This happens when the slice references a static array, or
3895 if another slice references elements past the end of the current slice.
3897 Note: The _capacity of a slice may be impacted by operations on other slices.
3899 @property size_t
capacity(T
)(T
[] arr
) pure nothrow @trusted
3901 return _d_arraysetcapacity(typeid(T
[]), 0, cast(void[]*)&arr
);
3907 //Static array slice: no capacity
3908 int[4] sarray
= [1, 2, 3, 4];
3909 int[] slice
= sarray
[];
3910 assert(sarray
.capacity
== 0);
3911 //Appending to slice will reallocate to a new array
3913 assert(slice
.capacity
>= 5);
3915 //Dynamic array slices
3916 int[] a
= [1, 2, 3, 4];
3917 int[] b
= a
[1 .. $];
3918 int[] c
= a
[1 .. $ - 1];
3919 debug(SENTINEL
) {} else // non-zero capacity very much depends on the array and GC implementation
3921 assert(a
.capacity
!= 0);
3922 assert(a
.capacity
== b
.capacity
+ 1); //both a and b share the same tail
3924 assert(c
.capacity
== 0); //an append to c must relocate c.
3928 Reserves capacity for a slice. The capacity is the size
3929 that the slice can grow to before the underlying array must be
3930 reallocated or extended.
3932 Returns: The new capacity of the array (which may be larger than
3933 the requested capacity).
3935 size_t
reserve(T
)(ref T
[] arr
, size_t newcapacity
) pure nothrow @trusted
3940 return _d_arraysetcapacity(typeid(T
[]), newcapacity
, cast(void[]*)&arr
);
3946 //Static array slice: no capacity. Reserve relocates.
3947 int[4] sarray
= [1, 2, 3, 4];
3948 int[] slice
= sarray
[];
3949 auto u
= slice
.reserve(8);
3951 assert(&sarray
[0] !is &slice
[0]);
3952 assert(slice
.capacity
== u
);
3954 //Dynamic array slices
3955 int[] a
= [1, 2, 3, 4];
3956 a
.reserve(8); //prepare a for appending 4 more items
3960 assert(p
== &a
[0]); //a should not have been reallocated
3961 assert(u
== a
.capacity
); //a should not have been extended
3964 // https://issues.dlang.org/show_bug.cgi?id=12330, reserve() at CTFE time
3969 auto a
= result
.reserve
= 5;
3976 // Issue 6646: should be possible to use array.reserve from SafeD.
3983 // HACK: This is a lie. `_d_arrayshrinkfit` is not `nothrow`, but this lie is necessary
3984 // for now to prevent breaking code.
3985 private extern (C
) void _d_arrayshrinkfit(const TypeInfo ti
, void[] arr
) nothrow;
3988 Assume that it is safe to append to this array. Appends made to this array
3989 after calling this function may append in place, even if the array was a
3990 slice of a larger array to begin with.
3992 Use this only when it is certain there are no elements in use beyond the
3993 array in the memory block. If there are, those elements will be
3994 overwritten by appending to this array.
3996 Warning: Calling this function, and then using references to data located after the
3997 given array results in undefined behavior.
4000 The input is returned.
4002 auto ref inout(T
[]) assumeSafeAppend(T
)(auto ref inout(T
[]) arr
) nothrow @system
4004 _d_arrayshrinkfit(typeid(T
[]), *(cast(void[]*)&arr
));
4011 int[] a
= [1, 2, 3, 4];
4013 // Without assumeSafeAppend. Appending relocates.
4014 int[] b
= a
[0 .. 3];
4016 assert(a
.ptr
!= b
.ptr
);
4018 debug(SENTINEL
) {} else
4020 // With assumeSafeAppend. Appending overwrites.
4021 int[] c
= a
[0 .. 3];
4022 c
.assumeSafeAppend() ~= 5;
4023 assert(a
.ptr
== c
.ptr
);
4030 auto newcap
= arr
.reserve(2000);
4031 assert(newcap
>= 2000);
4032 assert(newcap
== arr
.capacity
);
4034 foreach (i
; 0..2000)
4036 assert(ptr
== arr
.ptr
);
4038 arr
.assumeSafeAppend();
4040 assert(ptr
== arr
.ptr
);
4045 int[] arr
= [1, 2, 3];
4046 void foo(ref int[] i
)
4051 foo(assumeSafeAppend(arr
)); //pass by ref
4052 assert(arr
[]==[1, 2, 5]);
4053 arr
= arr
[0 .. 1].assumeSafeAppend(); //pass by value
4056 // https://issues.dlang.org/show_bug.cgi?id=10574
4061 auto a2
= &assumeSafeAppend(a
);
4062 auto b2
= &assumeSafeAppend(b
);
4063 auto a3
= assumeSafeAppend(a
[]);
4064 auto b3
= assumeSafeAppend(b
[]);
4065 assert(is(typeof(*a2
) == int[]));
4066 assert(is(typeof(*b2
) == immutable(int[])));
4067 assert(is(typeof(a3
) == int[]));
4068 assert(is(typeof(b3
) == immutable(int[])));
4071 private void _doPostblit(T
)(T
[] arr
)
4073 // infer static postblit type, run postblit if any
4074 static if (__traits(hasPostblit
, T
))
4076 static if (__traits(isStaticArray
, T
) && is(T
: E
[], E
))
4077 _doPostblit(cast(E
[]) arr
);
4078 else static if (!is(typeof(arr
[0].__xpostblit())) && is(immutable T
== immutable U
, U
))
4079 foreach (ref elem
; (() @trusted => cast(U
[]) arr
)())
4082 foreach (ref elem
; arr
)
4088 Destroys the given object and optionally resets to initial state. It's used to
4089 _destroy an object, calling its destructor or finalizer so it no longer
4090 references any other objects. It does $(I not) initiate a GC cycle or free
4092 If `initialize` is supplied `false`, the object is considered invalid after
4093 destruction, and should not be referenced.
4095 void destroy(bool initialize
= true, T
)(ref T obj
) if (is(T
== struct))
4097 import core
.internal
.destruction
: destructRecurse
;
4099 destructRecurse(obj
);
4101 static if (initialize
)
4103 import core
.internal
.lifetime
: emplaceInitializer
;
4104 emplaceInitializer(obj
); // emplace T.init
4110 struct A
{ string s
= "A"; }
4117 nothrow @safe @nogc unittest
4120 struct A
{ string s
= "A"; }
4124 assert(a
.s
== "asd");
4129 static int destroyed
= 0;
4133 ~this() nothrow @safe @nogc
4143 ~this() nothrow @safe @nogc
4152 assert(destroyed
== 2);
4153 assert(a
.s
== "asd");
4154 assert(a
.c
.s
== "jkl" );
4156 assert(destroyed
== 4);
4158 assert(a
.c
.s
== "C" );
4162 private extern (C
) void rt_finalize2(void* p
, bool det
= true, bool resetMemory
= true) nothrow;
4165 void destroy(bool initialize
= true, T
)(T obj
) if (is(T
== class))
4167 static if (__traits(getLinkage
, T
) == "C++")
4169 static if (__traits(hasMember
, T
, "__xdtor"))
4172 static if (initialize
)
4174 const initializer
= __traits(initSymbol
, T
);
4175 (cast(void*)obj
)[0 .. initializer
.length
] = initializer
[];
4180 // Bypass overloaded opCast
4181 auto ptr
= (() @trusted => *cast(void**) &obj
)();
4182 rt_finalize2(ptr
, true, initialize
);
4187 void destroy(bool initialize
= true, T
)(T obj
) if (is(T
== interface))
4189 static assert(__traits(getLinkage
, T
) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage
, T
) ~ ") interface");
4191 destroy
!initialize(cast(Object
)obj
);
4194 /// Reference type demonstration
4201 static int dtorCount
;
4204 ~this() { dtorCount
++; }
4207 static int dtorCount
;
4211 ~this() { dtorCount
++; }
4215 assert(c
.dtorCount
== 0); // destructor not yet called
4216 assert(c
.s
== "S"); // initial state `c.s` is `"S"`
4217 assert(c
.a
.dtorCount
== 0); // destructor not yet called
4218 assert(c
.a
.x
== 10); // initial state `c.a.x` is `10`
4221 assert(c
.s
== "T"); // `c.s` is `"T"`
4223 assert(c
.dtorCount
== 1); // `c`'s destructor was called
4224 assert(c
.s
== "S"); // `c.s` is back to its inital state, `"S"`
4225 assert(c
.a
.dtorCount
== 1); // `c.a`'s destructor was called
4226 assert(c
.a
.x
== 10); // `c.a.x` is back to its inital state, `10`
4229 /// C++ classes work too
4232 extern (C
++) class CPP
4236 __gshared
int dtorCount
;
4239 ~this() { dtorCount
++; }
4242 __gshared
int dtorCount
;
4246 ~this() { dtorCount
++; }
4249 CPP cpp
= new CPP();
4250 assert(cpp
.dtorCount
== 0); // destructor not yet called
4251 assert(cpp
.s
== "S"); // initial state `cpp.s` is `"S"`
4252 assert(cpp
.a
.dtorCount
== 0); // destructor not yet called
4253 assert(cpp
.a
.x
== 10); // initial state `cpp.a.x` is `10`
4256 assert(cpp
.s
== "T"); // `cpp.s` is `"T"`
4257 destroy
!false(cpp
); // destroy without initialization
4258 assert(cpp
.dtorCount
== 1); // `cpp`'s destructor was called
4259 assert(cpp
.s
== "T"); // `cpp.s` is not initialized
4260 assert(cpp
.a
.dtorCount
== 1); // `cpp.a`'s destructor was called
4261 assert(cpp
.a
.x
== 30); // `cpp.a.x` is not initialized
4263 assert(cpp
.dtorCount
== 2); // `cpp`'s destructor was called again
4264 assert(cpp
.s
== "S"); // `cpp.s` is back to its inital state, `"S"`
4265 assert(cpp
.a
.dtorCount
== 2); // `cpp.a`'s destructor was called again
4266 assert(cpp
.a
.x
== 10); // `cpp.a.x` is back to its inital state, `10`
4269 /// Value type demonstration
4273 assert(i
== 0); // `i`'s initial state is `0`
4275 assert(i
== 1); // `i` changed to `1`
4277 assert(i
== 1); // `i` was not initialized
4279 assert(i
== 0); // `i` is back to its initial state `0`
4282 /// Nested struct type
4291 dtorCount
++; // capture local variable
4296 assert(dtorCount
== 1);
4300 assert(dtorCount
== 2);
4303 // the context pointer is now null
4304 // restore it so the dtor can run
4305 import core
.lifetime
: emplace
;
4307 // dtor also called here
4319 destroy
!false(new C());
4320 destroy
!true(new C());
4325 // class with an `alias this`
4328 static int dtorCount
;
4343 static int dtorCount
;
4350 assert(A
.dtorCount
== 0);
4351 assert(B
.dtorCount
== 0);
4353 assert(A
.dtorCount
== 0);
4354 assert(B
.dtorCount
== 1);
4358 assert(A
.dtorCount
== 1);
4365 class A
: I
{ string s
= "A"; this() {} }
4366 auto a
= new A
, b
= new A
;
4376 static bool destroyed
= false;
4386 auto a
= new B
, b
= new B
;
4398 // this test is invalid now that the default ctor is not run after clearing
4416 nothrow @safe @nogc unittest
4419 struct A
{ string s
= "A"; }
4423 assert(a
.s
== "asd");
4428 static int destroyed
= 0;
4432 ~this() nothrow @safe @nogc
4442 ~this() nothrow @safe @nogc
4451 assert(destroyed
== 2);
4452 assert(a
.s
== "asd");
4453 assert(a
.c
.s
== "jkl" );
4455 assert(destroyed
== 4);
4457 assert(a
.c
.s
== "C" );
4463 // Bugzilla 20049: Test to ensure proper behavior of `nothrow` destructors
4466 static int dtorCount
= 0;
4468 ~this() nothrow { dtorCount
++; }
4473 assert(C
.dtorCount
== 1);
4476 // https://issues.dlang.org/show_bug.cgi?id=22832
4482 A
opCast(T
: A
)() { return A(); }
4488 // make sure destroy!false skips re-initialization
4491 static struct S
{ int x
; }
4492 static class C
{ int x
; }
4493 static extern(C
++) class Cpp
{ int x
; }
4495 static void test(T
)(T inst
)
4498 destroy
!false(inst
);
4499 assert(inst
.x
== 123, T
.stringof
);
4508 void destroy(bool initialize
= true, T
)(ref T obj
)
4509 if (__traits(isStaticArray
, T
))
4511 foreach_reverse (ref e
; obj
[])
4512 destroy
!initialize(e
);
4521 assert(a
== [ 1, 2 ]);
4523 assert(a
== [ 0, 0 ]);
4528 static struct vec2f
{
4534 destroy
!(true, vec2f
)(v
);
4544 this(int x
) { op
~= "C" ~ cast(char)('0'+x
); this.x
= x
; }
4545 this(this) { op
~= "P" ~ cast(char)('0'+x
); }
4546 ~this() { op
~= "D" ~ cast(char)('0'+x
); }
4550 S
[2] a1
= [S(1), S(2)];
4553 assert(op
== "D2D1"); // built-in scope destruction
4555 S
[2] a1
= [S(1), S(2)];
4558 assert(op
== "D2D1"); // consistent with built-in behavior
4562 S
[2][2] a2
= [[S(1), S(2)], [S(3), S(4)]];
4565 assert(op
== "D4D3D2D1");
4567 S
[2][2] a2
= [[S(1), S(2)], [S(3), S(4)]];
4570 assert(op
== "D4D3D2D1", op
);
4574 // https://issues.dlang.org/show_bug.cgi?id=19218
4579 static dtorCount
= 0;
4580 ~this() { ++dtorCount
; }
4585 ref S
[3] getArray();
4586 alias getArray
this;
4591 static dtorCount
= 0;
4592 ~this() { ++dtorCount
; }
4597 ref S
[3] getArray() { return a
; }
4602 assert(S
.dtorCount
== 3);
4603 assert(C
.dtorCount
== 1);
4607 assert(S
.dtorCount
== 6);
4608 assert(C
.dtorCount
== 2);
4612 void destroy(bool initialize
= true, T
)(ref T obj
)
4613 if (!is(T
== struct) && !is(T
== interface) && !is(T
== class) && !__traits(isStaticArray
, T
))
4615 static if (initialize
)
4633 assert(a
!= a
); // isnan
4640 static struct HasDtor
4642 ~this() { assert(0); }
4651 assert(o
.ptr
is null);
4652 destroy(o
); // must not reach in HasDtor.__dtor()
4655 /* ************************************************************************
4657 The compiler lowers certain expressions to instantiations of the following
4658 templates. They must be implicitly imported, which is why they are here
4659 in this file. They must also be `public` as they must be visible from the
4660 scope in which they are instantiated. They are explicitly undocumented as
4661 they are only intended to be instantiated by the compiler, not the user.
4662 **************************************************************************/
4664 public import core
.internal
.entrypoint
: _d_cmain
;
4666 public import core
.internal
.array
.appending
: _d_arrayappendT
;
4667 version (D_ProfileGC
)
4669 public import core
.internal
.array
.appending
: _d_arrayappendTTrace
;
4670 public import core
.internal
.array
.appending
: _d_arrayappendcTXTrace
;
4671 public import core
.internal
.array
.concatenation
: _d_arraycatnTXTrace
;
4672 public import core
.lifetime
: _d_newitemTTrace
;
4673 public import core
.internal
.array
.construction
: _d_newarrayTTrace
;
4674 public import core
.internal
.array
.construction
: _d_newarraymTXTrace
;
4676 public import core
.internal
.array
.appending
: _d_arrayappendcTX
;
4677 public import core
.internal
.array
.comparison
: __cmp
;
4678 public import core
.internal
.array
.equality
: __equals
;
4679 public import core
.internal
.array
.casting
: __ArrayCast
;
4680 public import core
.internal
.array
.concatenation
: _d_arraycatnTX
;
4681 public import core
.internal
.array
.construction
: _d_arrayctor
;
4682 public import core
.internal
.array
.construction
: _d_arraysetctor
;
4683 public import core
.internal
.array
.construction
: _d_newarrayT
;
4684 public import core
.internal
.array
.construction
: _d_newarraymTX
;
4685 public import core
.internal
.array
.arrayassign
: _d_arrayassign_l
;
4686 public import core
.internal
.array
.arrayassign
: _d_arrayassign_r
;
4687 public import core
.internal
.array
.arrayassign
: _d_arraysetassign
;
4688 public import core
.internal
.array
.capacity
: _d_arraysetlengthTImpl
;
4690 public import core
.internal
.dassert
: _d_assert_fail
;
4692 public import core
.internal
.destruction
: __ArrayDtor
;
4694 public import core
.internal
.moving
: __move_post_blt
;
4696 public import core
.internal
.postblit
: __ArrayPostblit
;
4698 public import core
.internal
.switch_
: __switch
;
4699 public import core
.internal
.switch_
: __switch_error
;
4701 public import core
.lifetime
: _d_delstructImpl
;
4702 public import core
.lifetime
: _d_newThrowable
;
4703 public import core
.lifetime
: _d_newclassT
;
4704 public import core
.lifetime
: _d_newclassTTrace
;
4705 public import core
.lifetime
: _d_newitemT
;
4707 public @trusted @nogc nothrow pure extern (C
) void _d_delThrowable(scope Throwable
);
4709 // Compare class and interface objects for ordering.
4710 int __cmp(C1
, C2
)(C1 lhs
, C2 rhs
)
4711 if ((is(C1
: const(Object
)) ||
(is(C1
== interface) && (__traits(getLinkage
, C1
) == "D"))) &&
4712 (is(C2
: const(Object
)) ||
(is(C2
== interface) && (__traits(getLinkage
, C2
) == "D"))))
4714 static if (is(C1
== typeof(null)) && is(C2
== typeof(null)))
4718 else static if (is(C1
== typeof(null)))
4720 // Regard null references as always being "less than"
4723 else static if (is(C2
== typeof(null)))
4735 return lhs
.opCmp(rhs
);
4745 this(int i
) { this.i
= i
; }
4747 override int opCmp(Object c
) const @safe
4749 return i
- (cast(C
)c
).i
;
4755 assert(__cmp(c1
, null) > 0);
4756 assert(__cmp(null, c1
) < 0);
4757 assert(__cmp(c1
, c1
) == 0);
4758 assert(__cmp(c1
, c2
) < 0);
4759 assert(__cmp(c2
, c1
) > 0);
4761 assert(__cmp([c1
, c1
][], [c2
, c2
][]) < 0);
4762 assert(__cmp([c2
, c2
], [c1
, c1
]) > 0);
4771 this(ubyte i
) { this.i
= i
; }
4777 assert(__cmp([c1
, c1
][], [c2
, c2
][]) < 0);
4778 assert(__cmp([c2
, c2
], [c1
, c1
]) > 0);
4779 assert(__cmp([c2
, c2
], [c2
, c1
]) > 0);
4788 assert(a
< "helloo");
4789 assert(a
<= "helloo");
4790 assert(a
> "betty");
4791 assert(a
>= "betty");
4792 assert(a
== "hello");
4793 assert(a
<= "hello");
4794 assert(a
>= "hello");
4798 // Used in Exception Handling LSDA tables to 'wrap' C++ type info
4799 // so it can be distinguished from D TypeInfo
4800 class __cpp_type_info_ptr
4802 void* ptr
; // opaque pointer to C++ RTTI type info
4805 // Compiler hook into the runtime implementation of array (vector) operations.
4806 template _arrayOp(Args
...)
4808 import core
.internal
.array
.operations
;
4809 alias _arrayOp
= arrayOp
!Args
;
4812 public import core
.builtins
: __ctfeWrite
;
4816 Provides an "inline import", i.e. an `import` that is only available for a
4817 limited lookup. For example:
4820 void fun(imported!"std.stdio".File input)
4822 ... use File from std.stdio normally ...
4826 There is no need to import `std.stdio` at top level, so `fun` carries its own
4827 dependencies. The same approach can be used for template constraints:
4830 void fun(T)(imported!"std.stdio".File input, T value)
4831 if (imported!"std.traits".isIntegral!T)
4837 An inline import may be used in conjunction with the `with` statement as well.
4838 Inside the scope controlled by `with`, all symbols in the imported module are
4844 with (imported!"std.datetime")
4845 with (imported!"std.stdio")
4847 Clock.currTime.writeln;
4852 The advantages of inline imports over top-level uses of the `import` declaration
4856 $(LI The `imported` template specifies dependencies at declaration level, not at
4857 module level. This allows reasoning about the dependency cost of declarations in
4858 separation instead of aggregated at module level.)
4859 $(LI Declarations using `imported` are easier to move around because they don't
4860 require top-level context, making for simpler and quicker refactorings.)
4861 $(LI Declarations using `imported` scale better with templates. This is because
4862 templates that are not instantiated do not have their parameters and constraints
4863 instantiated, so additional modules are not imported without necessity. This
4864 makes the cost of unused templates negligible. Dependencies are pulled on a need
4865 basis depending on the declarations used by client code.)
4868 The use of `imported` also has drawbacks:
4871 $(LI If most declarations in a module need the same imports, then factoring them
4872 at top level, outside the declarations, is simpler than repeating them.)
4873 $(LI Traditional dependency-tracking tools such as make and other build systems
4874 assume file-level dependencies and need special tooling (such as rdmd) in order
4875 to work efficiently.)
4876 $(LI Dependencies at the top of a module are easier to inspect quickly than
4877 dependencies spread throughout the module.)
4880 See_Also: The $(HTTP forum.dlang.org/post/tzqzmqhankrkbrfsrmbo@forum.dlang.org,
4881 forum discussion) that led to the creation of the `imported` facility. Credit is
4882 due to Daniel Nielsen and Dominikus Dittes Scherkl.
4885 template imported(string moduleName
)
4887 mixin("import imported = " ~ moduleName
~ ";");