1 /**
2 * $(SCRIPT inhibitQuickIndex = 1;)
3 * $(DIVC quickindex,
4 * $(BOOKTABLE,
5 * $(TR $(TH Category) $(TH Symbols))
6 * $(TR $(TD Arrays) $(TD
7 * $(MYREF assumeSafeAppend)
8 * $(MYREF capacity)
9 * $(MYREF idup)
10 * $(MYREF reserve)
11 * ))
12 * $(TR $(TD Associative arrays) $(TD
13 * $(MYREF byKey)
14 * $(MYREF byKeyValue)
15 * $(MYREF byValue)
16 * $(MYREF clear)
17 * $(MYREF get)
18 * $(MYREF keys)
19 * $(MYREF rehash)
20 * $(MYREF require)
21 * $(MYREF update)
22 * $(MYREF values)
23 * ))
24 * $(TR $(TD General) $(TD
25 * $(MYREF destroy)
26 * $(MYREF dup)
27 * $(MYREF hashOf)
28 * $(MYREF opEquals)
29 * ))
30 * $(TR $(TD Types) $(TD
31 * $(MYREF Error)
32 * $(MYREF Exception)
33 * $(MYREF noreturn)
34 * $(MYREF Object)
35 * $(MYREF Throwable)
36 * ))
37 * $(TR $(TD Type info) $(TD
38 * $(MYREF Interface)
39 * $(MYREF ModuleInfo)
40 * $(MYREF OffsetTypeInfo)
41 * $(MYREF RTInfoImpl)
42 * $(MYREF rtinfoNoPointers)
43 * $(MYREF TypeInfo)
44 * $(MYREF TypeInfo_Class)
45 * ))
46 * ))
47 *
48 * Forms the symbols available to all D programs. Includes Object, which is
49 * the root of the class object hierarchy. This module is implicitly
50 * imported.
51 *
52 * Copyright: Copyright Digital Mars 2000 - 2011.
53 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
54 * Authors: Walter Bright, Sean Kelly
55 * Source: $(DRUNTIMESRC object.d)
56 */
57
58 module object;
59
60 alias size_t = typeof(int.sizeof);
61 alias ptrdiff_t = typeof(cast(void*)0 - cast(void*)0);
62
63 alias sizediff_t = ptrdiff_t; // For backwards compatibility only.
64 alias noreturn = typeof(*null); /// bottom type
65
66 alias hash_t = size_t; // For backwards compatibility only.
67 alias equals_t = bool; // For backwards compatibility only.
68
69 alias string = immutable(char)[];
70 alias wstring = immutable(wchar)[];
71 alias dstring = immutable(dchar)[];
72
version(D_ObjectiveC)73 version (D_ObjectiveC)
74 {
75 deprecated("explicitly import `selector` instead using: `import core.attribute : selector;`")
76 public import core.attribute : selector;
77 }
78 version (Posix) public import core.attribute : gnuAbiTag;
79
80 // Some ABIs use a complex varargs implementation requiring TypeInfo.argTypes().
version(GNU)81 version (GNU)
82 {
83 // No TypeInfo-based core.vararg.va_arg().
84 }
version(X86_64)85 else version (X86_64)
86 {
87 version (DigitalMars) version = WithArgTypes;
88 else version (Windows) { /* no need for Win64 ABI */ }
89 else version = WithArgTypes;
90 }
version(AArch64)91 else version (AArch64)
92 {
93 // Apple uses a trivial varargs implementation
94 version (OSX) {}
95 else version (iOS) {}
96 else version (TVOS) {}
97 else version (WatchOS) {}
98 else version = WithArgTypes;
99 }
100
101 /**
102 * All D class objects inherit from Object.
103 */
104 class Object
105 {
106 /**
107 * Convert Object to a human readable string.
108 */
toString()109 string toString()
110 {
111 return typeid(this).name;
112 }
113
114 @system unittest
115 {
116 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
117 enum fqn_unittest = "object.Object." ~ unittest_sym_name; // object.__unittest_LX_CY
118
119 class C {}
120
121 Object obj = new Object;
122 C c = new C;
123
124 assert(obj.toString() == "object.Object");
125 assert(c.toString() == fqn_unittest ~ ".C");
126 }
127
128 /**
129 * Compute hash function for Object.
130 */
toHash()131 size_t toHash() @trusted nothrow
132 {
133 // BUG: this prevents a compacting GC from working, needs to be fixed
134 size_t addr = cast(size_t) cast(void*) this;
135 // The bottom log2((void*).alignof) bits of the address will always
136 // be 0. Moreover it is likely that each Object is allocated with a
137 // separate call to malloc. The alignment of malloc differs from
138 // platform to platform, but rather than having special cases for
139 // each platform it is safe to use a shift of 4. To minimize
140 // collisions in the low bits it is more important for the shift to
141 // not be too small than for the shift to not be too big.
142 return addr ^ (addr >>> 4);
143 }
144
145 /**
146 * Compare with another Object obj.
147 * Returns:
148 * $(TABLE
149 * $(TR $(TD this < obj) $(TD < 0))
150 * $(TR $(TD this == obj) $(TD 0))
151 * $(TR $(TD this > obj) $(TD > 0))
152 * )
153 */
opCmp(Object o)154 int opCmp(Object o)
155 {
156 // BUG: this prevents a compacting GC from working, needs to be fixed
157 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
158
159 throw new Exception("need opCmp for class " ~ typeid(this).name);
160 //return this !is o;
161 }
162
163 @system unittest
164 {
165 Object obj = new Object;
166
167 bool gotCaught;
168 try
169 {
170 obj.opCmp(new Object);
171 }
catch(Exception e)172 catch (Exception e)
173 {
174 gotCaught = true;
175 assert(e.msg == "need opCmp for class object.Object");
176 }
177 assert(gotCaught);
178 }
179
180 /**
181 * Test whether $(D this) is equal to $(D o).
182 * The default implementation only compares by identity (using the $(D is) operator).
183 * Generally, overrides and overloads for $(D opEquals) should attempt to compare objects by their contents.
184 * A class will most likely want to add an overload that takes your specific type as the argument
185 * and does the content comparison. Then you can override this and forward it to your specific
186 * typed overload with a cast. Remember to check for `null` on the typed overload.
187 *
188 * Examples:
189 * ---
190 * class Child {
191 * int contents;
192 * // the typed overload first. It can use all the attribute you want
193 * bool opEquals(const Child c) const @safe pure nothrow @nogc
194 * {
195 * if (c is null)
196 * return false;
197 * return this.contents == c.contents;
198 * }
199 *
200 * // and now the generic override forwards with a cast
201 * override bool opEquals(Object o)
202 * {
203 * return this.opEquals(cast(Child) o);
204 * }
205 * }
206 * ---
207 */
opEquals(Object o)208 bool opEquals(Object o)
209 {
210 return this is o;
211 }
212
213 interface Monitor
214 {
215 void lock();
216 void unlock();
217 }
218
219 /**
220 * Create instance of class specified by the fully qualified name
221 * classname.
222 * The class must either have no constructors or have
223 * a default constructor.
224 * Returns:
225 * null if failed
226 * Example:
227 * ---
228 * module foo.bar;
229 *
230 * class C
231 * {
232 * this() { x = 10; }
233 * int x;
234 * }
235 *
236 * void main()
237 * {
238 * auto c = cast(C)Object.factory("foo.bar.C");
239 * assert(c !is null && c.x == 10);
240 * }
241 * ---
242 */
factory(string classname)243 static Object factory(string classname)
244 {
245 auto ci = TypeInfo_Class.find(classname);
246 if (ci)
247 {
248 return ci.create();
249 }
250 return null;
251 }
252
253 @system unittest
254 {
255 Object valid_obj = Object.factory("object.Object");
256 Object invalid_obj = Object.factory("object.__this_class_doesnt_exist__");
257
258 assert(valid_obj !is null);
259 assert(invalid_obj is null);
260 }
261 }
262
263 /++
264 Implementation for class opEquals override. Calls the class-defined methods after a null check.
265 Please note this is not nogc right now, even if your implementation is, because of
266 the typeinfo name string compare. This is because of dmd's dll implementation. However,
267 it can infer to @safe if your class' opEquals is.
268 +/
269 bool opEquals(LHS, RHS)(LHS lhs, RHS rhs) if (is(LHS : const Object) && is(RHS : const Object))
270 {
271 static if (__traits(compiles, lhs.opEquals(rhs)) && __traits(compiles, rhs.opEquals(lhs)))
272 {
273 // If aliased to the same object or both null => equal
274 if (lhs is rhs) return true;
275
276 // If either is null => non-equal
277 if (lhs is null || rhs is null) return false;
278
279 if (!lhs.opEquals(rhs)) return false;
280
281 // If same exact type => one call to method opEquals
282 if (typeid(lhs) is typeid(rhs) ||
283 !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
284 /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
285 (issue 7147). But CTFE also guarantees that equal TypeInfos are
286 always identical. So, no opEquals needed during CTFE. */
287 {
288 return true;
289 }
290
291 // General case => symmetric calls to method opEquals
292 return rhs.opEquals(lhs);
293 }
294 else
295 {
296 // this is a compatibility hack for the old const cast behavior
297 // if none of the new overloads compile, we'll go back plain Object,
298 // including casting away const. It does this through the pointer
299 // to bypass any opCast that may be present on the original class.
300 return .opEquals!(Object, Object)(*cast(Object*) &lhs, *cast(Object*) &rhs);
301
302 }
303 }
304
305 /// If aliased to the same object or both null => equal
306 @system unittest // this one is not @safe because it goes through the Object base method
307 {
this(int flag)308 class F { int flag; this(int flag) { this.flag = flag; } }
309
310 F f;
311 assert(f == f); // both null
312 f = new F(1);
313 assert(f == f); // both aliased to the same object
314 }
315
316 /// If either is null => non-equal
317 @system unittest
318 {
this(int flag)319 class F { int flag; this(int flag) { this.flag = flag; } }
320 F f;
321 assert(!(new F(0) == f));
322 assert(!(f == new F(0)));
323 }
324
325 /// If same exact type => one call to method opEquals
326 /// This test passes `@safe` because it defines a new opEquals with `@safe`
327 @safe unittest
328 {
329 class F
330 {
331 int flag;
332
this(int flag)333 this(int flag)
334 {
335 this.flag = flag;
336 }
337
opEquals(const F o)338 bool opEquals(const F o) const @safe nothrow pure
339 {
340 return flag == o.flag;
341 }
342 }
343
344 F f;
345 assert(new F(0) == new F(0));
346 assert(!(new F(0) == new F(1)));
347 }
348
349 /// General case => symmetric calls to method opEquals
350 @safe unittest
351 {
352 int fEquals, gEquals;
353
354 class Base
355 {
356 int flag;
this(int flag)357 this(int flag)
358 {
359 this.flag = flag;
360 }
361 }
362
363 class F : Base
364 {
this(int flag)365 this(int flag) { super(flag); }
366
opEquals(const Base o)367 bool opEquals(const Base o) @safe
368 {
369 fEquals++;
370 return flag == o.flag;
371 }
372 }
373
374 class G : Base
375 {
this(int flag)376 this(int flag) { super(flag); }
377
opEquals(const Base o)378 bool opEquals(const Base o) @safe
379 {
380 gEquals++;
381 return flag == o.flag;
382 }
383 }
384
385 assert(new F(1) == new G(1));
386 assert(fEquals == 1);
387 assert(gEquals == 1);
388 }
389
390 /++
391 This test shows an example for a comprehensive inheritance equality chain too.
392 +/
393 unittest
394 {
395 static class Base
396 {
397 int member;
398
this(int member)399 this(int member) pure @safe nothrow @nogc
400 {
401 this.member = member;
402 }
403
opEquals(Object rhs)404 override bool opEquals(Object rhs) const
405 {
406 return this.opEquals(cast(Base) rhs);
407 }
408
opEquals(const Base rhs)409 bool opEquals(const Base rhs) const @nogc pure nothrow @safe
410 {
411 if (rhs is null)
412 return false;
413 return this.member == rhs.member;
414 }
415 }
416
417 // works through the direct class with attributes enabled, except for pure and nogc in the current TypeInfo implementation
testThroughBase()418 bool testThroughBase() nothrow @safe
419 {
420 Base b1 = new Base(0);
421 Base b2 = new Base(0);
422 assert(b1 == b2);
423 Base b3 = new Base(1);
424 assert(b1 != b3);
425 return true;
426 }
427
428 static assert(testThroughBase());
429
430 // also works through the base class interface thanks to the override, but no more attributes
testThroughObject()431 bool testThroughObject()
432 {
433 Object o1 = new Base(0);
434 Object o2 = new Base(0);
435 assert(o1 == o2);
436 Object o3 = new Base(1);
437 assert(o1 != o3);
438 return true;
439 }
440
441 static assert(testThroughObject());
442
443 // Each time you make a child, you want to override all old opEquals
444 // and add a new overload for the new child.
445 static class Child : Base
446 {
447 int member2;
448
this(int member,int member2)449 this(int member, int member2) pure @safe nothrow @nogc
450 {
451 super(member);
452 this.member2 = member2;
453 }
454
455 // override the whole chain so it works consistently though any base
opEquals(Object rhs)456 override bool opEquals(Object rhs) const
457 {
458 return this.opEquals(cast(Child) rhs);
459 }
opEquals(const Base rhs)460 override bool opEquals(const Base rhs) const
461 {
462 return this.opEquals(cast(const Child) rhs);
463 }
464 // and then add the new overload, if necessary, to handle new members
opEquals(const Child rhs)465 bool opEquals(const Child rhs) const @nogc pure nothrow @safe
466 {
467 if (rhs is null)
468 return false;
469 // can call back to the devirtualized base test with implicit conversion
470 // then compare the new member too. or we could have just compared the base
471 // member directly here as well.
472 return Base.opEquals(rhs) && this.member2 == rhs.member2;
473 }
474
475 // a mixin template, of course, could automate this.
476 }
477
testThroughChild()478 bool testThroughChild()
479 {
480 Child a = new Child(0, 0);
481 Child b = new Child(0, 1);
482 assert(a != b);
483
484 Base ba = a;
485 Base bb = b;
486 assert(ba != bb);
487
488 Object oa = a;
489 Object ob = b;
490 assert(oa != ob);
491
492 return true;
493 }
494
495 static assert(testThroughChild());
496 }
497
498 // To cover const Object opEquals
499 @system unittest
500 {
501 const Object obj1 = new Object;
502 const Object obj2 = new Object;
503
504 assert(obj1 == obj1);
505 assert(obj1 != obj2);
506 }
507
508 private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
509
setSameMutex(shared Object ownee,shared Object owner)510 void setSameMutex(shared Object ownee, shared Object owner)
511 {
512 _d_setSameMutex(ownee, owner);
513 }
514
515 @system unittest
516 {
517 shared Object obj1 = new Object;
518 synchronized class C
519 {
bar()520 void bar() {}
521 }
522 shared C obj2 = new shared(C);
523 obj2.bar();
524
525 assert(obj1.__monitor != obj2.__monitor);
526 assert(obj1.__monitor is null);
527
528 setSameMutex(obj1, obj2);
529 assert(obj1.__monitor == obj2.__monitor);
530 assert(obj1.__monitor !is null);
531 }
532
533 /**
534 * Information about an interface.
535 * When an object is accessed via an interface, an Interface* appears as the
536 * first entry in its vtbl.
537 */
538 struct Interface
539 {
540 /// Class info returned by `typeid` for this interface (not for containing class)
541 TypeInfo_Class classinfo;
542 void*[] vtbl;
543 size_t offset; /// offset to Interface 'this' from Object 'this'
544 }
545
546 /**
547 * Array of pairs giving the offset and type information for each
548 * member in an aggregate.
549 */
550 struct OffsetTypeInfo
551 {
552 size_t offset; /// Offset of member from start of object
553 TypeInfo ti; /// TypeInfo for this member
554 }
555
556 /**
557 * Runtime type information about a type.
558 * Can be retrieved for any type using a
559 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
560 */
561 class TypeInfo
562 {
toString()563 override string toString() const @safe nothrow
564 {
565 return typeid(this).name;
566 }
567
toHash()568 override size_t toHash() @trusted const nothrow
569 {
570 return hashOf(this.toString());
571 }
572
opCmp(Object rhs)573 override int opCmp(Object rhs)
574 {
575 if (this is rhs)
576 return 0;
577 auto ti = cast(TypeInfo) rhs;
578 if (ti is null)
579 return 1;
580 return __cmp(this.toString(), ti.toString());
581 }
582
583 @system unittest
584 {
585 assert(typeid(void) <= typeid(void));
586 assert(typeid(void).opCmp(null));
587 assert(!typeid(void).opCmp(typeid(void)));
588 }
589
opEquals(Object o)590 override bool opEquals(Object o)
591 {
592 return opEquals(cast(TypeInfo) o);
593 }
594
opEquals(const TypeInfo ti)595 bool opEquals(const TypeInfo ti) @safe nothrow const
596 {
597 /* TypeInfo instances are singletons, but duplicates can exist
598 * across DLL's. Therefore, comparing for a name match is
599 * sufficient.
600 */
601 if (this is ti)
602 return true;
603 return ti && this.toString() == ti.toString();
604 }
605
606 @system unittest
607 {
608 auto anotherObj = new Object();
609
610 assert(typeid(void).opEquals(typeid(void)));
611 assert(typeid(void) != anotherObj); // calling .opEquals here directly is a type mismatch
612 }
613
614 /**
615 * Computes a hash of the instance of a type.
616 * Params:
617 * p = pointer to start of instance of the type
618 * Returns:
619 * the hash
620 * Bugs:
621 * fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
622 */
getHash(scope const void * p)623 size_t getHash(scope const void* p) @trusted nothrow const
624 {
625 return hashOf(p);
626 }
627
628 /// Compares two instances for equality.
equals(in void * p1,in void * p2)629 bool equals(in void* p1, in void* p2) const { return p1 == p2; }
630
631 /// Compares two instances for <, ==, or >.
compare(in void * p1,in void * p2)632 int compare(in void* p1, in void* p2) const { return _xopCmp(p1, p2); }
633
634 /// Returns size of the type.
tsize()635 @property size_t tsize() nothrow pure const @safe @nogc { return 0; }
636
637 /// Swaps two instances of the type.
swap(void * p1,void * p2)638 void swap(void* p1, void* p2) const
639 {
640 size_t remaining = tsize;
641 // If the type might contain pointers perform the swap in pointer-sized
642 // chunks in case a garbage collection pass interrupts this function.
643 if ((cast(size_t) p1 | cast(size_t) p2) % (void*).alignof == 0)
644 {
645 while (remaining >= (void*).sizeof)
646 {
647 void* tmp = *cast(void**) p1;
648 *cast(void**) p1 = *cast(void**) p2;
649 *cast(void**) p2 = tmp;
650 p1 += (void*).sizeof;
651 p2 += (void*).sizeof;
652 remaining -= (void*).sizeof;
653 }
654 }
655 for (size_t i = 0; i < remaining; i++)
656 {
657 byte t = (cast(byte *)p1)[i];
658 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
659 (cast(byte*)p2)[i] = t;
660 }
661 }
662
663 @system unittest
664 {
665 class _TypeInfo_Dummy : TypeInfo
666 {
initializer()667 override const(void)[] initializer() const { return []; }
tsize()668 @property override size_t tsize() nothrow pure const @safe @nogc { return tsize_val; }
669
670 size_t tsize_val;
671 }
672 auto dummy = new _TypeInfo_Dummy();
673 cast(void)dummy.initializer(); // For coverage completeness
674
675 int a = 2, b = -2;
676 dummy.swap(&a, &b);
677 // does nothing because tsize is 0
678 assert(a == 2);
679 assert(b == -2);
680
681 dummy.tsize_val = int.sizeof;
682 dummy.swap(&a, &b);
683 assert(a == -2);
684 assert(b == 2);
685
686 void* ptr_a = null, ptr_b = cast(void*)1;
687 dummy.tsize_val = (void*).sizeof;
688 dummy.swap(&ptr_a, &ptr_b);
689 assert(ptr_a is cast(void*)1);
690 assert(ptr_b is null);
691 }
692
693 /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
694 null if none. */
inout(TypeInfo)695 @property inout(TypeInfo) next() nothrow pure inout @nogc { return null; }
696
697 /**
698 * Return default initializer. If the type should be initialized to all
699 * zeros, an array with a null ptr and a length equal to the type size will
700 * be returned. For static arrays, this returns the default initializer for
701 * a single element of the array, use `tsize` to get the correct size.
702 */
703 abstract const(void)[] initializer() nothrow pure const @safe @nogc;
704
705 /** Get flags for type: 1 means GC should scan for pointers,
706 2 means arg of this type is passed in SIMD register(s) if available */
flags()707 @property uint flags() nothrow pure const @safe @nogc { return 0; }
708
709 /// Get type information on the contents of the type; null if not available
offTi()710 const(OffsetTypeInfo)[] offTi() const { return null; }
711 /// Run the destructor on the object and all its sub-objects
destroy(void * p)712 void destroy(void* p) const {}
713 /// Run the postblit on the object and all its sub-objects
postblit(void * p)714 void postblit(void* p) const {}
715
716
717 /// Return alignment of type
talign()718 @property size_t talign() nothrow pure const @safe @nogc { return tsize; }
719
720 /** Return internal info on arguments fitting into 8byte.
721 * See X86-64 ABI 3.2.3
722 */
version(WithArgTypes)723 version (WithArgTypes) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
724 {
725 arg1 = this;
726 return 0;
727 }
728
729 /** Return info used by the garbage collector to do precise collection.
730 */
immutable(void)731 @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return rtinfoHasPointers; } // better safe than sorry
732 }
733
734 @system unittest
735 {
736 class _TypeInfo_Dummy : TypeInfo
737 {
initializer()738 override const(void)[] initializer() const { return []; }
739 }
740 auto dummy = new _TypeInfo_Dummy();
741 cast(void)dummy.initializer(); // For coverage completeness
742
743 assert(dummy.rtInfo() is rtinfoHasPointers);
744 assert(typeid(void).rtInfo() is rtinfoNoPointers);
745
746 assert(dummy.tsize() == 0);
747
748 bool gotCaught;
749 try
750 {
751 dummy.compare(null, null);
catch(Error e)752 } catch (Error e)
753 {
754 gotCaught = true;
755 assert(e.msg == "TypeInfo.compare is not implemented");
756 }
757 assert(gotCaught);
758
759 assert(dummy.equals(null, null));
760 assert(!dummy.equals(cast(void*)1, null));
761 }
762
763 @system unittest
764 {
765 assert(typeid(void).next() is null);
766 assert(typeid(void).offTi() is null);
767 assert(typeid(void).tsize() == 1);
768
version(WithArgTypes)769 version (WithArgTypes)
770 {
771 TypeInfo ti1;
772 TypeInfo ti2;
773 assert(typeid(void).argTypes(ti1, ti2) == 0);
774 assert(typeid(void) is ti1);
775
776 assert(ti1 !is null);
777 assert(ti2 is null);
778 }
779 }
780
781 @system unittest
782 {
783 class _ZypeInfo_Dummy : TypeInfo
784 {
initializer()785 override const(void)[] initializer() const { return []; }
786 }
787 auto dummy2 = new _ZypeInfo_Dummy();
788 cast(void)dummy2.initializer(); // For coverage completeness
789
790 assert(typeid(void) > dummy2);
791 assert(dummy2 < typeid(void));
792 }
793
794 @safe unittest
795 {
796 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
797 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
798
799 class _TypeInfo_Dummy : TypeInfo
800 {
initializer()801 override const(void)[] initializer() const { return []; }
802 }
803
804 auto dummy = new _TypeInfo_Dummy();
805 cast(void)dummy.initializer(); // For coverage completeness
806
807 assert(dummy.toString() == fqn_unittest ~ "._TypeInfo_Dummy");
808 assert(dummy.toHash() == hashOf(dummy.toString()));
809 assert(dummy.getHash(null) == 0);
810 }
811
812 class TypeInfo_Enum : TypeInfo
813 {
toString()814 override string toString() const pure { return name; }
815
opEquals(Object o)816 override bool opEquals(Object o)
817 {
818 if (this is o)
819 return true;
820 auto c = cast(const TypeInfo_Enum)o;
821 return c && this.name == c.name &&
822 this.base == c.base;
823 }
824
825 @system unittest
826 {
827 enum E { A, B, C }
828 enum EE { A, B, C }
829
830 assert(typeid(E).opEquals(typeid(E)));
831 assert(!typeid(E).opEquals(typeid(EE)));
832 }
833
getHash(scope const void * p)834 override size_t getHash(scope const void* p) const { return base.getHash(p); }
835
836 @system unittest
837 {
838 enum E { A, B, C }
839 E e1 = E.A;
840 E e2 = E.B;
841
842 assert(typeid(E).getHash(&e1) == hashOf(E.A));
843 assert(typeid(E).getHash(&e2) == hashOf(E.B));
844
845 enum ES : string { A = "foo", B = "bar" }
846 ES es1 = ES.A;
847 ES es2 = ES.B;
848
849 assert(typeid(ES).getHash(&es1) == hashOf("foo"));
850 assert(typeid(ES).getHash(&es2) == hashOf("bar"));
851 }
852
equals(in void * p1,in void * p2)853 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
854
855 @system unittest
856 {
857 enum E { A, B, C }
858
859 E e1 = E.A;
860 E e2 = E.B;
861
862 assert(typeid(E).equals(&e1, &e1));
863 assert(!typeid(E).equals(&e1, &e2));
864 }
865
compare(in void * p1,in void * p2)866 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
867
868 @system unittest
869 {
870 enum E { A, B, C }
871
872 E e1 = E.A;
873 E e2 = E.B;
874
875 assert(typeid(E).compare(&e1, &e1) == 0);
876 assert(typeid(E).compare(&e1, &e2) < 0);
877 assert(typeid(E).compare(&e2, &e1) > 0);
878 }
879
tsize()880 override @property size_t tsize() nothrow pure const { return base.tsize; }
881
882 @safe unittest
883 {
884 enum E { A, B, C }
885 enum ES : string { A = "a", B = "b", C = "c"}
886
887 assert(typeid(E).tsize == E.sizeof);
888 assert(typeid(ES).tsize == ES.sizeof);
889 assert(typeid(E).tsize != ES.sizeof);
890 }
891
swap(void * p1,void * p2)892 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
893
894 @system unittest
895 {
896 enum E { A, B, C }
897
898 E e1 = E.A;
899 E e2 = E.B;
900
901 typeid(E).swap(&e1, &e2);
902 assert(e1 == E.B);
903 assert(e2 == E.A);
904 }
905
inout(TypeInfo)906 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
907
908 @system unittest
909 {
910 enum E { A, B, C }
911
912 assert(typeid(E).next is null);
913 }
914
flags()915 override @property uint flags() nothrow pure const { return base.flags; }
916
917 @safe unittest
918 {
919 enum E { A, B, C }
920
921 assert(typeid(E).flags == 0);
922 }
923
offTi()924 override const(OffsetTypeInfo)[] offTi() const { return base.offTi; }
925
926 @system unittest
927 {
928 enum E { A, B, C }
929
930 assert(typeid(E).offTi is null);
931 }
932
destroy(void * p)933 override void destroy(void* p) const { return base.destroy(p); }
postblit(void * p)934 override void postblit(void* p) const { return base.postblit(p); }
935
initializer()936 override const(void)[] initializer() const
937 {
938 return m_init.length ? m_init : base.initializer();
939 }
940
talign()941 override @property size_t talign() nothrow pure const { return base.talign; }
942
version(WithArgTypes)943 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
944 {
945 return base.argTypes(arg1, arg2);
946 }
947
immutable(void)948 override @property immutable(void)* rtInfo() const { return base.rtInfo; }
949
950 TypeInfo base;
951 string name;
952 void[] m_init;
953 }
954
955 @safe unittest
956 {
957 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
958 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
959
960 enum E { A, B, C }
961 enum EE { A, B, C }
962
963 assert(typeid(E).toString() == fqn_unittest ~ ".E");
964 }
965
966
967 @safe unittest // issue 12233
968 {
969 static assert(is(typeof(TypeInfo.init) == TypeInfo));
970 assert(TypeInfo.init is null);
971 }
972
973
974 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
975 class TypeInfo_Pointer : TypeInfo
976 {
toString()977 override string toString() const { return m_next.toString() ~ "*"; }
978
opEquals(Object o)979 override bool opEquals(Object o)
980 {
981 if (this is o)
982 return true;
983 auto c = cast(const TypeInfo_Pointer)o;
984 return c && this.m_next == c.m_next;
985 }
986
getHash(scope const void * p)987 override size_t getHash(scope const void* p) @trusted const
988 {
989 size_t addr = cast(size_t) *cast(const void**)p;
990 return addr ^ (addr >> 4);
991 }
992
equals(in void * p1,in void * p2)993 override bool equals(in void* p1, in void* p2) const
994 {
995 return *cast(void**)p1 == *cast(void**)p2;
996 }
997
compare(in void * p1,in void * p2)998 override int compare(in void* p1, in void* p2) const
999 {
1000 const v1 = *cast(void**) p1, v2 = *cast(void**) p2;
1001 return (v1 > v2) - (v1 < v2);
1002 }
1003
tsize()1004 override @property size_t tsize() nothrow pure const
1005 {
1006 return (void*).sizeof;
1007 }
1008
initializer()1009 override const(void)[] initializer() const @trusted
1010 {
1011 return (cast(void *)null)[0 .. (void*).sizeof];
1012 }
1013
swap(void * p1,void * p2)1014 override void swap(void* p1, void* p2) const
1015 {
1016 void* tmp = *cast(void**)p1;
1017 *cast(void**)p1 = *cast(void**)p2;
1018 *cast(void**)p2 = tmp;
1019 }
1020
inout(TypeInfo)1021 override @property inout(TypeInfo) next() nothrow pure inout { return m_next; }
flags()1022 override @property uint flags() nothrow pure const { return 1; }
1023
1024 TypeInfo m_next;
1025 }
1026
1027 class TypeInfo_Array : TypeInfo
1028 {
toString()1029 override string toString() const { return value.toString() ~ "[]"; }
1030
opEquals(Object o)1031 override bool opEquals(Object o)
1032 {
1033 if (this is o)
1034 return true;
1035 auto c = cast(const TypeInfo_Array)o;
1036 return c && this.value == c.value;
1037 }
1038
getHash(scope const void * p)1039 override size_t getHash(scope const void* p) @trusted const
1040 {
1041 void[] a = *cast(void[]*)p;
1042 return getArrayHash(value, a.ptr, a.length);
1043 }
1044
equals(in void * p1,in void * p2)1045 override bool equals(in void* p1, in void* p2) const
1046 {
1047 void[] a1 = *cast(void[]*)p1;
1048 void[] a2 = *cast(void[]*)p2;
1049 if (a1.length != a2.length)
1050 return false;
1051 size_t sz = value.tsize;
1052 for (size_t i = 0; i < a1.length; i++)
1053 {
1054 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
1055 return false;
1056 }
1057 return true;
1058 }
1059
compare(in void * p1,in void * p2)1060 override int compare(in void* p1, in void* p2) const
1061 {
1062 void[] a1 = *cast(void[]*)p1;
1063 void[] a2 = *cast(void[]*)p2;
1064 size_t sz = value.tsize;
1065 size_t len = a1.length;
1066
1067 if (a2.length < len)
1068 len = a2.length;
1069 for (size_t u = 0; u < len; u++)
1070 {
1071 immutable int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
1072 if (result)
1073 return result;
1074 }
1075 return (a1.length > a2.length) - (a1.length < a2.length);
1076 }
1077
tsize()1078 override @property size_t tsize() nothrow pure const
1079 {
1080 return (void[]).sizeof;
1081 }
1082
initializer()1083 override const(void)[] initializer() const @trusted
1084 {
1085 return (cast(void *)null)[0 .. (void[]).sizeof];
1086 }
1087
swap(void * p1,void * p2)1088 override void swap(void* p1, void* p2) const
1089 {
1090 void[] tmp = *cast(void[]*)p1;
1091 *cast(void[]*)p1 = *cast(void[]*)p2;
1092 *cast(void[]*)p2 = tmp;
1093 }
1094
1095 TypeInfo value;
1096
inout(TypeInfo)1097 override @property inout(TypeInfo) next() nothrow pure inout
1098 {
1099 return value;
1100 }
1101
flags()1102 override @property uint flags() nothrow pure const { return 1; }
1103
talign()1104 override @property size_t talign() nothrow pure const
1105 {
1106 return (void[]).alignof;
1107 }
1108
version(WithArgTypes)1109 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1110 {
1111 arg1 = typeid(size_t);
1112 arg2 = typeid(void*);
1113 return 0;
1114 }
1115
immutable(void)1116 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(void[]); }
1117 }
1118
1119 class TypeInfo_StaticArray : TypeInfo
1120 {
toString()1121 override string toString() const
1122 {
1123 import core.internal.string : unsignedToTempString;
1124
1125 char[20] tmpBuff = void;
1126 const lenString = unsignedToTempString(len, tmpBuff);
1127
1128 return (() @trusted => cast(string) (value.toString() ~ "[" ~ lenString ~ "]"))();
1129 }
1130
opEquals(Object o)1131 override bool opEquals(Object o)
1132 {
1133 if (this is o)
1134 return true;
1135 auto c = cast(const TypeInfo_StaticArray)o;
1136 return c && this.len == c.len &&
1137 this.value == c.value;
1138 }
1139
getHash(scope const void * p)1140 override size_t getHash(scope const void* p) @trusted const
1141 {
1142 return getArrayHash(value, p, len);
1143 }
1144
equals(in void * p1,in void * p2)1145 override bool equals(in void* p1, in void* p2) const
1146 {
1147 size_t sz = value.tsize;
1148
1149 for (size_t u = 0; u < len; u++)
1150 {
1151 if (!value.equals(p1 + u * sz, p2 + u * sz))
1152 return false;
1153 }
1154 return true;
1155 }
1156
compare(in void * p1,in void * p2)1157 override int compare(in void* p1, in void* p2) const
1158 {
1159 size_t sz = value.tsize;
1160
1161 for (size_t u = 0; u < len; u++)
1162 {
1163 immutable int result = value.compare(p1 + u * sz, p2 + u * sz);
1164 if (result)
1165 return result;
1166 }
1167 return 0;
1168 }
1169
tsize()1170 override @property size_t tsize() nothrow pure const
1171 {
1172 return len * value.tsize;
1173 }
1174
swap(void * p1,void * p2)1175 override void swap(void* p1, void* p2) const
1176 {
1177 import core.stdc.string : memcpy;
1178
1179 size_t remaining = value.tsize * len;
1180 void[size_t.sizeof * 4] buffer = void;
1181 while (remaining > buffer.length)
1182 {
1183 memcpy(buffer.ptr, p1, buffer.length);
1184 memcpy(p1, p2, buffer.length);
1185 memcpy(p2, buffer.ptr, buffer.length);
1186 p1 += buffer.length;
1187 p2 += buffer.length;
1188 remaining -= buffer.length;
1189 }
1190 memcpy(buffer.ptr, p1, remaining);
1191 memcpy(p1, p2, remaining);
1192 memcpy(p2, buffer.ptr, remaining);
1193 }
1194
initializer()1195 override const(void)[] initializer() nothrow pure const
1196 {
1197 return value.initializer();
1198 }
1199
inout(TypeInfo)1200 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
flags()1201 override @property uint flags() nothrow pure const { return value.flags; }
1202
destroy(void * p)1203 override void destroy(void* p) const
1204 {
1205 immutable sz = value.tsize;
1206 p += sz * len;
1207 foreach (i; 0 .. len)
1208 {
1209 p -= sz;
1210 value.destroy(p);
1211 }
1212 }
1213
postblit(void * p)1214 override void postblit(void* p) const
1215 {
1216 immutable sz = value.tsize;
1217 foreach (i; 0 .. len)
1218 {
1219 value.postblit(p);
1220 p += sz;
1221 }
1222 }
1223
1224 TypeInfo value;
1225 size_t len;
1226
talign()1227 override @property size_t talign() nothrow pure const
1228 {
1229 return value.talign;
1230 }
1231
version(WithArgTypes)1232 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1233 {
1234 arg1 = typeid(void*);
1235 return 0;
1236 }
1237
1238 // just return the rtInfo of the element, we have no generic type T to run RTInfo!T on
immutable(void)1239 override @property immutable(void)* rtInfo() nothrow pure const @safe { return value.rtInfo(); }
1240 }
1241
1242 // https://issues.dlang.org/show_bug.cgi?id=21315
1243 @system unittest
1244 {
1245 int[16] a, b;
1246 foreach (int i; 0 .. 16)
1247 {
1248 a[i] = i;
1249 b[i] = ~i;
1250 }
1251 typeid(int[16]).swap(&a, &b);
1252 foreach (int i; 0 .. 16)
1253 {
1254 assert(a[i] == ~i);
1255 assert(b[i] == i);
1256 }
1257 }
1258
1259 class TypeInfo_AssociativeArray : TypeInfo
1260 {
toString()1261 override string toString() const
1262 {
1263 return value.toString() ~ "[" ~ key.toString() ~ "]";
1264 }
1265
opEquals(Object o)1266 override bool opEquals(Object o)
1267 {
1268 if (this is o)
1269 return true;
1270 auto c = cast(const TypeInfo_AssociativeArray)o;
1271 return c && this.key == c.key &&
1272 this.value == c.value;
1273 }
1274
equals(in void * p1,in void * p2)1275 override bool equals(in void* p1, in void* p2) @trusted const
1276 {
1277 return !!_aaEqual(this, *cast(const AA*) p1, *cast(const AA*) p2);
1278 }
1279
getHash(scope const void * p)1280 override hash_t getHash(scope const void* p) nothrow @trusted const
1281 {
1282 return _aaGetHash(cast(AA*)p, this);
1283 }
1284
1285 // BUG: need to add the rest of the functions
1286
tsize()1287 override @property size_t tsize() nothrow pure const
1288 {
1289 return (char[int]).sizeof;
1290 }
1291
initializer()1292 override const(void)[] initializer() const @trusted
1293 {
1294 return (cast(void *)null)[0 .. (char[int]).sizeof];
1295 }
1296
inout(TypeInfo)1297 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
flags()1298 override @property uint flags() nothrow pure const { return 1; }
1299
1300 TypeInfo value;
1301 TypeInfo key;
1302
talign()1303 override @property size_t talign() nothrow pure const
1304 {
1305 return (char[int]).alignof;
1306 }
1307
version(WithArgTypes)1308 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1309 {
1310 arg1 = typeid(void*);
1311 return 0;
1312 }
1313 }
1314
1315 class TypeInfo_Vector : TypeInfo
1316 {
toString()1317 override string toString() const { return "__vector(" ~ base.toString() ~ ")"; }
1318
opEquals(Object o)1319 override bool opEquals(Object o)
1320 {
1321 if (this is o)
1322 return true;
1323 auto c = cast(const TypeInfo_Vector)o;
1324 return c && this.base == c.base;
1325 }
1326
getHash(scope const void * p)1327 override size_t getHash(scope const void* p) const { return base.getHash(p); }
equals(in void * p1,in void * p2)1328 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
compare(in void * p1,in void * p2)1329 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
tsize()1330 override @property size_t tsize() nothrow pure const { return base.tsize; }
swap(void * p1,void * p2)1331 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
1332
inout(TypeInfo)1333 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
flags()1334 override @property uint flags() nothrow pure const { return 2; /* passed in SIMD register */ }
1335
initializer()1336 override const(void)[] initializer() nothrow pure const
1337 {
1338 return base.initializer();
1339 }
1340
talign()1341 override @property size_t talign() nothrow pure const { return 16; }
1342
version(WithArgTypes)1343 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1344 {
1345 return base.argTypes(arg1, arg2);
1346 }
1347
1348 TypeInfo base;
1349 }
1350
1351 class TypeInfo_Function : TypeInfo
1352 {
toString()1353 override string toString() const pure @trusted
1354 {
1355 import core.demangle : demangleType;
1356
1357 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
1358 SafeDemangleFunctionType demangle = cast(SafeDemangleFunctionType) &demangleType;
1359
1360 return cast(string) demangle(deco);
1361 }
1362
opEquals(Object o)1363 override bool opEquals(Object o)
1364 {
1365 if (this is o)
1366 return true;
1367 auto c = cast(const TypeInfo_Function)o;
1368 return c && this.deco == c.deco;
1369 }
1370
1371 // BUG: need to add the rest of the functions
1372
tsize()1373 override @property size_t tsize() nothrow pure const
1374 {
1375 return 0; // no size for functions
1376 }
1377
initializer()1378 override const(void)[] initializer() const @safe
1379 {
1380 return null;
1381 }
1382
immutable(void)1383 override @property immutable(void)* rtInfo() nothrow pure const @safe { return rtinfoNoPointers; }
1384
1385 TypeInfo next;
1386
1387 /**
1388 * Mangled function type string
1389 */
1390 string deco;
1391 }
1392
1393 @safe unittest
1394 {
1395 abstract class C
1396 {
1397 void func();
1398 void func(int a);
1399 int func(int a, int b);
1400 }
1401
1402 alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func"));
1403 assert(typeid(functionTypes[0]).toString() == "void function()");
1404 assert(typeid(functionTypes[1]).toString() == "void function(int)");
1405 assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
1406 }
1407
1408 @system unittest
1409 {
1410 abstract class C
1411 {
1412 void func();
1413 void func(int a);
1414 }
1415
1416 alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func"));
1417
1418 Object obj = typeid(functionTypes[0]);
1419 assert(obj.opEquals(typeid(functionTypes[0])));
1420 assert(typeid(functionTypes[0]) == typeid(functionTypes[0]));
1421 assert(typeid(functionTypes[0]) != typeid(functionTypes[1]));
1422
1423 assert(typeid(functionTypes[0]).tsize() == 0);
1424 assert(typeid(functionTypes[0]).initializer() is null);
1425 assert(typeid(functionTypes[0]).rtInfo() is null);
1426 }
1427
1428 class TypeInfo_Delegate : TypeInfo
1429 {
toString()1430 override string toString() const pure @trusted
1431 {
1432 import core.demangle : demangleType;
1433
1434 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
1435 SafeDemangleFunctionType demangle = cast(SafeDemangleFunctionType) &demangleType;
1436
1437 return cast(string) demangle(deco);
1438 }
1439
1440 @safe unittest
1441 {
sqr(double x)1442 double sqr(double x) { return x * x; }
1443 sqr(double.init); // for coverage completeness
1444
1445 auto delegate_str = "double delegate(double) pure nothrow @nogc @safe";
1446
1447 assert(typeid(typeof(&sqr)).toString() == delegate_str);
1448 assert(delegate_str.hashOf() == typeid(typeof(&sqr)).hashOf());
1449 assert(typeid(typeof(&sqr)).toHash() == typeid(typeof(&sqr)).hashOf());
1450
1451 int g;
1452
1453 alias delegate_type = typeof((int a, int b) => a + b + g);
1454 delegate_str = "int delegate(int, int) pure nothrow @nogc @safe";
1455
1456 assert(typeid(delegate_type).toString() == delegate_str);
1457 assert(delegate_str.hashOf() == typeid(delegate_type).hashOf());
1458 assert(typeid(delegate_type).toHash() == typeid(delegate_type).hashOf());
1459 }
1460
opEquals(Object o)1461 override bool opEquals(Object o)
1462 {
1463 if (this is o)
1464 return true;
1465 auto c = cast(const TypeInfo_Delegate)o;
1466 return c && this.deco == c.deco;
1467 }
1468
1469 @system unittest
1470 {
sqr(double x)1471 double sqr(double x) { return x * x; }
dbl(int x)1472 int dbl(int x) { return x + x; }
1473 sqr(double.init); // for coverage completeness
1474 dbl(int.init); // for coverage completeness
1475
1476 Object obj = typeid(typeof(&sqr));
1477 assert(obj.opEquals(typeid(typeof(&sqr))));
1478 assert(typeid(typeof(&sqr)) == typeid(typeof(&sqr)));
1479 assert(typeid(typeof(&dbl)) != typeid(typeof(&sqr)));
1480 }
1481
getHash(scope const void * p)1482 override size_t getHash(scope const void* p) @trusted const
1483 {
1484 return hashOf(*cast(void delegate()*)p);
1485 }
1486
equals(in void * p1,in void * p2)1487 override bool equals(in void* p1, in void* p2) const
1488 {
1489 auto dg1 = *cast(void delegate()*)p1;
1490 auto dg2 = *cast(void delegate()*)p2;
1491 return dg1 == dg2;
1492 }
1493
compare(in void * p1,in void * p2)1494 override int compare(in void* p1, in void* p2) const
1495 {
1496 auto dg1 = *cast(void delegate()*)p1;
1497 auto dg2 = *cast(void delegate()*)p2;
1498
1499 if (dg1 < dg2)
1500 return -1;
1501 else if (dg1 > dg2)
1502 return 1;
1503 else
1504 return 0;
1505 }
1506
tsize()1507 override @property size_t tsize() nothrow pure const
1508 {
1509 alias dg = int delegate();
1510 return dg.sizeof;
1511 }
1512
initializer()1513 override const(void)[] initializer() const @trusted
1514 {
1515 return (cast(void *)null)[0 .. (int delegate()).sizeof];
1516 }
1517
flags()1518 override @property uint flags() nothrow pure const { return 1; }
1519
1520 TypeInfo next;
1521 string deco;
1522
talign()1523 override @property size_t talign() nothrow pure const
1524 {
1525 alias dg = int delegate();
1526 return dg.alignof;
1527 }
1528
version(WithArgTypes)1529 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1530 {
1531 arg1 = typeid(void*);
1532 arg2 = typeid(void*);
1533 return 0;
1534 }
1535
immutable(void)1536 override @property immutable(void)* rtInfo() nothrow pure const @safe { return RTInfo!(int delegate()); }
1537 }
1538
1539 private extern (C) Object _d_newclass(const TypeInfo_Class ci);
1540 private extern (C) int _d_isbaseof(scope TypeInfo_Class child,
1541 scope const TypeInfo_Class parent) @nogc nothrow pure @safe; // rt.cast_
1542
1543 /**
1544 * Runtime type information about a class.
1545 * Can be retrieved from an object instance by using the
1546 * $(DDSUBLINK spec/expression,typeid_expressions,typeid expression).
1547 */
1548 class TypeInfo_Class : TypeInfo
1549 {
toString()1550 override string toString() const pure { return name; }
1551
opEquals(const TypeInfo o)1552 override bool opEquals(const TypeInfo o) const
1553 {
1554 if (this is o)
1555 return true;
1556 auto c = cast(const TypeInfo_Class)o;
1557 return c && this.name == c.name;
1558 }
1559
getHash(scope const void * p)1560 override size_t getHash(scope const void* p) @trusted const
1561 {
1562 auto o = *cast(Object*)p;
1563 return o ? o.toHash() : 0;
1564 }
1565
equals(in void * p1,in void * p2)1566 override bool equals(in void* p1, in void* p2) const
1567 {
1568 Object o1 = *cast(Object*)p1;
1569 Object o2 = *cast(Object*)p2;
1570
1571 return (o1 is o2) || (o1 && o1.opEquals(o2));
1572 }
1573
compare(in void * p1,in void * p2)1574 override int compare(in void* p1, in void* p2) const
1575 {
1576 Object o1 = *cast(Object*)p1;
1577 Object o2 = *cast(Object*)p2;
1578 int c = 0;
1579
1580 // Regard null references as always being "less than"
1581 if (o1 !is o2)
1582 {
1583 if (o1)
1584 {
1585 if (!o2)
1586 c = 1;
1587 else
1588 c = o1.opCmp(o2);
1589 }
1590 else
1591 c = -1;
1592 }
1593 return c;
1594 }
1595
tsize()1596 override @property size_t tsize() nothrow pure const
1597 {
1598 return Object.sizeof;
1599 }
1600
initializer()1601 override const(void)[] initializer() nothrow pure const @safe
1602 {
1603 return m_init;
1604 }
1605
flags()1606 override @property uint flags() nothrow pure const { return 1; }
1607
offTi()1608 override @property const(OffsetTypeInfo)[] offTi() nothrow pure const
1609 {
1610 return m_offTi;
1611 }
1612
1613 final @property auto info() @safe @nogc nothrow pure const return { return this; }
1614 final @property auto typeinfo() @safe @nogc nothrow pure const return { return this; }
1615
1616 byte[] m_init; /** class static initializer
1617 * (init.length gives size in bytes of class)
1618 */
1619 string name; /// class name
1620 void*[] vtbl; /// virtual function pointer table
1621 Interface[] interfaces; /// interfaces this class implements
1622 TypeInfo_Class base; /// base class
1623 void* destructor;
1624 void function(Object) classInvariant;
1625 enum ClassFlags : uint
1626 {
1627 isCOMclass = 0x1,
1628 noPointers = 0x2,
1629 hasOffTi = 0x4,
1630 hasCtor = 0x8,
1631 hasGetMembers = 0x10,
1632 hasTypeInfo = 0x20,
1633 isAbstract = 0x40,
1634 isCPPclass = 0x80,
1635 hasDtor = 0x100,
1636 }
1637 ClassFlags m_flags;
1638 void* deallocator;
1639 OffsetTypeInfo[] m_offTi;
1640 void function(Object) defaultConstructor; // default Constructor
1641
1642 immutable(void)* m_RTInfo; // data for precise GC
immutable(void)1643 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
1644
1645 /**
1646 * Search all modules for TypeInfo_Class corresponding to classname.
1647 * Returns: null if not found
1648 */
find(const scope char[]classname)1649 static const(TypeInfo_Class) find(const scope char[] classname)
1650 {
1651 foreach (m; ModuleInfo)
1652 {
1653 if (m)
1654 {
1655 //writefln("module %s, %d", m.name, m.localClasses.length);
1656 foreach (c; m.localClasses)
1657 {
1658 if (c is null)
1659 continue;
1660 //writefln("\tclass %s", c.name);
1661 if (c.name == classname)
1662 return c;
1663 }
1664 }
1665 }
1666 return null;
1667 }
1668
1669 /**
1670 * Create instance of Object represented by 'this'.
1671 */
create()1672 Object create() const
1673 {
1674 if (m_flags & 8 && !defaultConstructor)
1675 return null;
1676 if (m_flags & 64) // abstract
1677 return null;
1678 Object o = _d_newclass(this);
1679 if (m_flags & 8 && defaultConstructor)
1680 {
1681 defaultConstructor(o);
1682 }
1683 return o;
1684 }
1685
1686 /**
1687 * Returns true if the class described by `child` derives from or is
1688 * the class described by this `TypeInfo_Class`. Always returns false
1689 * if the argument is null.
1690 *
1691 * Params:
1692 * child = TypeInfo for some class
1693 * Returns:
1694 * true if the class described by `child` derives from or is the
1695 * class described by this `TypeInfo_Class`.
1696 */
isBaseOf(scope const TypeInfo_Class child)1697 final bool isBaseOf(scope const TypeInfo_Class child) const @nogc nothrow pure @trusted
1698 {
1699 if (m_init.length)
1700 {
1701 // If this TypeInfo_Class represents an actual class we only need
1702 // to check the child and its direct ancestors.
1703 for (auto ti = cast() child; ti !is null; ti = ti.base)
1704 if (ti is this)
1705 return true;
1706 return false;
1707 }
1708 else
1709 {
1710 // If this TypeInfo_Class is the .info field of a TypeInfo_Interface
1711 // we also need to recursively check the child's interfaces.
1712 return child !is null && _d_isbaseof(cast() child, this);
1713 }
1714 }
1715 }
1716
1717 alias ClassInfo = TypeInfo_Class;
1718
1719 @safe unittest
1720 {
1721 // Bugzilla 14401
1722 static class X
1723 {
1724 int a;
1725 }
1726
1727 assert(typeid(X).initializer is typeid(X).m_init);
1728 assert(typeid(X).initializer.length == typeid(const(X)).initializer.length);
1729 assert(typeid(X).initializer.length == typeid(shared(X)).initializer.length);
1730 assert(typeid(X).initializer.length == typeid(immutable(X)).initializer.length);
1731 }
1732
1733 class TypeInfo_Interface : TypeInfo
1734 {
toString()1735 override string toString() const pure { return info.name; }
1736
opEquals(Object o)1737 override bool opEquals(Object o)
1738 {
1739 if (this is o)
1740 return true;
1741 auto c = cast(const TypeInfo_Interface)o;
1742 return c && this.info.name == typeid(c).name;
1743 }
1744
getHash(scope const void * p)1745 override size_t getHash(scope const void* p) @trusted const
1746 {
1747 if (!*cast(void**)p)
1748 {
1749 return 0;
1750 }
1751 Interface* pi = **cast(Interface ***)*cast(void**)p;
1752 Object o = cast(Object)(*cast(void**)p - pi.offset);
1753 assert(o);
1754 return o.toHash();
1755 }
1756
equals(in void * p1,in void * p2)1757 override bool equals(in void* p1, in void* p2) const
1758 {
1759 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1760 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1761 pi = **cast(Interface ***)*cast(void**)p2;
1762 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1763
1764 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
1765 }
1766
compare(in void * p1,in void * p2)1767 override int compare(in void* p1, in void* p2) const
1768 {
1769 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1770 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1771 pi = **cast(Interface ***)*cast(void**)p2;
1772 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1773 int c = 0;
1774
1775 // Regard null references as always being "less than"
1776 if (o1 != o2)
1777 {
1778 if (o1)
1779 {
1780 if (!o2)
1781 c = 1;
1782 else
1783 c = o1.opCmp(o2);
1784 }
1785 else
1786 c = -1;
1787 }
1788 return c;
1789 }
1790
tsize()1791 override @property size_t tsize() nothrow pure const
1792 {
1793 return Object.sizeof;
1794 }
1795
initializer()1796 override const(void)[] initializer() const @trusted
1797 {
1798 return (cast(void *)null)[0 .. Object.sizeof];
1799 }
1800
flags()1801 override @property uint flags() nothrow pure const { return 1; }
1802
1803 TypeInfo_Class info;
1804
1805 /**
1806 * Returns true if the class described by `child` derives from the
1807 * interface described by this `TypeInfo_Interface`. Always returns
1808 * false if the argument is null.
1809 *
1810 * Params:
1811 * child = TypeInfo for some class
1812 * Returns:
1813 * true if the class described by `child` derives from the
1814 * interface described by this `TypeInfo_Interface`.
1815 */
isBaseOf(scope const TypeInfo_Class child)1816 final bool isBaseOf(scope const TypeInfo_Class child) const @nogc nothrow pure @trusted
1817 {
1818 return child !is null && _d_isbaseof(cast() child, this.info);
1819 }
1820
1821 /**
1822 * Returns true if the interface described by `child` derives from
1823 * or is the interface described by this `TypeInfo_Interface`.
1824 * Always returns false if the argument is null.
1825 *
1826 * Params:
1827 * child = TypeInfo for some interface
1828 * Returns:
1829 * true if the interface described by `child` derives from or is
1830 * the interface described by this `TypeInfo_Interface`.
1831 */
isBaseOf(scope const TypeInfo_Interface child)1832 final bool isBaseOf(scope const TypeInfo_Interface child) const @nogc nothrow pure @trusted
1833 {
1834 return child !is null && _d_isbaseof(cast() child.info, this.info);
1835 }
1836 }
1837
1838 @safe unittest
1839 {
1840 enum unittest_sym_name = __traits(identifier, __traits(parent, (){}));
1841 enum fqn_unittest = "object." ~ unittest_sym_name; // object.__unittest_LX_CY
1842
1843 interface I {}
1844
1845 assert(fqn_unittest ~ ".I" == typeid(I).info.name);
1846 assert((fqn_unittest ~ ".I").hashOf() == typeid(I).hashOf());
1847 assert(typeid(I).toHash() == typeid(I).hashOf());
1848 }
1849
1850 class TypeInfo_Struct : TypeInfo
1851 {
toString()1852 override string toString() const { return name; }
1853
toHash()1854 override size_t toHash() const
1855 {
1856 return hashOf(this.mangledName);
1857 }
1858
opEquals(Object o)1859 override bool opEquals(Object o)
1860 {
1861 if (this is o)
1862 return true;
1863 auto s = cast(const TypeInfo_Struct)o;
1864 return s && this.mangledName == s.mangledName;
1865 }
1866
getHash(scope const void * p)1867 override size_t getHash(scope const void* p) @trusted pure nothrow const
1868 {
1869 assert(p);
1870 if (xtoHash)
1871 {
1872 return (*xtoHash)(p);
1873 }
1874 else
1875 {
1876 return hashOf(p[0 .. initializer().length]);
1877 }
1878 }
1879
equals(in void * p1,in void * p2)1880 override bool equals(in void* p1, in void* p2) @trusted pure nothrow const
1881 {
1882 import core.stdc.string : memcmp;
1883
1884 if (!p1 || !p2)
1885 return false;
1886 else if (xopEquals)
1887 {
1888 const dg = _memberFunc(p1, xopEquals);
1889 return dg.xopEquals(p2);
1890 }
1891 else if (p1 == p2)
1892 return true;
1893 else
1894 // BUG: relies on the GC not moving objects
1895 return memcmp(p1, p2, initializer().length) == 0;
1896 }
1897
compare(in void * p1,in void * p2)1898 override int compare(in void* p1, in void* p2) @trusted pure nothrow const
1899 {
1900 import core.stdc.string : memcmp;
1901
1902 // Regard null references as always being "less than"
1903 if (p1 != p2)
1904 {
1905 if (p1)
1906 {
1907 if (!p2)
1908 return true;
1909 else if (xopCmp)
1910 {
1911 const dg = _memberFunc(p1, xopCmp);
1912 return dg.xopCmp(p2);
1913 }
1914 else
1915 // BUG: relies on the GC not moving objects
1916 return memcmp(p1, p2, initializer().length);
1917 }
1918 else
1919 return -1;
1920 }
1921 return 0;
1922 }
1923
tsize()1924 override @property size_t tsize() nothrow pure const
1925 {
1926 return initializer().length;
1927 }
1928
initializer()1929 override const(void)[] initializer() nothrow pure const @safe
1930 {
1931 return m_init;
1932 }
1933
flags()1934 override @property uint flags() nothrow pure const { return m_flags; }
1935
talign()1936 override @property size_t talign() nothrow pure const { return m_align; }
1937
destroy(void * p)1938 final override void destroy(void* p) const
1939 {
1940 if (xdtor)
1941 {
1942 if (m_flags & StructFlags.isDynamicType)
1943 (*xdtorti)(p, this);
1944 else
1945 (*xdtor)(p);
1946 }
1947 }
1948
postblit(void * p)1949 override void postblit(void* p) const
1950 {
1951 if (xpostblit)
1952 (*xpostblit)(p);
1953 }
1954
1955 string mangledName;
1956
name()1957 final @property string name() nothrow const @trusted
1958 {
1959 import core.demangle : demangleType;
1960
1961 if (mangledName is null) // e.g., opaque structs
1962 return null;
1963
1964 const key = cast(const void*) this; // faster lookup than TypeInfo_Struct, at the cost of potential duplicates per binary
1965 static string[typeof(key)] demangledNamesCache; // per thread
1966
1967 // not nothrow:
1968 //return demangledNamesCache.require(key, cast(string) demangleType(mangledName));
1969
1970 if (auto pDemangled = key in demangledNamesCache)
1971 return *pDemangled;
1972
1973 const demangled = cast(string) demangleType(mangledName);
1974 demangledNamesCache[key] = demangled;
1975 return demangled;
1976 }
1977
1978 void[] m_init; // initializer; m_init.ptr == null if 0 initialize
1979
1980 @safe pure nothrow
1981 {
1982 size_t function(in void*) xtoHash;
1983 bool function(in void*, in void*) xopEquals;
1984 int function(in void*, in void*) xopCmp;
1985 string function(in void*) xtoString;
1986
1987 enum StructFlags : uint
1988 {
1989 hasPointers = 0x1,
1990 isDynamicType = 0x2, // built at runtime, needs type info in xdtor
1991 }
1992 StructFlags m_flags;
1993 }
1994 union
1995 {
1996 void function(void*) xdtor;
1997 void function(void*, const TypeInfo_Struct ti) xdtorti;
1998 }
1999 void function(void*) xpostblit;
2000
2001 uint m_align;
2002
immutable(void)2003 override @property immutable(void)* rtInfo() nothrow pure const @safe { return m_RTInfo; }
2004
version(WithArgTypes)2005 version (WithArgTypes)
2006 {
2007 override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2008 {
2009 arg1 = m_arg1;
2010 arg2 = m_arg2;
2011 return 0;
2012 }
2013 TypeInfo m_arg1;
2014 TypeInfo m_arg2;
2015 }
2016 immutable(void)* m_RTInfo; // data for precise GC
2017
2018 // The xopEquals and xopCmp members are function pointers to member
2019 // functions, which is not guaranteed to share the same ABI, as it is not
2020 // known whether the `this` parameter is the first or second argument.
2021 // This wrapper is to convert it to a delegate which will always pass the
2022 // `this` parameter in the correct way.
2023 private struct _memberFunc
2024 {
2025 union
2026 {
2027 struct // delegate
2028 {
2029 const void* ptr;
2030 const void* funcptr;
2031 }
2032 @safe pure nothrow
2033 {
2034 bool delegate(in void*) xopEquals;
2035 int delegate(in void*) xopCmp;
2036 }
2037 }
2038 }
2039 }
2040
2041 @system unittest
2042 {
2043 struct S
2044 {
2045 bool opEquals(ref const S rhs) const
2046 {
2047 return false;
2048 }
2049 }
2050 S s;
2051 assert(!typeid(S).equals(&s, &s));
2052 }
2053
2054 class TypeInfo_Tuple : TypeInfo
2055 {
2056 TypeInfo[] elements;
2057
2058 override string toString() const
2059 {
2060 string s = "(";
2061 foreach (i, element; elements)
2062 {
2063 if (i)
2064 s ~= ',';
2065 s ~= element.toString();
2066 }
2067 s ~= ")";
2068 return s;
2069 }
2070
2071 override bool opEquals(Object o)
2072 {
2073 if (this is o)
2074 return true;
2075
2076 auto t = cast(const TypeInfo_Tuple)o;
2077 if (t && elements.length == t.elements.length)
2078 {
2079 for (size_t i = 0; i < elements.length; i++)
2080 {
2081 if (elements[i] != t.elements[i])
2082 return false;
2083 }
2084 return true;
2085 }
2086 return false;
2087 }
2088
2089 override size_t getHash(scope const void* p) const
2090 {
2091 assert(0);
2092 }
2093
2094 override bool equals(in void* p1, in void* p2) const
2095 {
2096 assert(0);
2097 }
2098
2099 override int compare(in void* p1, in void* p2) const
2100 {
2101 assert(0);
2102 }
2103
2104 override @property size_t tsize() nothrow pure const
2105 {
2106 assert(0);
2107 }
2108
2109 override const(void)[] initializer() const @trusted
2110 {
2111 assert(0);
2112 }
2113
2114 override void swap(void* p1, void* p2) const
2115 {
2116 assert(0);
2117 }
2118
2119 override void destroy(void* p) const
2120 {
2121 assert(0);
2122 }
2123
2124 override void postblit(void* p) const
2125 {
2126 assert(0);
2127 }
2128
2129 override @property size_t talign() nothrow pure const
2130 {
2131 assert(0);
2132 }
2133
2134 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2135 {
2136 assert(0);
2137 }
2138 }
2139
2140 class TypeInfo_Const : TypeInfo
2141 {
2142 override string toString() const
2143 {
2144 return cast(string) ("const(" ~ base.toString() ~ ")");
2145 }
2146
2147 //override bool opEquals(Object o) { return base.opEquals(o); }
2148 override bool opEquals(Object o)
2149 {
2150 if (this is o)
2151 return true;
2152
2153 if (typeid(this) != typeid(o))
2154 return false;
2155
2156 auto t = cast(TypeInfo_Const)o;
2157 return base.opEquals(t.base);
2158 }
2159
2160 override size_t getHash(scope const void *p) const { return base.getHash(p); }
2161 override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); }
2162 override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); }
2163 override @property size_t tsize() nothrow pure const { return base.tsize; }
2164 override void swap(void *p1, void *p2) const { return base.swap(p1, p2); }
2165
2166 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
2167 override @property uint flags() nothrow pure const { return base.flags; }
2168
2169 override const(void)[] initializer() nothrow pure const
2170 {
2171 return base.initializer();
2172 }
2173
2174 override @property size_t talign() nothrow pure const { return base.talign; }
2175
2176 version (WithArgTypes) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
2177 {
2178 return base.argTypes(arg1, arg2);
2179 }
2180
2181 TypeInfo base;
2182 }
2183
2184 class TypeInfo_Invariant : TypeInfo_Const
2185 {
2186 override string toString() const
2187 {
2188 return cast(string) ("immutable(" ~ base.toString() ~ ")");
2189 }
2190 }
2191
2192 class TypeInfo_Shared : TypeInfo_Const
2193 {
2194 override string toString() const
2195 {
2196 return cast(string) ("shared(" ~ base.toString() ~ ")");
2197 }
2198 }
2199
2200 class TypeInfo_Inout : TypeInfo_Const
2201 {
2202 override string toString() const
2203 {
2204 return cast(string) ("inout(" ~ base.toString() ~ ")");
2205 }
2206 }
2207
2208 // Contents of Moduleinfo._flags
2209 enum
2210 {
2211 MIctorstart = 0x1, // we've started constructing it
2212 MIctordone = 0x2, // finished construction
2213 MIstandalone = 0x4, // module ctor does not depend on other module
2214 // ctors being done first
2215 MItlsctor = 8,
2216 MItlsdtor = 0x10,
2217 MIctor = 0x20,
2218 MIdtor = 0x40,
2219 MIxgetMembers = 0x80,
2220 MIictor = 0x100,
2221 MIunitTest = 0x200,
2222 MIimportedModules = 0x400,
2223 MIlocalClasses = 0x800,
2224 MIname = 0x1000,
2225 }
2226
2227 /*****************************************
2228 * An instance of ModuleInfo is generated into the object file for each compiled module.
2229 *
2230 * It provides access to various aspects of the module.
2231 * It is not generated for betterC.
2232 */
2233 struct ModuleInfo
2234 {
2235 uint _flags; // MIxxxx
2236 uint _index; // index into _moduleinfo_array[]
2237
2238 version (all)
2239 {
2240 deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
2241 void opAssign(const scope ModuleInfo m) { _flags = m._flags; _index = m._index; }
2242 }
2243 else
2244 {
2245 @disable this();
2246 }
2247
2248 const:
2249 private void* addrOf(int flag) return nothrow pure @nogc
2250 in
2251 {
2252 assert(flag >= MItlsctor && flag <= MIname);
2253 assert(!(flag & (flag - 1)) && !(flag & ~(flag - 1) << 1));
2254 }
2255 do
2256 {
2257 import core.stdc.string : strlen;
2258
2259 void* p = cast(void*)&this + ModuleInfo.sizeof;
2260
2261 if (flags & MItlsctor)
2262 {
2263 if (flag == MItlsctor) return p;
2264 p += typeof(tlsctor).sizeof;
2265 }
2266 if (flags & MItlsdtor)
2267 {
2268 if (flag == MItlsdtor) return p;
2269 p += typeof(tlsdtor).sizeof;
2270 }
2271 if (flags & MIctor)
2272 {
2273 if (flag == MIctor) return p;
2274 p += typeof(ctor).sizeof;
2275 }
2276 if (flags & MIdtor)
2277 {
2278 if (flag == MIdtor) return p;
2279 p += typeof(dtor).sizeof;
2280 }
2281 if (flags & MIxgetMembers)
2282 {
2283 if (flag == MIxgetMembers) return p;
2284 p += typeof(xgetMembers).sizeof;
2285 }
2286 if (flags & MIictor)
2287 {
2288 if (flag == MIictor) return p;
2289 p += typeof(ictor).sizeof;
2290 }
2291 if (flags & MIunitTest)
2292 {
2293 if (flag == MIunitTest) return p;
2294 p += typeof(unitTest).sizeof;
2295 }
2296 if (flags & MIimportedModules)
2297 {
2298 if (flag == MIimportedModules) return p;
2299 p += size_t.sizeof + *cast(size_t*)p * typeof(importedModules[0]).sizeof;
2300 }
2301 if (flags & MIlocalClasses)
2302 {
2303 if (flag == MIlocalClasses) return p;
2304 p += size_t.sizeof + *cast(size_t*)p * typeof(localClasses[0]).sizeof;
2305 }
2306 if (true || flags & MIname) // always available for now
2307 {
2308 if (flag == MIname) return p;
2309 p += strlen(cast(immutable char*)p);
2310 }
2311 assert(0);
2312 }
2313
2314 @property uint index() nothrow pure @nogc { return _index; }
2315
2316 @property uint flags() nothrow pure @nogc { return _flags; }
2317
2318 /************************
2319 * Returns:
2320 * module constructor for thread locals, `null` if there isn't one
2321 */
2322 @property void function() tlsctor() nothrow pure @nogc
2323 {
2324 return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null;
2325 }
2326
2327 /************************
2328 * Returns:
2329 * module destructor for thread locals, `null` if there isn't one
2330 */
2331 @property void function() tlsdtor() nothrow pure @nogc
2332 {
2333 return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null;
2334 }
2335
2336 /*****************************
2337 * Returns:
2338 * address of a module's `const(MemberInfo)[] getMembers(string)` function, `null` if there isn't one
2339 */
2340 @property void* xgetMembers() nothrow pure @nogc
2341 {
2342 return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null;
2343 }
2344
2345 /************************
2346 * Returns:
2347 * module constructor, `null` if there isn't one
2348 */
2349 @property void function() ctor() nothrow pure @nogc
2350 {
2351 return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null;
2352 }
2353
2354 /************************
2355 * Returns:
2356 * module destructor, `null` if there isn't one
2357 */
2358 @property void function() dtor() nothrow pure @nogc
2359 {
2360 return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null;
2361 }
2362
2363 /************************
2364 * Returns:
2365 * module order independent constructor, `null` if there isn't one
2366 */
2367 @property void function() ictor() nothrow pure @nogc
2368 {
2369 return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null;
2370 }
2371
2372 /*************
2373 * Returns:
2374 * address of function that runs the module's unittests, `null` if there isn't one
2375 */
2376 @property void function() unitTest() nothrow pure @nogc
2377 {
2378 return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null;
2379 }
2380
2381 /****************
2382 * Returns:
2383 * array of pointers to the ModuleInfo's of modules imported by this one
2384 */
2385 @property immutable(ModuleInfo*)[] importedModules() return nothrow pure @nogc
2386 {
2387 if (flags & MIimportedModules)
2388 {
2389 auto p = cast(size_t*)addrOf(MIimportedModules);
2390 return (cast(immutable(ModuleInfo*)*)(p + 1))[0 .. *p];
2391 }
2392 return null;
2393 }
2394
2395 /****************
2396 * Returns:
2397 * array of TypeInfo_Class references for classes defined in this module
2398 */
2399 @property TypeInfo_Class[] localClasses() return nothrow pure @nogc
2400 {
2401 if (flags & MIlocalClasses)
2402 {
2403 auto p = cast(size_t*)addrOf(MIlocalClasses);
2404 return (cast(TypeInfo_Class*)(p + 1))[0 .. *p];
2405 }
2406 return null;
2407 }
2408
2409 /********************
2410 * Returns:
2411 * name of module, `null` if no name
2412 */
2413 @property string name() return nothrow pure @nogc
2414 {
2415 import core.stdc.string : strlen;
2416
2417 auto p = cast(immutable char*) addrOf(MIname);
2418 return p[0 .. strlen(p)];
2419 }
2420
2421 static int opApply(scope int delegate(ModuleInfo*) dg)
2422 {
2423 import core.internal.traits : externDFunc;
2424 alias moduleinfos_apply = externDFunc!("rt.minfo.moduleinfos_apply",
2425 int function(scope int delegate(immutable(ModuleInfo*))));
2426 // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
2427 return moduleinfos_apply(
2428 (immutable(ModuleInfo*)m) => dg(cast(ModuleInfo*)m));
2429 }
2430 }
2431
2432 @system unittest
2433 {
2434 ModuleInfo* m1;
2435 foreach (m; ModuleInfo)
2436 {
2437 m1 = m;
2438 }
2439 }
2440
2441 ///////////////////////////////////////////////////////////////////////////////
2442 // Throwable
2443 ///////////////////////////////////////////////////////////////////////////////
2444
2445
2446 /**
2447 * The base class of all thrown objects.
2448 *
2449 * All thrown objects must inherit from Throwable. Class $(D Exception), which
2450 * derives from this class, represents the category of thrown objects that are
2451 * safe to catch and handle. In principle, one should not catch Throwable
2452 * objects that are not derived from $(D Exception), as they represent
2453 * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
2454 * when these errors are thrown, making it unsafe to continue execution after
2455 * catching them.
2456 */
2457 class Throwable : Object
2458 {
2459 interface TraceInfo
2460 {
2461 int opApply(scope int delegate(ref const(char[]))) const;
2462 int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
2463 string toString() const;
2464 }
2465
2466 string msg; /// A message describing the error.
2467
2468 /**
2469 * The _file name of the D source code corresponding with
2470 * where the error was thrown from.
2471 */
2472 string file;
2473 /**
2474 * The _line number of the D source code corresponding with
2475 * where the error was thrown from.
2476 */
2477 size_t line;
2478
2479 /**
2480 * The stack trace of where the error happened. This is an opaque object
2481 * that can either be converted to $(D string), or iterated over with $(D
2482 * foreach) to extract the items in the stack trace (as strings).
2483 */
2484 TraceInfo info;
2485
2486 /**
2487 * A reference to the _next error in the list. This is used when a new
2488 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2489 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2490 * field.
2491 */
2492 private Throwable nextInChain;
2493
2494 private uint _refcount; // 0 : allocated by GC
2495 // 1 : allocated by _d_newThrowable()
2496 // 2.. : reference count + 1
2497
2498 /**
2499 * Returns:
2500 * A reference to the _next error in the list. This is used when a new
2501 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
2502 * caught $(D Exception) will be chained to the new $(D Throwable) via this
2503 * field.
2504 */
2505 @property inout(Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; }
2506
2507 /**
2508 * Replace next in chain with `tail`.
2509 * Use `chainTogether` instead if at all possible.
2510 */
2511 @property void next(Throwable tail) @safe scope pure nothrow @nogc
2512 {
2513 if (tail && tail._refcount)
2514 ++tail._refcount; // increment the replacement *first*
2515
2516 auto n = nextInChain;
2517 nextInChain = null; // sever the tail before deleting it
2518
2519 if (n && n._refcount)
2520 _d_delThrowable(n); // now delete the old tail
2521
2522 nextInChain = tail; // and set the new tail
2523 }
2524
2525 /**
2526 * Returns:
2527 * mutable reference to the reference count, which is
2528 * 0 - allocated by the GC, 1 - allocated by _d_newThrowable(),
2529 * and >=2 which is the reference count + 1
2530 * Note:
2531 * Marked as `@system` to discourage casual use of it.
2532 */
2533 @system @nogc final pure nothrow ref uint refcount() return { return _refcount; }
2534
2535 /**
2536 * Loop over the chain of Throwables.
2537 */
2538 int opApply(scope int delegate(Throwable) dg)
2539 {
2540 int result = 0;
2541 for (Throwable t = this; t; t = t.nextInChain)
2542 {
2543 result = dg(t);
2544 if (result)
2545 break;
2546 }
2547 return result;
2548 }
2549
2550 /**
2551 * Append `e2` to chain of exceptions that starts with `e1`.
2552 * Params:
2553 * e1 = start of chain (can be null)
2554 * e2 = second part of chain (can be null)
2555 * Returns:
2556 * Throwable that is at the start of the chain; null if both `e1` and `e2` are null
2557 */
2558 static @__future @system @nogc pure nothrow Throwable chainTogether(return scope Throwable e1, return scope Throwable e2)
2559 {
2560 if (!e1)
2561 return e2;
2562 if (!e2)
2563 return e1;
2564 if (e2.refcount())
2565 ++e2.refcount();
2566
2567 for (auto e = e1; 1; e = e.nextInChain)
2568 {
2569 if (!e.nextInChain)
2570 {
2571 e.nextInChain = e2;
2572 break;
2573 }
2574 }
2575 return e1;
2576 }
2577
2578 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2579 {
2580 this.msg = msg;
2581 this.nextInChain = nextInChain;
2582 if (nextInChain && nextInChain._refcount)
2583 ++nextInChain._refcount;
2584 //this.info = _d_traceContext();
2585 }
2586
2587 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2588 {
2589 this(msg, nextInChain);
2590 this.file = file;
2591 this.line = line;
2592 //this.info = _d_traceContext();
2593 }
2594
2595 @trusted nothrow ~this()
2596 {
2597 if (nextInChain && nextInChain._refcount)
2598 _d_delThrowable(nextInChain);
2599 }
2600
2601 /**
2602 * Overrides $(D Object.toString) and returns the error message.
2603 * Internally this forwards to the $(D toString) overload that
2604 * takes a $(D_PARAM sink) delegate.
2605 */
2606 override string toString()
2607 {
2608 string s;
2609 toString((in buf) { s ~= buf; });
2610 return s;
2611 }
2612
2613 /**
2614 * The Throwable hierarchy uses a toString overload that takes a
2615 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
2616 * performed in certain error situations. Override this $(D
2617 * toString) method to customize the error message.
2618 */
2619 void toString(scope void delegate(in char[]) sink) const
2620 {
2621 import core.internal.string : unsignedToTempString;
2622
2623 char[20] tmpBuff = void;
2624
2625 sink(typeid(this).name);
2626 sink("@"); sink(file);
2627 sink("("); sink(unsignedToTempString(line, tmpBuff)); sink(")");
2628
2629 if (msg.length)
2630 {
2631 sink(": "); sink(msg);
2632 }
2633 if (info)
2634 {
2635 try
2636 {
2637 sink("\n----------------");
2638 foreach (t; info)
2639 {
2640 sink("\n"); sink(t);
2641 }
2642 }
2643 catch (Throwable)
2644 {
2645 // ignore more errors
2646 }
2647 }
2648 }
2649
2650 /**
2651 * Get the message describing the error.
2652 *
2653 * This getter is an alternative way to access the Exception's message,
2654 * with the added advantage of being override-able in subclasses.
2655 * Subclasses are hence free to do their own memory managements without
2656 * being tied to the requirement of providing a `string` in a field.
2657 *
2658 * The default behavior is to return the `Throwable.msg` field.
2659 *
2660 * Returns:
2661 * A message representing the cause of the `Throwable`
2662 */
2663 @__future const(char)[] message() const @safe nothrow
2664 {
2665 return this.msg;
2666 }
2667 }
2668
2669
2670 /**
2671 * The base class of all errors that are safe to catch and handle.
2672 *
2673 * In principle, only thrown objects derived from this class are safe to catch
2674 * inside a $(D catch) block. Thrown objects not derived from Exception
2675 * represent runtime errors that should not be caught, as certain runtime
2676 * guarantees may not hold, making it unsafe to continue program execution.
2677 */
2678 class Exception : Throwable
2679 {
2680
2681 /**
2682 * Creates a new instance of Exception. The nextInChain parameter is used
2683 * internally and should always be $(D null) when passed by user code.
2684 * This constructor does not automatically throw the newly-created
2685 * Exception; the $(D throw) statement should be used for that purpose.
2686 */
2687 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null)
2688 {
2689 super(msg, file, line, nextInChain);
2690 }
2691
2692 @nogc @safe pure nothrow this(string msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__)
2693 {
2694 super(msg, file, line, nextInChain);
2695 }
2696 }
2697
2698 ///
2699 @safe unittest
2700 {
2701 bool gotCaught;
2702 try
2703 {
2704 throw new Exception("msg");
2705 }
2706 catch (Exception e)
2707 {
2708 gotCaught = true;
2709 assert(e.msg == "msg");
2710 }
2711 assert(gotCaught);
2712 }
2713
2714 @system unittest
2715 {
2716 {
2717 auto e = new Exception("msg");
2718 assert(e.file == __FILE__);
2719 assert(e.line == __LINE__ - 2);
2720 assert(e.nextInChain is null);
2721 assert(e.msg == "msg");
2722 }
2723
2724 {
2725 auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
2726 assert(e.file == "hello");
2727 assert(e.line == 42);
2728 assert(e.nextInChain !is null);
2729 assert(e.msg == "msg");
2730 }
2731
2732 {
2733 auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
2734 assert(e.file == "hello");
2735 assert(e.line == 42);
2736 assert(e.nextInChain !is null);
2737 assert(e.msg == "msg");
2738 }
2739
2740 {
2741 auto e = new Exception("message");
2742 assert(e.message == "message");
2743 }
2744 }
2745
2746
2747 /**
2748 * The base class of all unrecoverable runtime errors.
2749 *
2750 * This represents the category of $(D Throwable) objects that are $(B not)
2751 * safe to catch and handle. In principle, one should not catch Error
2752 * objects, as they represent unrecoverable runtime errors.
2753 * Certain runtime guarantees may fail to hold when these errors are
2754 * thrown, making it unsafe to continue execution after catching them.
2755 */
2756 class Error : Throwable
2757 {
2758 /**
2759 * Creates a new instance of Error. The nextInChain parameter is used
2760 * internally and should always be $(D null) when passed by user code.
2761 * This constructor does not automatically throw the newly-created
2762 * Error; the $(D throw) statement should be used for that purpose.
2763 */
2764 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null)
2765 {
2766 super(msg, nextInChain);
2767 bypassedException = null;
2768 }
2769
2770 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null)
2771 {
2772 super(msg, file, line, nextInChain);
2773 bypassedException = null;
2774 }
2775
2776 /** The first $(D Exception) which was bypassed when this Error was thrown,
2777 or $(D null) if no $(D Exception)s were pending. */
2778 Throwable bypassedException;
2779 }
2780
2781 ///
2782 @system unittest
2783 {
2784 bool gotCaught;
2785 try
2786 {
2787 throw new Error("msg");
2788 }
2789 catch (Error e)
2790 {
2791 gotCaught = true;
2792 assert(e.msg == "msg");
2793 }
2794 assert(gotCaught);
2795 }
2796
2797 @safe unittest
2798 {
2799 {
2800 auto e = new Error("msg");
2801 assert(e.file is null);
2802 assert(e.line == 0);
2803 assert(e.nextInChain is null);
2804 assert(e.msg == "msg");
2805 assert(e.bypassedException is null);
2806 }
2807
2808 {
2809 auto e = new Error("msg", new Exception("It's an Exception!"));
2810 assert(e.file is null);
2811 assert(e.line == 0);
2812 assert(e.nextInChain !is null);
2813 assert(e.msg == "msg");
2814 assert(e.bypassedException is null);
2815 }
2816
2817 {
2818 auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
2819 assert(e.file == "hello");
2820 assert(e.line == 42);
2821 assert(e.nextInChain !is null);
2822 assert(e.msg == "msg");
2823 assert(e.bypassedException is null);
2824 }
2825 }
2826
2827 extern (C)
2828 {
2829 // from druntime/src/rt/aaA.d
2830
2831 private struct AA { void* impl; }
2832 // size_t _aaLen(in AA aa) pure nothrow @nogc;
2833 private void* _aaGetY(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow;
2834 private void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow;
2835 // inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey);
2836 inout(void[]) _aaValues(inout AA aa, const size_t keysz, const size_t valsz, const TypeInfo tiValueArray) pure nothrow;
2837 inout(void[]) _aaKeys(inout AA aa, const size_t keysz, const TypeInfo tiKeyArray) pure nothrow;
2838 void* _aaRehash(AA* paa, const scope TypeInfo keyti) pure nothrow;
2839 void _aaClear(AA aa) pure nothrow;
2840
2841 // alias _dg_t = extern(D) int delegate(void*);
2842 // int _aaApply(AA aa, size_t keysize, _dg_t dg);
2843
2844 // alias _dg2_t = extern(D) int delegate(void*, void*);
2845 // int _aaApply2(AA aa, size_t keysize, _dg2_t dg);
2846
2847 private struct AARange { AA impl; size_t idx; }
2848 AARange _aaRange(AA aa) pure nothrow @nogc @safe;
2849 bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe;
2850 void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe;
2851 void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe;
2852 void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe;
2853
2854 int _aaEqual(scope const TypeInfo tiRaw, scope const AA aa1, scope const AA aa2);
2855 hash_t _aaGetHash(scope const AA* aa, scope const TypeInfo tiRaw) nothrow;
2856
2857 /*
2858 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
2859 This is a typesystem hole, however this is existing hole.
2860 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
2861 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
2862 */
2863 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure;
2864 }
2865
2866 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
2867 {
2868 return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
2869 }
2870
2871 alias AssociativeArray(Key, Value) = Value[Key];
2872
2873 /***********************************
2874 * Removes all remaining keys and values from an associative array.
2875 * Params:
2876 * aa = The associative array.
2877 */
2878 void clear(Value, Key)(Value[Key] aa)
2879 {
2880 _aaClear(*cast(AA *) &aa);
2881 }
2882
2883 /** ditto */
2884 void clear(Value, Key)(Value[Key]* aa)
2885 {
2886 _aaClear(*cast(AA *) aa);
2887 }
2888
2889 ///
2890 @system unittest
2891 {
2892 auto aa = ["k1": 2];
2893 aa.clear;
2894 assert("k1" !in aa);
2895 }
2896
2897 // Issue 20559
2898 @system unittest
2899 {
2900 static class Foo
2901 {
2902 int[string] aa;
2903 alias aa this;
2904 }
2905
2906 auto v = new Foo();
2907 v["Hello World"] = 42;
2908 v.clear;
2909 assert("Hello World" !in v);
2910
2911 // Test for T*
2912 static assert(!__traits(compiles, (&v).clear));
2913 static assert( __traits(compiles, (*(&v)).clear));
2914 }
2915
2916 /***********************************
2917 * Reorganizes the associative array in place so that lookups are more
2918 * efficient.
2919 * Params:
2920 * aa = The associative array.
2921 * Returns:
2922 * The rehashed associative array.
2923 */
2924 T rehash(T : Value[Key], Value, Key)(T aa)
2925 {
2926 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
2927 return aa;
2928 }
2929
2930 /** ditto */
2931 T rehash(T : Value[Key], Value, Key)(T* aa)
2932 {
2933 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
2934 return *aa;
2935 }
2936
2937 /** ditto */
2938 T rehash(T : shared Value[Key], Value, Key)(T aa)
2939 {
2940 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
2941 return aa;
2942 }
2943
2944 /** ditto */
2945 T rehash(T : shared Value[Key], Value, Key)(T* aa)
2946 {
2947 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
2948 return *aa;
2949 }
2950
2951 /***********************************
2952 * Creates a new associative array of the same size and copies the contents of
2953 * the associative array into it.
2954 * Params:
2955 * aa = The associative array.
2956 */
2957 V[K] dup(T : V[K], K, V)(T aa)
2958 {
2959 //pragma(msg, "K = ", K, ", V = ", V);
2960
2961 // Bug10720 - check whether V is copyable
2962 static assert(is(typeof({ V v = aa[K.init]; })),
2963 "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");
2964
2965 V[K] result;
2966
2967 //foreach (k, ref v; aa)
2968 // result[k] = v; // Bug13701 - won't work if V is not mutable
2969
2970 ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow
2971 {
2972 import core.stdc.string : memcpy;
2973
2974 void* pv = _aaGetY(cast(AA*)&result, typeid(V[K]), V.sizeof, &k);
2975 memcpy(pv, &v, V.sizeof);
2976 return *cast(V*)pv;
2977 }
2978
2979 foreach (k, ref v; aa)
2980 {
2981 static if (!__traits(hasPostblit, V))
2982 duplicateElem(k, v);
2983 else static if (__traits(isStaticArray, V))
2984 _doPostblit(duplicateElem(k, v)[]);
2985 else static if (!is(typeof(v.__xpostblit())) && is(immutable V == immutable UV, UV))
2986 (() @trusted => *cast(UV*) &duplicateElem(k, v))().__xpostblit();
2987 else
2988 duplicateElem(k, v).__xpostblit();
2989 }
2990
2991 return result;
2992 }
2993
2994 /** ditto */
2995 V[K] dup(T : V[K], K, V)(T* aa)
2996 {
2997 return (*aa).dup;
2998 }
2999
3000 ///
3001 @safe unittest
3002 {
3003 auto aa = ["k1": 2];
3004 auto a2 = aa.dup;
3005 aa["k2"] = 3;
3006 assert("k2" !in a2);
3007 }
3008
3009 // this should never be made public.
3010 private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe
3011 {
3012 // ensure we are dealing with a genuine AA.
3013 static if (is(const(V[K]) == const(T)))
3014 alias realAA = aa;
3015 else
3016 const(V[K]) realAA = aa;
3017 return _aaRange(() @trusted { return *cast(AA*)&realAA; } ());
3018 }
3019
3020 /***********************************
3021 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3022 * which will iterate over the keys of the associative array. The keys are
3023 * returned by reference.
3024 *
3025 * If structural changes are made to the array (removing or adding keys), all
3026 * ranges previously obtained through this function are invalidated. The
3027 * following example program will dereference a null pointer:
3028 *
3029 *---
3030 * import std.stdio : writeln;
3031 *
3032 * auto dict = ["k1": 1, "k2": 2];
3033 * auto keyRange = dict.byKey;
3034 * dict.clear;
3035 * writeln(keyRange.front); // Segmentation fault
3036 *---
3037 *
3038 * Params:
3039 * aa = The associative array.
3040 * Returns:
3041 * A forward range referencing the keys of the associative array.
3042 */
3043 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3044 {
3045 import core.internal.traits : substInout;
3046
3047 static struct Result
3048 {
3049 AARange r;
3050
3051 pure nothrow @nogc:
3052 @property bool empty() @safe { return _aaRangeEmpty(r); }
3053 @property ref front() @trusted
3054 {
3055 return *cast(substInout!K*) _aaRangeFrontKey(r);
3056 }
3057 void popFront() @safe { _aaRangePopFront(r); }
3058 @property Result save() { return this; }
3059 }
3060
3061 return Result(_aaToRange(aa));
3062 }
3063
3064 /** ditto */
3065 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
3066 {
3067 return (*aa).byKey();
3068 }
3069
3070 ///
3071 @safe unittest
3072 {
3073 auto dict = [1: "v1", 2: "v2"];
3074 int sum;
3075 foreach (v; dict.byKey)
3076 sum += v;
3077
3078 assert(sum == 3);
3079 }
3080
3081 /***********************************
3082 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3083 * which will iterate over the values of the associative array. The values are
3084 * returned by reference.
3085 *
3086 * If structural changes are made to the array (removing or adding keys), all
3087 * ranges previously obtained through this function are invalidated. The
3088 * following example program will dereference a null pointer:
3089 *
3090 *---
3091 * import std.stdio : writeln;
3092 *
3093 * auto dict = ["k1": 1, "k2": 2];
3094 * auto valueRange = dict.byValue;
3095 * dict.clear;
3096 * writeln(valueRange.front); // Segmentation fault
3097 *---
3098 *
3099 * Params:
3100 * aa = The associative array.
3101 * Returns:
3102 * A forward range referencing the values of the associative array.
3103 */
3104 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3105 {
3106 import core.internal.traits : substInout;
3107
3108 static struct Result
3109 {
3110 AARange r;
3111
3112 pure nothrow @nogc:
3113 @property bool empty() @safe { return _aaRangeEmpty(r); }
3114 @property ref front() @trusted
3115 {
3116 return *cast(substInout!V*) _aaRangeFrontValue(r);
3117 }
3118 void popFront() @safe { _aaRangePopFront(r); }
3119 @property Result save() { return this; }
3120 }
3121
3122 return Result(_aaToRange(aa));
3123 }
3124
3125 /** ditto */
3126 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3127 {
3128 return (*aa).byValue();
3129 }
3130
3131 ///
3132 @safe unittest
3133 {
3134 auto dict = ["k1": 1, "k2": 2];
3135 int sum;
3136 foreach (v; dict.byValue)
3137 sum += v;
3138
3139 assert(sum == 3);
3140 }
3141
3142 /***********************************
3143 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives)
3144 * which will iterate over the key-value pairs of the associative array. The
3145 * returned pairs are represented by an opaque type with `.key` and `.value`
3146 * properties for accessing references to the key and value of the pair,
3147 * respectively.
3148 *
3149 * If structural changes are made to the array (removing or adding keys), all
3150 * ranges previously obtained through this function are invalidated. The
3151 * following example program will dereference a null pointer:
3152 *
3153 *---
3154 * import std.stdio : writeln;
3155 *
3156 * auto dict = ["k1": 1, "k2": 2];
3157 * auto kvRange = dict.byKeyValue;
3158 * dict.clear;
3159 * writeln(kvRange.front.key, ": ", kvRange.front.value); // Segmentation fault
3160 *---
3161 *
3162 * Note that this is a low-level interface to iterating over the associative
3163 * array and is not compatible withth the
3164 * $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) type in Phobos.
3165 * For compatibility with `Tuple`, use
3166 * $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead.
3167 *
3168 * Params:
3169 * aa = The associative array.
3170 * Returns:
3171 * A forward range referencing the pairs of the associative array.
3172 */
3173 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
3174 {
3175 import core.internal.traits : substInout;
3176
3177 static struct Result
3178 {
3179 AARange r;
3180
3181 pure nothrow @nogc:
3182 @property bool empty() @safe { return _aaRangeEmpty(r); }
3183 @property auto front()
3184 {
3185 static struct Pair
3186 {
3187 // We save the pointers here so that the Pair we return
3188 // won't mutate when Result.popFront is called afterwards.
3189 private void* keyp;
3190 private void* valp;
3191
3192 @property ref key() inout @trusted
3193 {
3194 return *cast(substInout!K*) keyp;
3195 }
3196 @property ref value() inout @trusted
3197 {
3198 return *cast(substInout!V*) valp;
3199 }
3200 }
3201 return Pair(_aaRangeFrontKey(r),
3202 _aaRangeFrontValue(r));
3203 }
3204 void popFront() @safe { return _aaRangePopFront(r); }
3205 @property Result save() { return this; }
3206 }
3207
3208 return Result(_aaToRange(aa));
3209 }
3210
3211 /** ditto */
3212 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
3213 {
3214 return (*aa).byKeyValue();
3215 }
3216
3217 ///
3218 @safe unittest
3219 {
3220 auto dict = ["k1": 1, "k2": 2];
3221 int sum;
3222 foreach (e; dict.byKeyValue)
3223 {
3224 assert(e.key[1] == e.value + '0');
3225 sum += e.value;
3226 }
3227
3228 assert(sum == 3);
3229 }
3230
3231 /***********************************
3232 * Returns a newly allocated dynamic array containing a copy of the keys from
3233 * the associative array.
3234 * Params:
3235 * aa = The associative array.
3236 * Returns:
3237 * A dynamic array containing a copy of the keys.
3238 */
3239 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
3240 {
3241 // ensure we are dealing with a genuine AA.
3242 static if (is(const(Value[Key]) == const(T)))
3243 alias realAA = aa;
3244 else
3245 const(Value[Key]) realAA = aa;
3246 auto res = () @trusted {
3247 auto a = cast(void[])_aaKeys(*cast(inout(AA)*)&realAA, Key.sizeof, typeid(Key[]));
3248 return *cast(Key[]*)&a;
3249 }();
3250 static if (__traits(hasPostblit, Key))
3251 _doPostblit(res);
3252 return res;
3253 }
3254
3255 /** ditto */
3256 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
3257 {
3258 return (*aa).keys;
3259 }
3260
3261 ///
3262 @safe unittest
3263 {
3264 auto aa = [1: "v1", 2: "v2"];
3265 int sum;
3266 foreach (k; aa.keys)
3267 sum += k;
3268
3269 assert(sum == 3);
3270 }
3271
3272 @safe unittest
3273 {
3274 static struct S
3275 {
3276 string str;
3277 void[][string] dict;
3278 alias dict this;
3279 }
3280
3281 auto s = S("a");
3282 assert(s.keys.length == 0);
3283 }
3284
3285 @safe unittest
3286 {
3287 @safe static struct Key
3288 {
3289 string str;
3290 this(this) @safe {}
3291 }
3292 string[Key] aa;
3293 static assert(__traits(compiles, {
3294 void test() @safe {
3295 const _ = aa.keys;
3296 }
3297 }));
3298 }
3299
3300 @safe unittest
3301 {
3302 static struct Key
3303 {
3304 string str;
3305 this(this) @system {}
3306 }
3307 string[Key] aa;
3308 static assert(!__traits(compiles, {
3309 void test() @safe {
3310 const _ = aa.keys;
3311 }
3312 }));
3313 }
3314
3315 /***********************************
3316 * Returns a newly allocated dynamic array containing a copy of the values from
3317 * the associative array.
3318 * Params:
3319 * aa = The associative array.
3320 * Returns:
3321 * A dynamic array containing a copy of the values.
3322 */
3323 Value[] values(T : Value[Key], Value, Key)(T aa) @property
3324 {
3325 // ensure we are dealing with a genuine AA.
3326 static if (is(const(Value[Key]) == const(T)))
3327 alias realAA = aa;
3328 else
3329 const(Value[Key]) realAA = aa;
3330 auto res = () @trusted {
3331 auto a = cast(void[])_aaValues(*cast(inout(AA)*)&realAA, Key.sizeof, Value.sizeof, typeid(Value[]));
3332 return *cast(Value[]*)&a;
3333 }();
3334 static if (__traits(hasPostblit, Value))
3335 _doPostblit(res);
3336 return res;
3337 }
3338
3339 /** ditto */
3340 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
3341 {
3342 return (*aa).values;
3343 }
3344
3345 ///
3346 @safe unittest
3347 {
3348 auto aa = ["k1": 1, "k2": 2];
3349 int sum;
3350 foreach (e; aa.values)
3351 sum += e;
3352
3353 assert(sum == 3);
3354 }
3355
3356 @safe unittest
3357 {
3358 static struct S
3359 {
3360 string str;
3361 void[][string] dict;
3362 alias dict this;
3363 }
3364
3365 auto s = S("a");
3366 assert(s.values.length == 0);
3367 }
3368
3369 @safe unittest
3370 {
3371 @safe static struct Value
3372 {
3373 string str;
3374 this(this) @safe {}
3375 }
3376 Value[string] aa;
3377 static assert(__traits(compiles, {
3378 void test() @safe {
3379 const _ = aa.values;
3380 }
3381 }));
3382 }
3383
3384 @safe unittest
3385 {
3386 static struct Value
3387 {
3388 string str;
3389 this(this) @system {}
3390 }
3391 Value[string] aa;
3392 static assert(!__traits(compiles, {
3393 void test() @safe {
3394 const _ = aa.values;
3395 }
3396 }));
3397 }
3398
3399 /***********************************
3400 * Looks up key; if it exists returns corresponding value else evaluates and
3401 * returns defaultValue.
3402 * Params:
3403 * aa = The associative array.
3404 * key = The key.
3405 * defaultValue = The default value.
3406 * Returns:
3407 * The value.
3408 */
3409 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)
3410 {
3411 auto p = key in aa;
3412 return p ? *p : defaultValue;
3413 }
3414
3415 /** ditto */
3416 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
3417 {
3418 return (*aa).get(key, defaultValue);
3419 }
3420
3421 ///
3422 @safe unittest
3423 {
3424 auto aa = ["k1": 1];
3425 assert(aa.get("k1", 0) == 1);
3426 assert(aa.get("k2", 0) == 0);
3427 }
3428
3429 /***********************************
3430 * Looks up key; if it exists returns corresponding value else evaluates
3431 * value, adds it to the associative array and returns it.
3432 * Params:
3433 * aa = The associative array.
3434 * key = The key.
3435 * value = The required value.
3436 * Returns:
3437 * The value.
3438 */
3439 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
3440 {
3441 bool found;
3442 // if key is @safe-ly copyable, `require` can infer @safe
3443 static if (isSafeCopyable!K)
3444 {
3445 auto p = () @trusted
3446 {
3447 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3448 } ();
3449 }
3450 else
3451 {
3452 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3453 }
3454 if (found)
3455 return *p;
3456 else
3457 {
3458 *p = value; // Not `return (*p = value)` since if `=` is overloaded
3459 return *p; // this might not return a ref to the left-hand side.
3460 }
3461 }
3462
3463 ///
3464 @safe unittest
3465 {
3466 auto aa = ["k1": 1];
3467 assert(aa.require("k1", 0) == 1);
3468 assert(aa.require("k2", 0) == 0);
3469 assert(aa["k2"] == 0);
3470 }
3471
3472 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test.
3473 private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); }));
3474
3475 /***********************************
3476 * Looks up key; if it exists applies the update callable else evaluates the
3477 * create callable and adds it to the associative array
3478 * Params:
3479 * aa = The associative array.
3480 * key = The key.
3481 * create = The callable to apply on create.
3482 * update = The callable to apply on update.
3483 */
3484 void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
3485 if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof(update(aa[K.init])) == void)))
3486 {
3487 bool found;
3488 // if key is @safe-ly copyable, `update` may infer @safe
3489 static if (isSafeCopyable!K)
3490 {
3491 auto p = () @trusted
3492 {
3493 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3494 } ();
3495 }
3496 else
3497 {
3498 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
3499 }
3500 if (!found)
3501 *p = create();
3502 else
3503 {
3504 static if (is(typeof(update(*p)) == void))
3505 update(*p);
3506 else
3507 *p = update(*p);
3508 }
3509 }
3510
3511 ///
3512 @system unittest
3513 {
3514 auto aa = ["k1": 1];
3515
3516 aa.update("k1", {
3517 return -1; // create (won't be executed)
3518 }, (ref int v) {
3519 v += 1; // update
3520 });
3521 assert(aa["k1"] == 2);
3522
3523 aa.update("k2", {
3524 return 0; // create
3525 }, (ref int v) {
3526 v = -1; // update (won't be executed)
3527 });
3528 assert(aa["k2"] == 0);
3529 }
3530
3531 @safe unittest
3532 {
3533 static struct S
3534 {
3535 int x;
3536 @nogc nothrow pure:
3537 this(this) @system {}
3538
3539 @safe const:
3540 // stubs
3541 bool opEquals(S rhs) { assert(0); }
3542 size_t toHash() { assert(0); }
3543 }
3544
3545 int[string] aai;
3546 static assert(is(typeof(() @safe { aai.require("a", 1234); })));
3547 static assert(is(typeof(() @safe { aai.update("a", { return 1234; }, (ref int x) { x++; return x; }); })));
3548
3549 S[string] aas;
3550 static assert(is(typeof(() { aas.require("a", S(1234)); })));
3551 static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3552 static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
3553
3554 int[S] aais;
3555 static assert(is(typeof(() { aais.require(S(1234), 1234); })));
3556 static assert(is(typeof(() { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3557 static assert(!is(typeof(() @safe { aais.require(S(1234), 1234); })));
3558 static assert(!is(typeof(() @safe { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
3559 }
3560
3561 @safe unittest
3562 {
3563 struct S0
3564 {
3565 int opCall(ref int v)
3566 {
3567 return v + 1;
3568 }
3569 }
3570
3571 struct S1
3572 {
3573 int opCall()()
3574 {
3575 return -2;
3576 }
3577
3578 T opCall(T)(ref T v)
3579 {
3580 return v + 1;
3581 }
3582 }
3583
3584 int[string] a = ["2" : 1];
3585 a.update("2", () => -1, S0.init);
3586 assert(a["2"] == 2);
3587 a.update("0", () => -1, S0.init);
3588 assert(a["0"] == -1);
3589 a.update("2", S1.init, S1.init);
3590 assert(a["2"] == 3);
3591 a.update("1", S1.init, S1.init);
3592 assert(a["1"] == -2);
3593 }
3594
3595 @system unittest
3596 {
3597 int[string] aa;
3598
3599 foreach (n; 0 .. 2)
3600 aa.update("k1", {
3601 return 7;
3602 }, (ref int v) {
3603 return v + 3;
3604 });
3605 assert(aa["k1"] == 10);
3606 }
3607
3608 version (CoreDdoc)
3609 {
3610 // This lets DDoc produce better documentation.
3611
3612 /**
3613 Calculates the hash value of `arg` with an optional `seed` initial value.
3614 The result might not be equal to `typeid(T).getHash(&arg)`.
3615
3616 Params:
3617 arg = argument to calculate the hash value of
3618 seed = optional `seed` value (may be used for hash chaining)
3619
3620 Return: calculated hash value of `arg`
3621 */
3622 size_t hashOf(T)(auto ref T arg, size_t seed)
3623 {
3624 static import core.internal.hash;
3625 return core.internal.hash.hashOf(arg, seed);
3626 }
3627 /// ditto
3628 size_t hashOf(T)(auto ref T arg)
3629 {
3630 static import core.internal.hash;
3631 return core.internal.hash.hashOf(arg);
3632 }
3633
3634 @safe unittest
3635 {
3636 auto h1 = "my.string".hashOf;
3637 assert(h1 == "my.string".hashOf);
3638 }
3639 }
3640 else
3641 {
3642 public import core.internal.hash : hashOf;
3643 }
3644
3645 ///
3646 @system unittest
3647 {
3648 class MyObject
3649 {
3650 size_t myMegaHash() const @safe pure nothrow
3651 {
3652 return 42;
3653 }
3654 }
3655 struct Test
3656 {
3657 int a;
3658 string b;
3659 MyObject c;
3660 size_t toHash() const pure nothrow
3661 {
3662 size_t hash = a.hashOf();
3663 hash = b.hashOf(hash);
3664 size_t h1 = c.myMegaHash();
3665 hash = h1.hashOf(hash); //Mix two hash values
3666 return hash;
3667 }
3668 }
3669 }
3670
3671 bool _xopEquals(in void*, in void*)
3672 {
3673 throw new Error("TypeInfo.equals is not implemented");
3674 }
3675
3676 bool _xopCmp(in void*, in void*)
3677 {
3678 throw new Error("TypeInfo.compare is not implemented");
3679 }
3680
3681 /******************************************
3682 * Create RTInfo for type T
3683 */
3684
3685 template RTInfoImpl(size_t[] pointerBitmap)
3686 {
3687 immutable size_t[pointerBitmap.length] RTInfoImpl = pointerBitmap[];
3688 }
3689
3690 template NoPointersBitmapPayload(size_t N)
3691 {
3692 enum size_t[N] NoPointersBitmapPayload = 0;
3693 }
3694
3695 template RTInfo(T)
3696 {
3697 enum pointerBitmap = __traits(getPointerBitmap, T);
3698 static if (pointerBitmap[1 .. $] == NoPointersBitmapPayload!(pointerBitmap.length - 1))
3699 enum RTInfo = rtinfoNoPointers;
3700 else
3701 enum RTInfo = RTInfoImpl!(pointerBitmap).ptr;
3702 }
3703
3704 /**
3705 * shortcuts for the precise GC, also generated by the compiler
3706 * used instead of the actual pointer bitmap
3707 */
3708 enum immutable(void)* rtinfoNoPointers = null;
3709 enum immutable(void)* rtinfoHasPointers = cast(void*)1;
3710
3711 // Helper functions
3712
3713 private inout(TypeInfo) getElement(return scope inout TypeInfo value) @trusted pure nothrow
3714 {
3715 TypeInfo element = cast() value;
3716 for (;;)
3717 {
3718 if (auto qualified = cast(TypeInfo_Const) element)
3719 element = qualified.base;
3720 else if (auto redefined = cast(TypeInfo_Enum) element)
3721 element = redefined.base;
3722 else if (auto staticArray = cast(TypeInfo_StaticArray) element)
3723 element = staticArray.value;
3724 else if (auto vector = cast(TypeInfo_Vector) element)
3725 element = vector.base;
3726 else
3727 break;
3728 }
3729 return cast(inout) element;
3730 }
3731
3732 private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr, const size_t count) @trusted nothrow
3733 {
3734 if (!count)
3735 return 0;
3736
3737 const size_t elementSize = element.tsize;
3738 if (!elementSize)
3739 return 0;
3740
3741 static bool hasCustomToHash(const scope TypeInfo value) @trusted pure nothrow
3742 {
3743 const element = getElement(value);
3744
3745 if (const struct_ = cast(const TypeInfo_Struct) element)
3746 return !!struct_.xtoHash;
3747
3748 return cast(const TypeInfo_Array) element
3749 || cast(const TypeInfo_AssociativeArray) element
3750 || cast(const ClassInfo) element
3751 || cast(const TypeInfo_Interface) element;
3752 }
3753
3754 if (!hasCustomToHash(element))
3755 return hashOf(ptr[0 .. elementSize * count]);
3756
3757 size_t hash = 0;
3758 foreach (size_t i; 0 .. count)
3759 hash = hashOf(element.getHash(ptr + i * elementSize), hash);
3760 return hash;
3761 }
3762
3763 /// Provide the .dup array property.
3764 @property auto dup(T)(T[] a)
3765 if (!is(const(T) : T))
3766 {
3767 import core.internal.traits : Unconst;
3768 static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
3769 " to "~Unconst!T.stringof~" in dup.");
3770
3771 return _dup!(T, Unconst!T)(a);
3772 }
3773
3774 ///
3775 @safe unittest
3776 {
3777 auto arr = [1, 2];
3778 auto arr2 = arr.dup;
3779 arr[0] = 0;
3780 assert(arr == [0, 2]);
3781 assert(arr2 == [1, 2]);
3782 }
3783
3784 /// ditto
3785 // const overload to support implicit conversion to immutable (unique result, see DIP29)
3786 @property T[] dup(T)(const(T)[] a)
3787 if (is(const(T) : T))
3788 {
3789 return _dup!(const(T), T)(a);
3790 }
3791
3792
3793 /// Provide the .idup array property.
3794 @property immutable(T)[] idup(T)(T[] a)
3795 {
3796 static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
3797 " to immutable in idup.");
3798 return _dup!(T, immutable(T))(a);
3799 }
3800
3801 /// ditto
3802 @property immutable(T)[] idup(T:void)(const(T)[] a)
3803 {
3804 return a.dup;
3805 }
3806
3807 ///
3808 @safe unittest
3809 {
3810 char[] arr = ['a', 'b', 'c'];
3811 string s = arr.idup;
3812 arr[0] = '.';
3813 assert(s == "abc");
3814 }
3815
3816 private U[] _dup(T, U)(scope T[] a) pure nothrow @trusted if (__traits(isPOD, T))
3817 {
3818 if (__ctfe)
3819 return _dupCtfe!(T, U)(a);
3820
3821 import core.stdc.string : memcpy;
3822 auto arr = _d_newarrayU(typeid(T[]), a.length);
3823 memcpy(arr.ptr, cast(const(void)*) a.ptr, T.sizeof * a.length);
3824 return *cast(U[]*) &arr;
3825 }
3826
3827 private U[] _dupCtfe(T, U)(scope T[] a)
3828 {
3829 static if (is(T : void))
3830 assert(0, "Cannot dup a void[] array at compile time.");
3831 else
3832 {
3833 U[] res;
3834 foreach (ref e; a)
3835 res ~= e;
3836 return res;
3837 }
3838 }
3839
3840 private U[] _dup(T, U)(T[] a) if (!__traits(isPOD, T))
3841 {
3842 // note: copyEmplace is `@system` inside a `@trusted` block, so the __ctfe branch
3843 // has the extra duty to infer _dup `@system` when the copy-constructor is `@system`.
3844 if (__ctfe)
3845 return _dupCtfe!(T, U)(a);
3846
3847 import core.lifetime: copyEmplace;
3848 U[] res = () @trusted {
3849 auto arr = cast(U*) _d_newarrayU(typeid(T[]), a.length);
3850 size_t i;
3851 scope (failure)
3852 {
3853 import core.internal.lifetime: emplaceInitializer;
3854 // Initialize all remaining elements to not destruct garbage
3855 foreach (j; i .. a.length)
3856 emplaceInitializer(cast() arr[j]);
3857 }
3858 for (; i < a.length; i++)
3859 {
3860 copyEmplace(a.ptr[i], arr[i]);
3861 }
3862 return cast(U[])(arr[0..a.length]);
3863 } ();
3864
3865 return res;
3866 }
3867
3868 // https://issues.dlang.org/show_bug.cgi?id=22107
3869 @safe unittest
3870 {
3871 static int i;
3872 @safe struct S
3873 {
3874 this(this) { i++; }
3875 }
3876
3877 void fun(scope S[] values...) @safe
3878 {
3879 values.dup;
3880 }
3881 }
3882
3883 // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is
3884 // necessary for now to prevent breaking code.
3885 private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow;
3886
3887 /**
3888 (Property) Gets the current _capacity of a slice. The _capacity is the size
3889 that the slice can grow to before the underlying array must be
3890 reallocated or extended.
3891
3892 If an append must reallocate a slice with no possibility of extension, then
3893 `0` is returned. This happens when the slice references a static array, or
3894 if another slice references elements past the end of the current slice.
3895
3896 Note: The _capacity of a slice may be impacted by operations on other slices.
3897 */
3898 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
3899 {
3900 return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr);
3901 }
3902
3903 ///
3904 @safe unittest
3905 {
3906 //Static array slice: no capacity
3907 int[4] sarray = [1, 2, 3, 4];
3908 int[] slice = sarray[];
3909 assert(sarray.capacity == 0);
3910 //Appending to slice will reallocate to a new array
3911 slice ~= 5;
3912 assert(slice.capacity >= 5);
3913
3914 //Dynamic array slices
3915 int[] a = [1, 2, 3, 4];
3916 int[] b = a[1 .. $];
3917 int[] c = a[1 .. $ - 1];
3918 debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation
3919 {
3920 assert(a.capacity != 0);
3921 assert(a.capacity == b.capacity + 1); //both a and b share the same tail
3922 }
3923 assert(c.capacity == 0); //an append to c must relocate c.
3924 }
3925
3926 /**
3927 Reserves capacity for a slice. The capacity is the size
3928 that the slice can grow to before the underlying array must be
3929 reallocated or extended.
3930
3931 Returns: The new capacity of the array (which may be larger than
3932 the requested capacity).
3933 */
3934 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
3935 {
3936 if (__ctfe)
3937 return newcapacity;
3938 else
3939 return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr);
3940 }
3941
3942 ///
3943 @safe unittest
3944 {
3945 //Static array slice: no capacity. Reserve relocates.
3946 int[4] sarray = [1, 2, 3, 4];
3947 int[] slice = sarray[];
3948 auto u = slice.reserve(8);
3949 assert(u >= 8);
3950 assert(&sarray[0] !is &slice[0]);
3951 assert(slice.capacity == u);
3952
3953 //Dynamic array slices
3954 int[] a = [1, 2, 3, 4];
3955 a.reserve(8); //prepare a for appending 4 more items
3956 auto p = &a[0];
3957 u = a.capacity;
3958 a ~= [5, 6, 7, 8];
3959 assert(p == &a[0]); //a should not have been reallocated
3960 assert(u == a.capacity); //a should not have been extended
3961 }
3962
3963 // https://issues.dlang.org/show_bug.cgi?id=12330, reserve() at CTFE time
3964 @safe unittest
3965 {
3966 int[] foo() {
3967 int[] result;
3968 auto a = result.reserve = 5;
3969 assert(a == 5);
3970 return result;
3971 }
3972 enum r = foo();
3973 }
3974
3975 // Issue 6646: should be possible to use array.reserve from SafeD.
3976 @safe unittest
3977 {
3978 int[] a;
3979 a.reserve(10);
3980 }
3981
3982 // HACK: This is a lie. `_d_arrayshrinkfit` is not `nothrow`, but this lie is necessary
3983 // for now to prevent breaking code.
3984 private extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow;
3985
3986 /**
3987 Assume that it is safe to append to this array. Appends made to this array
3988 after calling this function may append in place, even if the array was a
3989 slice of a larger array to begin with.
3990
3991 Use this only when it is certain there are no elements in use beyond the
3992 array in the memory block. If there are, those elements will be
3993 overwritten by appending to this array.
3994
3995 Warning: Calling this function, and then using references to data located after the
3996 given array results in undefined behavior.
3997
3998 Returns:
3999 The input is returned.
4000 */
4001 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system
4002 {
4003 _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
4004 return arr;
4005 }
4006
4007 ///
4008 @system unittest
4009 {
4010 int[] a = [1, 2, 3, 4];
4011
4012 // Without assumeSafeAppend. Appending relocates.
4013 int[] b = a [0 .. 3];
4014 b ~= 5;
4015 assert(a.ptr != b.ptr);
4016
4017 debug(SENTINEL) {} else
4018 {
4019 // With assumeSafeAppend. Appending overwrites.
4020 int[] c = a [0 .. 3];
4021 c.assumeSafeAppend() ~= 5;
4022 assert(a.ptr == c.ptr);
4023 }
4024 }
4025
4026 @system unittest
4027 {
4028 int[] arr;
4029 auto newcap = arr.reserve(2000);
4030 assert(newcap >= 2000);
4031 assert(newcap == arr.capacity);
4032 auto ptr = arr.ptr;
4033 foreach (i; 0..2000)
4034 arr ~= i;
4035 assert(ptr == arr.ptr);
4036 arr = arr[0..1];
4037 arr.assumeSafeAppend();
4038 arr ~= 5;
4039 assert(ptr == arr.ptr);
4040 }
4041
4042 @system unittest
4043 {
4044 int[] arr = [1, 2, 3];
4045 void foo(ref int[] i)
4046 {
4047 i ~= 5;
4048 }
4049 arr = arr[0 .. 2];
4050 foo(assumeSafeAppend(arr)); //pass by ref
4051 assert(arr[]==[1, 2, 5]);
4052 arr = arr[0 .. 1].assumeSafeAppend(); //pass by value
4053 }
4054
4055 // https://issues.dlang.org/show_bug.cgi?id=10574
4056 @system unittest
4057 {
4058 int[] a;
4059 immutable(int[]) b;
4060 auto a2 = &assumeSafeAppend(a);
4061 auto b2 = &assumeSafeAppend(b);
4062 auto a3 = assumeSafeAppend(a[]);
4063 auto b3 = assumeSafeAppend(b[]);
4064 assert(is(typeof(*a2) == int[]));
4065 assert(is(typeof(*b2) == immutable(int[])));
4066 assert(is(typeof(a3) == int[]));
4067 assert(is(typeof(b3) == immutable(int[])));
4068 }
4069
4070 private extern (C) void[] _d_newarrayU(const scope TypeInfo ti, size_t length) pure nothrow;
4071
4072 private void _doPostblit(T)(T[] arr)
4073 {
4074 // infer static postblit type, run postblit if any
4075 static if (__traits(hasPostblit, T))
4076 {
4077 static if (__traits(isStaticArray, T) && is(T : E[], E))
4078 _doPostblit(cast(E[]) arr);
4079 else static if (!is(typeof(arr[0].__xpostblit())) && is(immutable T == immutable U, U))
4080 foreach (ref elem; (() @trusted => cast(U[]) arr)())
4081 elem.__xpostblit();
4082 else
4083 foreach (ref elem; arr)
4084 elem.__xpostblit();
4085 }
4086 }
4087
4088 @safe unittest
4089 {
4090 static struct S1 { int* p; }
4091 static struct S2 { @disable this(); }
4092 static struct S3 { @disable this(this); }
4093
4094 int dg1() pure nothrow @safe
4095 {
4096 {
4097 char[] m;
4098 string i;
4099 m = m.dup;
4100 i = i.idup;
4101 m = i.dup;
4102 i = m.idup;
4103 }
4104 {
4105 S1[] m;
4106 immutable(S1)[] i;
4107 m = m.dup;
4108 i = i.idup;
4109 static assert(!is(typeof(m.idup)));
4110 static assert(!is(typeof(i.dup)));
4111 }
4112 {
4113 S3[] m;
4114 immutable(S3)[] i;
4115 static assert(!is(typeof(m.dup)));
4116 static assert(!is(typeof(i.idup)));
4117 }
4118 {
4119 shared(S1)[] m;
4120 m = m.dup;
4121 static assert(!is(typeof(m.idup)));
4122 }
4123 {
4124 int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
4125 }
4126 return 1;
4127 }
4128
4129 int dg2() pure nothrow @safe
4130 {
4131 {
4132 S2[] m = [S2.init, S2.init];
4133 immutable(S2)[] i = [S2.init, S2.init];
4134 m = m.dup;
4135 m = i.dup;
4136 i = m.idup;
4137 i = i.idup;
4138 }
4139 return 2;
4140 }
4141
4142 enum a = dg1();
4143 enum b = dg2();
4144 assert(dg1() == a);
4145 assert(dg2() == b);
4146 }
4147
4148 @system unittest
4149 {
4150 static struct Sunpure { this(this) @safe nothrow {} }
4151 static struct Sthrow { this(this) @safe pure {} }
4152 static struct Sunsafe { this(this) @system pure nothrow {} }
4153 static struct Snocopy { @disable this(this); }
4154
4155 [].dup!Sunpure;
4156 [].dup!Sthrow;
4157 cast(void) [].dup!Sunsafe;
4158 static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
4159 static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
4160 static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
4161 static assert(!__traits(compiles, () { [].dup!Snocopy; }));
4162
4163 [].idup!Sunpure;
4164 [].idup!Sthrow;
4165 [].idup!Sunsafe;
4166 static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
4167 static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
4168 static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
4169 static assert(!__traits(compiles, () { [].idup!Snocopy; }));
4170 }
4171
4172 @safe unittest
4173 {
4174 // test that the copy-constructor is called with .dup
4175 static struct ArrElem
4176 {
4177 int a;
4178 this(int a)
4179 {
4180 this.a = a;
4181 }
4182 this(ref const ArrElem)
4183 {
4184 a = 2;
4185 }
4186 this(ref ArrElem) immutable
4187 {
4188 a = 3;
4189 }
4190 }
4191
4192 auto arr = [ArrElem(1), ArrElem(1)];
4193
4194 ArrElem[] b = arr.dup;
4195 assert(b[0].a == 2 && b[1].a == 2);
4196
4197 immutable ArrElem[] c = arr.idup;
4198 assert(c[0].a == 3 && c[1].a == 3);
4199 }
4200
4201 @system unittest
4202 {
4203 static struct Sunpure { this(ref const typeof(this)) @safe nothrow {} }
4204 static struct Sthrow { this(ref const typeof(this)) @safe pure {} }
4205 static struct Sunsafe { this(ref const typeof(this)) @system pure nothrow {} }
4206 [].dup!Sunpure;
4207 [].dup!Sthrow;
4208 cast(void) [].dup!Sunsafe;
4209 static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
4210 static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
4211 static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
4212
4213 // for idup to work on structs that have copy constructors, it is necessary
4214 // that the struct defines a copy constructor that creates immutable objects
4215 static struct ISunpure { this(ref const typeof(this)) immutable @safe nothrow {} }
4216 static struct ISthrow { this(ref const typeof(this)) immutable @safe pure {} }
4217 static struct ISunsafe { this(ref const typeof(this)) immutable @system pure nothrow {} }
4218 [].idup!ISunpure;
4219 [].idup!ISthrow;
4220 [].idup!ISunsafe;
4221 static assert(!__traits(compiles, () pure { [].idup!ISunpure; }));
4222 static assert(!__traits(compiles, () nothrow { [].idup!ISthrow; }));
4223 static assert(!__traits(compiles, () @safe { [].idup!ISunsafe; }));
4224 }
4225
4226 @safe unittest
4227 {
4228 static int*[] pureFoo() pure { return null; }
4229 { char[] s; immutable x = s.dup; }
4230 { immutable x = (cast(int*[])null).dup; }
4231 { immutable x = pureFoo(); }
4232 { immutable x = pureFoo().dup; }
4233 }
4234
4235 @safe unittest
4236 {
4237 auto a = [1, 2, 3];
4238 auto b = a.dup;
4239 debug(SENTINEL) {} else
4240 assert(b.capacity >= 3);
4241 }
4242
4243 @system unittest
4244 {
4245 // Bugzilla 12580
4246 void[] m = [0];
4247 shared(void)[] s = [cast(shared)1];
4248 immutable(void)[] i = [cast(immutable)2];
4249
4250 s = s.dup;
4251 static assert(is(typeof(s.dup) == shared(void)[]));
4252
4253 m = i.dup;
4254 i = m.dup;
4255 i = i.idup;
4256 i = m.idup;
4257 i = s.idup;
4258 i = s.dup;
4259 static assert(!__traits(compiles, m = s.dup));
4260 }
4261
4262 @safe unittest
4263 {
4264 // Bugzilla 13809
4265 static struct S
4266 {
4267 this(this) {}
4268 ~this() {}
4269 }
4270
4271 S[] arr;
4272 auto a = arr.dup;
4273 }
4274
4275 @system unittest
4276 {
4277 // Bugzilla 16504
4278 static struct S
4279 {
4280 __gshared int* gp;
4281 int* p;
4282 // postblit and hence .dup could escape
4283 this(this) { gp = p; }
4284 }
4285
4286 int p;
4287 scope S[1] arr = [S(&p)];
4288 auto a = arr.dup; // dup does escape
4289 }
4290
4291 // https://issues.dlang.org/show_bug.cgi?id=21983
4292 // dup/idup destroys partially constructed arrays on failure
4293 @safe unittest
4294 {
4295 static struct SImpl(bool postblit)
4296 {
4297 int num;
4298 long l = 0xDEADBEEF;
4299
4300 static if (postblit)
4301 {
4302 this(this)
4303 {
4304 if (this.num == 3)
4305 throw new Exception("");
4306 }
4307 }
4308 else
4309 {
4310 this(scope ref const SImpl other)
4311 {
4312 if (other.num == 3)
4313 throw new Exception("");
4314
4315 this.num = other.num;
4316 this.l = other.l;
4317 }
4318 }
4319
4320 ~this() @trusted
4321 {
4322 if (l != 0xDEADBEEF)
4323 {
4324 import core.stdc.stdio;
4325 printf("Unexpected value: %lld\n", l);
4326 fflush(stdout);
4327 assert(false);
4328 }
4329 }
4330 }
4331
4332 alias Postblit = SImpl!true;
4333 alias Copy = SImpl!false;
4334
4335 static int test(S)()
4336 {
4337 S[4] arr = [ S(1), S(2), S(3), S(4) ];
4338 try
4339 {
4340 arr.dup();
4341 assert(false);
4342 }
4343 catch (Exception)
4344 {
4345 return 1;
4346 }
4347 }
4348
4349 static assert(test!Postblit());
4350 assert(test!Postblit());
4351
4352 static assert(test!Copy());
4353 assert(test!Copy());
4354 }
4355
4356 /**
4357 Destroys the given object and optionally resets to initial state. It's used to
4358 _destroy an object, calling its destructor or finalizer so it no longer
4359 references any other objects. It does $(I not) initiate a GC cycle or free
4360 any GC memory.
4361 If `initialize` is supplied `false`, the object is considered invalid after
4362 destruction, and should not be referenced.
4363 */
4364 void destroy(bool initialize = true, T)(ref T obj) if (is(T == struct))
4365 {
4366 import core.internal.destruction : destructRecurse;
4367
4368 destructRecurse(obj);
4369
4370 static if (initialize)
4371 {
4372 import core.internal.lifetime : emplaceInitializer;
4373 emplaceInitializer(obj); // emplace T.init
4374 }
4375 }
4376
4377 @safe unittest
4378 {
4379 struct A { string s = "A"; }
4380 A a = {s: "B"};
4381 assert(a.s == "B");
4382 a.destroy;
4383 assert(a.s == "A");
4384 }
4385
4386 nothrow @safe @nogc unittest
4387 {
4388 {
4389 struct A { string s = "A"; }
4390 A a;
4391 a.s = "asd";
4392 destroy!false(a);
4393 assert(a.s == "asd");
4394 destroy(a);
4395 assert(a.s == "A");
4396 }
4397 {
4398 static int destroyed = 0;
4399 struct C
4400 {
4401 string s = "C";
4402 ~this() nothrow @safe @nogc
4403 {
4404 destroyed ++;
4405 }
4406 }
4407
4408 struct B
4409 {
4410 C c;
4411 string s = "B";
4412 ~this() nothrow @safe @nogc
4413 {
4414 destroyed ++;
4415 }
4416 }
4417 B a;
4418 a.s = "asd";
4419 a.c.s = "jkl";
4420 destroy!false(a);
4421 assert(destroyed == 2);
4422 assert(a.s == "asd");
4423 assert(a.c.s == "jkl" );
4424 destroy(a);
4425 assert(destroyed == 4);
4426 assert(a.s == "B");
4427 assert(a.c.s == "C" );
4428 }
4429 }
4430
4431 private extern (C) void rt_finalize(void *data, bool det=true) nothrow;
4432
4433 /// ditto
4434 void destroy(bool initialize = true, T)(T obj) if (is(T == class))
4435 {
4436 static if (__traits(getLinkage, T) == "C++")
4437 {
4438 static if (__traits(hasMember, T, "__xdtor"))
4439 obj.__xdtor();
4440
4441 static if (initialize)
4442 {
4443 const initializer = __traits(initSymbol, T);
4444 (cast(void*)obj)[0 .. initializer.length] = initializer[];
4445 }
4446 }
4447 else
4448 {
4449 // Bypass overloaded opCast
4450 auto ptr = (() @trusted => *cast(void**) &obj)();
4451 rt_finalize(ptr);
4452 }
4453 }
4454
4455 /// ditto
4456 void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
4457 {
4458 static assert(__traits(getLinkage, T) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage, T) ~ ") interface");
4459
4460 destroy!initialize(cast(Object)obj);
4461 }
4462
4463 /// Reference type demonstration
4464 @system unittest
4465 {
4466 class C
4467 {
4468 struct Agg
4469 {
4470 static int dtorCount;
4471
4472 int x = 10;
4473 ~this() { dtorCount++; }
4474 }
4475
4476 static int dtorCount;
4477
4478 string s = "S";
4479 Agg a;
4480 ~this() { dtorCount++; }
4481 }
4482
4483 C c = new C();
4484 assert(c.dtorCount == 0); // destructor not yet called
4485 assert(c.s == "S"); // initial state `c.s` is `"S"`
4486 assert(c.a.dtorCount == 0); // destructor not yet called
4487 assert(c.a.x == 10); // initial state `c.a.x` is `10`
4488 c.s = "T";
4489 c.a.x = 30;
4490 assert(c.s == "T"); // `c.s` is `"T"`
4491 destroy(c);
4492 assert(c.dtorCount == 1); // `c`'s destructor was called
4493 assert(c.s == "S"); // `c.s` is back to its inital state, `"S"`
4494 assert(c.a.dtorCount == 1); // `c.a`'s destructor was called
4495 assert(c.a.x == 10); // `c.a.x` is back to its inital state, `10`
4496
4497 // check C++ classes work too!
4498 extern (C++) class CPP
4499 {
4500 struct Agg
4501 {
4502 __gshared int dtorCount;
4503
4504 int x = 10;
4505 ~this() { dtorCount++; }
4506 }
4507
4508 __gshared int dtorCount;
4509
4510 string s = "S";
4511 Agg a;
4512 ~this() { dtorCount++; }
4513 }
4514
4515 CPP cpp = new CPP();
4516 assert(cpp.dtorCount == 0); // destructor not yet called
4517 assert(cpp.s == "S"); // initial state `cpp.s` is `"S"`
4518 assert(cpp.a.dtorCount == 0); // destructor not yet called
4519 assert(cpp.a.x == 10); // initial state `cpp.a.x` is `10`
4520 cpp.s = "T";
4521 cpp.a.x = 30;
4522 assert(cpp.s == "T"); // `cpp.s` is `"T"`
4523 destroy!false(cpp); // destroy without initialization
4524 assert(cpp.dtorCount == 1); // `cpp`'s destructor was called
4525 assert(cpp.s == "T"); // `cpp.s` is not initialized
4526 assert(cpp.a.dtorCount == 1); // `cpp.a`'s destructor was called
4527 assert(cpp.a.x == 30); // `cpp.a.x` is not initialized
4528 destroy(cpp);
4529 assert(cpp.dtorCount == 2); // `cpp`'s destructor was called again
4530 assert(cpp.s == "S"); // `cpp.s` is back to its inital state, `"S"`
4531 assert(cpp.a.dtorCount == 2); // `cpp.a`'s destructor was called again
4532 assert(cpp.a.x == 10); // `cpp.a.x` is back to its inital state, `10`
4533 }
4534
4535 /// Value type demonstration
4536 @safe unittest
4537 {
4538 int i;
4539 assert(i == 0); // `i`'s initial state is `0`
4540 i = 1;
4541 assert(i == 1); // `i` changed to `1`
4542 destroy!false(i);
4543 assert(i == 1); // `i` was not initialized
4544 destroy(i);
4545 assert(i == 0); // `i` is back to its initial state `0`
4546 }
4547
4548 @system unittest
4549 {
4550 extern(C++)
4551 static class C
4552 {
4553 void* ptr;
4554 this() {}
4555 }
4556
4557 destroy!false(new C());
4558 destroy!true(new C());
4559 }
4560
4561 @system unittest
4562 {
4563 // class with an `alias this`
4564 class A
4565 {
4566 static int dtorCount;
4567 ~this()
4568 {
4569 dtorCount++;
4570 }
4571 }
4572
4573 class B
4574 {
4575 A a;
4576 alias a this;
4577 this()
4578 {
4579 a = new A;
4580 }
4581 static int dtorCount;
4582 ~this()
4583 {
4584 dtorCount++;
4585 }
4586 }
4587 auto b = new B;
4588 assert(A.dtorCount == 0);
4589 assert(B.dtorCount == 0);
4590 destroy(b);
4591 assert(A.dtorCount == 0);
4592 assert(B.dtorCount == 1);
4593
4594 auto a = new A;
4595 destroy(a);
4596 assert(A.dtorCount == 1);
4597 }
4598
4599 @system unittest
4600 {
4601 interface I { }
4602 {
4603 class A: I { string s = "A"; this() {} }
4604 auto a = new A, b = new A;
4605 a.s = b.s = "asd";
4606 destroy(a);
4607 assert(a.s == "A");
4608
4609 I i = b;
4610 destroy(i);
4611 assert(b.s == "A");
4612 }
4613 {
4614 static bool destroyed = false;
4615 class B: I
4616 {
4617 string s = "B";
4618 this() {}
4619 ~this()
4620 {
4621 destroyed = true;
4622 }
4623 }
4624 auto a = new B, b = new B;
4625 a.s = b.s = "asd";
4626 destroy(a);
4627 assert(destroyed);
4628 assert(a.s == "B");
4629
4630 destroyed = false;
4631 I i = b;
4632 destroy(i);
4633 assert(destroyed);
4634 assert(b.s == "B");
4635 }
4636 // this test is invalid now that the default ctor is not run after clearing
4637 version (none)
4638 {
4639 class C
4640 {
4641 string s;
4642 this()
4643 {
4644 s = "C";
4645 }
4646 }
4647 auto a = new C;
4648 a.s = "asd";
4649 destroy(a);
4650 assert(a.s == "C");
4651 }
4652 }
4653
4654 nothrow @safe @nogc unittest
4655 {
4656 {
4657 struct A { string s = "A"; }
4658 A a;
4659 a.s = "asd";
4660 destroy!false(a);
4661 assert(a.s == "asd");
4662 destroy(a);
4663 assert(a.s == "A");
4664 }
4665 {
4666 static int destroyed = 0;
4667 struct C
4668 {
4669 string s = "C";
4670 ~this() nothrow @safe @nogc
4671 {
4672 destroyed ++;
4673 }
4674 }
4675
4676 struct B
4677 {
4678 C c;
4679 string s = "B";
4680 ~this() nothrow @safe @nogc
4681 {
4682 destroyed ++;
4683 }
4684 }
4685 B a;
4686 a.s = "asd";
4687 a.c.s = "jkl";
4688 destroy!false(a);
4689 assert(destroyed == 2);
4690 assert(a.s == "asd");
4691 assert(a.c.s == "jkl" );
4692 destroy(a);
4693 assert(destroyed == 4);
4694 assert(a.s == "B");
4695 assert(a.c.s == "C" );
4696 }
4697 }
4698
4699 nothrow unittest
4700 {
4701 // Bugzilla 20049: Test to ensure proper behavior of `nothrow` destructors
4702 class C
4703 {
4704 static int dtorCount = 0;
4705 this() nothrow {}
4706 ~this() nothrow { dtorCount++; }
4707 }
4708
4709 auto c = new C;
4710 destroy(c);
4711 assert(C.dtorCount == 1);
4712 }
4713
4714 // https://issues.dlang.org/show_bug.cgi?id=22832
4715 nothrow unittest
4716 {
4717 static struct A {}
4718 static class B
4719 {
4720 A opCast(T : A)() { return A(); }
4721 }
4722
4723 destroy(B.init);
4724 }
4725
4726 /// ditto
4727 void destroy(bool initialize = true, T)(ref T obj)
4728 if (__traits(isStaticArray, T))
4729 {
4730 foreach_reverse (ref e; obj[])
4731 destroy!initialize(e);
4732 }
4733
4734 @safe unittest
4735 {
4736 int[2] a;
4737 a[0] = 1;
4738 a[1] = 2;
4739 destroy!false(a);
4740 assert(a == [ 1, 2 ]);
4741 destroy(a);
4742 assert(a == [ 0, 0 ]);
4743 }
4744
4745 @safe unittest
4746 {
4747 static struct vec2f {
4748 float[2] values;
4749 alias values this;
4750 }
4751
4752 vec2f v;
4753 destroy!(true, vec2f)(v);
4754 }
4755
4756 @system unittest
4757 {
4758 // Bugzilla 15009
4759 static string op;
4760 static struct S
4761 {
4762 int x;
4763 this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; }
4764 this(this) { op ~= "P" ~ cast(char)('0'+x); }
4765 ~this() { op ~= "D" ~ cast(char)('0'+x); }
4766 }
4767
4768 {
4769 S[2] a1 = [S(1), S(2)];
4770 op = "";
4771 }
4772 assert(op == "D2D1"); // built-in scope destruction
4773 {
4774 S[2] a1 = [S(1), S(2)];
4775 op = "";
4776 destroy(a1);
4777 assert(op == "D2D1"); // consistent with built-in behavior
4778 }
4779
4780 {
4781 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
4782 op = "";
4783 }
4784 assert(op == "D4D3D2D1");
4785 {
4786 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
4787 op = "";
4788 destroy(a2);
4789 assert(op == "D4D3D2D1", op);
4790 }
4791 }
4792
4793 // https://issues.dlang.org/show_bug.cgi?id=19218
4794 @system unittest
4795 {
4796 static struct S
4797 {
4798 static dtorCount = 0;
4799 ~this() { ++dtorCount; }
4800 }
4801
4802 static interface I
4803 {
4804 ref S[3] getArray();
4805 alias getArray this;
4806 }
4807
4808 static class C : I
4809 {
4810 static dtorCount = 0;
4811 ~this() { ++dtorCount; }
4812
4813 S[3] a;
4814 alias a this;
4815
4816 ref S[3] getArray() { return a; }
4817 }
4818
4819 C c = new C();
4820 destroy(c);
4821 assert(S.dtorCount == 3);
4822 assert(C.dtorCount == 1);
4823
4824 I i = new C();
4825 destroy(i);
4826 assert(S.dtorCount == 6);
4827 assert(C.dtorCount == 2);
4828 }
4829
4830 /// ditto
4831 void destroy(bool initialize = true, T)(ref T obj)
4832 if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T))
4833 {
4834 static if (initialize)
4835 obj = T.init;
4836 }
4837
4838 @safe unittest
4839 {
4840 {
4841 int a = 42;
4842 destroy!false(a);
4843 assert(a == 42);
4844 destroy(a);
4845 assert(a == 0);
4846 }
4847 {
4848 float a = 42;
4849 destroy!false(a);
4850 assert(a == 42);
4851 destroy(a);
4852 assert(a != a); // isnan
4853 }
4854 }
4855
4856 @safe unittest
4857 {
4858 // Bugzilla 14746
4859 static struct HasDtor
4860 {
4861 ~this() { assert(0); }
4862 }
4863 static struct Owner
4864 {
4865 HasDtor* ptr;
4866 alias ptr this;
4867 }
4868
4869 Owner o;
4870 assert(o.ptr is null);
4871 destroy(o); // must not reach in HasDtor.__dtor()
4872 }
4873
4874 /* ************************************************************************
4875 COMPILER SUPPORT
4876 The compiler lowers certain expressions to instantiations of the following
4877 templates. They must be implicitly imported, which is why they are here
4878 in this file. They must also be `public` as they must be visible from the
4879 scope in which they are instantiated. They are explicitly undocumented as
4880 they are only intended to be instantiated by the compiler, not the user.
4881 **************************************************************************/
4882
4883 public import core.internal.entrypoint : _d_cmain;
4884
4885 public import core.internal.array.appending : _d_arrayappendTImpl;
4886 public import core.internal.array.appending : _d_arrayappendcTXImpl;
4887 public import core.internal.array.comparison : __cmp;
4888 public import core.internal.array.equality : __equals;
4889 public import core.internal.array.casting: __ArrayCast;
4890 public import core.internal.array.concatenation : _d_arraycatnTXImpl;
4891 public import core.internal.array.construction : _d_arrayctor;
4892 public import core.internal.array.construction : _d_arraysetctor;
4893 public import core.internal.array.capacity: _d_arraysetlengthTImpl;
4894
4895 public import core.internal.dassert: _d_assert_fail;
4896
4897 public import core.internal.destruction: __ArrayDtor;
4898
4899 public import core.internal.moving: __move_post_blt;
4900
4901 public import core.internal.postblit: __ArrayPostblit;
4902
4903 public import core.internal.switch_: __switch;
4904 public import core.internal.switch_: __switch_error;
4905
4906 public import core.lifetime : _d_delstructImpl;
4907 public import core.lifetime : _d_newThrowable;
4908
4909 public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable);
4910
4911 // Compare class and interface objects for ordering.
4912 int __cmp(C1, C2)(C1 lhs, C2 rhs)
4913 if ((is(C1 : const(Object)) || (is(C1 == interface) && (__traits(getLinkage, C1) == "D"))) &&
4914 (is(C2 : const(Object)) || (is(C2 == interface) && (__traits(getLinkage, C2) == "D"))))
4915 {
4916 static if (is(C1 == typeof(null)) && is(C2 == typeof(null)))
4917 {
4918 return 0;
4919 }
4920 else static if (is(C1 == typeof(null)))
4921 {
4922 // Regard null references as always being "less than"
4923 return -1;
4924 }
4925 else static if (is(C2 == typeof(null)))
4926 {
4927 return 1;
4928 }
4929 else
4930 {
4931 if (lhs is rhs)
4932 return 0;
4933 if (lhs is null)
4934 return -1;
4935 if (rhs is null)
4936 return 1;
4937 return lhs.opCmp(rhs);
4938 }
4939 }
4940
4941 // objects
4942 @safe unittest
4943 {
4944 class C
4945 {
4946 int i;
4947 this(int i) { this.i = i; }
4948
4949 override int opCmp(Object c) const @safe
4950 {
4951 return i - (cast(C)c).i;
4952 }
4953 }
4954
4955 auto c1 = new C(1);
4956 auto c2 = new C(2);
4957 assert(__cmp(c1, null) > 0);
4958 assert(__cmp(null, c1) < 0);
4959 assert(__cmp(c1, c1) == 0);
4960 assert(__cmp(c1, c2) < 0);
4961 assert(__cmp(c2, c1) > 0);
4962
4963 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
4964 assert(__cmp([c2, c2], [c1, c1]) > 0);
4965 }
4966
4967 // structs
4968 @safe unittest
4969 {
4970 struct C
4971 {
4972 ubyte i;
4973 this(ubyte i) { this.i = i; }
4974 }
4975
4976 auto c1 = C(1);
4977 auto c2 = C(2);
4978
4979 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
4980 assert(__cmp([c2, c2], [c1, c1]) > 0);
4981 assert(__cmp([c2, c2], [c2, c1]) > 0);
4982 }
4983
4984 @safe unittest
4985 {
4986 auto a = "hello"c;
4987
4988 assert(a > "hel");
4989 assert(a >= "hel");
4990 assert(a < "helloo");
4991 assert(a <= "helloo");
4992 assert(a > "betty");
4993 assert(a >= "betty");
4994 assert(a == "hello");
4995 assert(a <= "hello");
4996 assert(a >= "hello");
4997 assert(a < "я");
4998 }
4999
5000 // Used in Exception Handling LSDA tables to 'wrap' C++ type info
5001 // so it can be distinguished from D TypeInfo
5002 class __cpp_type_info_ptr
5003 {
5004 void* ptr; // opaque pointer to C++ RTTI type info
5005 }
5006
5007 // Compiler hook into the runtime implementation of array (vector) operations.
5008 template _arrayOp(Args...)
5009 {
5010 import core.internal.array.operations;
5011 alias _arrayOp = arrayOp!Args;
5012 }
5013
5014 public import core.builtins : __ctfeWrite;
5015
5016 /**
5017
5018 Provides an "inline import", i.e. an `import` that is only available for a
5019 limited lookup. For example:
5020
5021 ---
5022 void fun(imported!"std.stdio".File input)
5023 {
5024 ... use File from std.stdio normally ...
5025 }
5026 ---
5027
5028 There is no need to import `std.stdio` at top level, so `fun` carries its own
5029 dependencies. The same approach can be used for template constraints:
5030
5031 ---
5032 void fun(T)(imported!"std.stdio".File input, T value)
5033 if (imported!"std.traits".isIntegral!T)
5034 {
5035 ...
5036 }
5037 ---
5038
5039 An inline import may be used in conjunction with the `with` statement as well.
5040 Inside the scope controlled by `with`, all symbols in the imported module are
5041 made available:
5042
5043 ---
5044 void fun()
5045 {
5046 with (imported!"std.datetime")
5047 with (imported!"std.stdio")
5048 {
5049 Clock.currTime.writeln;
5050 }
5051 }
5052 ---
5053
5054 The advantages of inline imports over top-level uses of the `import` declaration
5055 are the following:
5056
5057 $(UL
5058 $(LI The `imported` template specifies dependencies at declaration level, not at
5059 module level. This allows reasoning about the dependency cost of declarations in
5060 separation instead of aggregated at module level.)
5061 $(LI Declarations using `imported` are easier to move around because they don't
5062 require top-level context, making for simpler and quicker refactorings.)
5063 $(LI Declarations using `imported` scale better with templates. This is because
5064 templates that are not instantiated do not have their parameters and constraints
5065 instantiated, so additional modules are not imported without necessity. This
5066 makes the cost of unused templates negligible. Dependencies are pulled on a need
5067 basis depending on the declarations used by client code.)
5068 )
5069
5070 The use of `imported` also has drawbacks:
5071
5072 $(UL
5073 $(LI If most declarations in a module need the same imports, then factoring them
5074 at top level, outside the declarations, is simpler than repeating them.)
5075 $(LI Traditional dependency-tracking tools such as make and other build systems
5076 assume file-level dependencies and need special tooling (such as rdmd) in order
5077 to work efficiently.)
5078 $(LI Dependencies at the top of a module are easier to inspect quickly than
5079 dependencies spread throughout the module.)
5080 )
5081
5082 See_Also: The $(HTTP forum.dlang.org/post/tzqzmqhankrkbrfsrmbo@forum.dlang.org,
5083 forum discussion) that led to the creation of the `imported` facility. Credit is
5084 due to Daniel Nielsen and Dominikus Dittes Scherkl.
5085
5086 */
5087 template imported(string moduleName)
5088 {
5089 mixin("import imported = " ~ moduleName ~ ";");
5090 }
5091