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