]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/libdruntime/object.d
PR d/90079
[thirdparty/gcc.git] / libphobos / libdruntime / object.d
1 /**
2 * Forms the symbols available to all D programs. Includes Object, which is
3 * the root of the class object hierarchy. This module is implicitly
4 * imported.
5 *
6 * Copyright: Copyright Digital Mars 2000 - 2011.
7 * License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
8 * Authors: Walter Bright, Sean Kelly
9 */
10
11 module object;
12
13 private
14 {
15 extern (C) Object _d_newclass(const TypeInfo_Class ci);
16 extern (C) void rt_finalize(void *data, bool det=true);
17 }
18
19 // NOTE: For some reason, this declaration method doesn't work
20 // in this particular file (and this file only). It must
21 // be a DMD thing.
22 //alias typeof(int.sizeof) size_t;
23 //alias typeof(cast(void*)0 - cast(void*)0) ptrdiff_t;
24
25 version (D_LP64)
26 {
27 alias size_t = ulong;
28 alias ptrdiff_t = long;
29 }
30 else
31 {
32 alias size_t = uint;
33 alias ptrdiff_t = int;
34 }
35
36 alias sizediff_t = ptrdiff_t; //For backwards compatibility only.
37
38 alias hash_t = size_t; //For backwards compatibility only.
39 alias equals_t = bool; //For backwards compatibility only.
40
41 alias string = immutable(char)[];
42 alias wstring = immutable(wchar)[];
43 alias dstring = immutable(dchar)[];
44
45 version (D_ObjectiveC) public import core.attribute : selector;
46
47 /**
48 * All D class objects inherit from Object.
49 */
50 class Object
51 {
52 /**
53 * Convert Object to a human readable string.
54 */
55 string toString()
56 {
57 return typeid(this).name;
58 }
59
60 /**
61 * Compute hash function for Object.
62 */
63 size_t toHash() @trusted nothrow
64 {
65 // BUG: this prevents a compacting GC from working, needs to be fixed
66 size_t addr = cast(size_t) cast(void*) this;
67 // The bottom log2((void*).alignof) bits of the address will always
68 // be 0. Moreover it is likely that each Object is allocated with a
69 // separate call to malloc. The alignment of malloc differs from
70 // platform to platform, but rather than having special cases for
71 // each platform it is safe to use a shift of 4. To minimize
72 // collisions in the low bits it is more important for the shift to
73 // not be too small than for the shift to not be too big.
74 return addr ^ (addr >>> 4);
75 }
76
77 /**
78 * Compare with another Object obj.
79 * Returns:
80 * $(TABLE
81 * $(TR $(TD this < obj) $(TD < 0))
82 * $(TR $(TD this == obj) $(TD 0))
83 * $(TR $(TD this > obj) $(TD > 0))
84 * )
85 */
86 int opCmp(Object o)
87 {
88 // BUG: this prevents a compacting GC from working, needs to be fixed
89 //return cast(int)cast(void*)this - cast(int)cast(void*)o;
90
91 throw new Exception("need opCmp for class " ~ typeid(this).name);
92 //return this !is o;
93 }
94
95 /**
96 * Test whether $(D this) is equal to $(D o).
97 * The default implementation only compares by identity (using the $(D is) operator).
98 * Generally, overrides for $(D opEquals) should attempt to compare objects by their contents.
99 */
100 bool opEquals(Object o)
101 {
102 return this is o;
103 }
104
105 interface Monitor
106 {
107 void lock();
108 void unlock();
109 }
110
111 /**
112 * Create instance of class specified by the fully qualified name
113 * classname.
114 * The class must either have no constructors or have
115 * a default constructor.
116 * Returns:
117 * null if failed
118 * Example:
119 * ---
120 * module foo.bar;
121 *
122 * class C
123 * {
124 * this() { x = 10; }
125 * int x;
126 * }
127 *
128 * void main()
129 * {
130 * auto c = cast(C)Object.factory("foo.bar.C");
131 * assert(c !is null && c.x == 10);
132 * }
133 * ---
134 */
135 static Object factory(string classname)
136 {
137 auto ci = TypeInfo_Class.find(classname);
138 if (ci)
139 {
140 return ci.create();
141 }
142 return null;
143 }
144 }
145
146 auto opEquals(Object lhs, Object rhs)
147 {
148 // If aliased to the same object or both null => equal
149 if (lhs is rhs) return true;
150
151 // If either is null => non-equal
152 if (lhs is null || rhs is null) return false;
153
154 // If same exact type => one call to method opEquals
155 if (typeid(lhs) is typeid(rhs) ||
156 !__ctfe && typeid(lhs).opEquals(typeid(rhs)))
157 /* CTFE doesn't like typeid much. 'is' works, but opEquals doesn't
158 (issue 7147). But CTFE also guarantees that equal TypeInfos are
159 always identical. So, no opEquals needed during CTFE. */
160 {
161 return lhs.opEquals(rhs);
162 }
163
164 // General case => symmetric calls to method opEquals
165 return lhs.opEquals(rhs) && rhs.opEquals(lhs);
166 }
167
168 /************************
169 * Returns true if lhs and rhs are equal.
170 */
171 auto opEquals(const Object lhs, const Object rhs)
172 {
173 // A hack for the moment.
174 return opEquals(cast()lhs, cast()rhs);
175 }
176
177 private extern(C) void _d_setSameMutex(shared Object ownee, shared Object owner) nothrow;
178
179 void setSameMutex(shared Object ownee, shared Object owner)
180 {
181 _d_setSameMutex(ownee, owner);
182 }
183
184 /**
185 * Information about an interface.
186 * When an object is accessed via an interface, an Interface* appears as the
187 * first entry in its vtbl.
188 */
189 struct Interface
190 {
191 TypeInfo_Class classinfo; /// .classinfo for this interface (not for containing class)
192 void*[] vtbl;
193 size_t offset; /// offset to Interface 'this' from Object 'this'
194 }
195
196 /**
197 * Array of pairs giving the offset and type information for each
198 * member in an aggregate.
199 */
200 struct OffsetTypeInfo
201 {
202 size_t offset; /// Offset of member from start of object
203 TypeInfo ti; /// TypeInfo for this member
204 }
205
206 /**
207 * Runtime type information about a type.
208 * Can be retrieved for any type using a
209 * $(GLINK2 expression,TypeidExpression, TypeidExpression).
210 */
211 class TypeInfo
212 {
213 override string toString() const pure @safe nothrow
214 {
215 return typeid(this).name;
216 }
217
218 override size_t toHash() @trusted const nothrow
219 {
220 return hashOf(this.toString());
221 }
222
223 override int opCmp(Object o)
224 {
225 import core.internal.traits : externDFunc;
226 alias dstrcmp = externDFunc!("core.internal.string.dstrcmp",
227 int function(scope const char[] s1, scope const char[] s2) @trusted pure nothrow @nogc);
228
229 if (this is o)
230 return 0;
231 TypeInfo ti = cast(TypeInfo)o;
232 if (ti is null)
233 return 1;
234 return dstrcmp(this.toString(), ti.toString());
235 }
236
237 override bool opEquals(Object o)
238 {
239 /* TypeInfo instances are singletons, but duplicates can exist
240 * across DLL's. Therefore, comparing for a name match is
241 * sufficient.
242 */
243 if (this is o)
244 return true;
245 auto ti = cast(const TypeInfo)o;
246 return ti && this.toString() == ti.toString();
247 }
248
249 /**
250 * Computes a hash of the instance of a type.
251 * Params:
252 * p = pointer to start of instance of the type
253 * Returns:
254 * the hash
255 * Bugs:
256 * fix https://issues.dlang.org/show_bug.cgi?id=12516 e.g. by changing this to a truly safe interface.
257 */
258 size_t getHash(scope const void* p) @trusted nothrow const
259 {
260 return hashOf(p);
261 }
262
263 /// Compares two instances for equality.
264 bool equals(in void* p1, in void* p2) const { return p1 == p2; }
265
266 /// Compares two instances for <, ==, or >.
267 int compare(in void* p1, in void* p2) const { return _xopCmp(p1, p2); }
268
269 /// Returns size of the type.
270 @property size_t tsize() nothrow pure const @safe @nogc { return 0; }
271
272 /// Swaps two instances of the type.
273 void swap(void* p1, void* p2) const
274 {
275 immutable size_t n = tsize;
276 for (size_t i = 0; i < n; i++)
277 {
278 byte t = (cast(byte *)p1)[i];
279 (cast(byte*)p1)[i] = (cast(byte*)p2)[i];
280 (cast(byte*)p2)[i] = t;
281 }
282 }
283
284 /** Get TypeInfo for 'next' type, as defined by what kind of type this is,
285 null if none. */
286 @property inout(TypeInfo) next() nothrow pure inout @nogc { return null; }
287
288 /**
289 * Return default initializer. If the type should be initialized to all
290 * zeros, an array with a null ptr and a length equal to the type size will
291 * be returned. For static arrays, this returns the default initializer for
292 * a single element of the array, use `tsize` to get the correct size.
293 */
294 abstract const(void)[] initializer() nothrow pure const @safe @nogc;
295
296 /** Get flags for type: 1 means GC should scan for pointers,
297 2 means arg of this type is passed in XMM register */
298 @property uint flags() nothrow pure const @safe @nogc { return 0; }
299
300 /// Get type information on the contents of the type; null if not available
301 const(OffsetTypeInfo)[] offTi() const { return null; }
302 /// Run the destructor on the object and all its sub-objects
303 void destroy(void* p) const {}
304 /// Run the postblit on the object and all its sub-objects
305 void postblit(void* p) const {}
306
307
308 /// Return alignment of type
309 @property size_t talign() nothrow pure const @safe @nogc { return tsize; }
310
311 /** Return internal info on arguments fitting into 8byte.
312 * See X86-64 ABI 3.2.3
313 */
314 version (X86_64) int argTypes(out TypeInfo arg1, out TypeInfo arg2) @safe nothrow
315 {
316 arg1 = this;
317 return 0;
318 }
319
320 /** Return info used by the garbage collector to do precise collection.
321 */
322 @property immutable(void)* rtInfo() nothrow pure const @safe @nogc { return null; }
323 }
324
325 class TypeInfo_Enum : TypeInfo
326 {
327 override string toString() const { return name; }
328
329 override bool opEquals(Object o)
330 {
331 if (this is o)
332 return true;
333 auto c = cast(const TypeInfo_Enum)o;
334 return c && this.name == c.name &&
335 this.base == c.base;
336 }
337
338 override size_t getHash(scope const void* p) const { return base.getHash(p); }
339 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
340 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
341 override @property size_t tsize() nothrow pure const { return base.tsize; }
342 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
343
344 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
345 override @property uint flags() nothrow pure const { return base.flags; }
346
347 override const(void)[] initializer() const
348 {
349 return m_init.length ? m_init : base.initializer();
350 }
351
352 override @property size_t talign() nothrow pure const { return base.talign; }
353
354 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
355 {
356 return base.argTypes(arg1, arg2);
357 }
358
359 override @property immutable(void)* rtInfo() const { return base.rtInfo; }
360
361 TypeInfo base;
362 string name;
363 void[] m_init;
364 }
365
366 unittest // issue 12233
367 {
368 static assert(is(typeof(TypeInfo.init) == TypeInfo));
369 assert(TypeInfo.init is null);
370 }
371
372
373 // Please make sure to keep this in sync with TypeInfo_P (src/rt/typeinfo/ti_ptr.d)
374 class TypeInfo_Pointer : TypeInfo
375 {
376 override string toString() const { return m_next.toString() ~ "*"; }
377
378 override bool opEquals(Object o)
379 {
380 if (this is o)
381 return true;
382 auto c = cast(const TypeInfo_Pointer)o;
383 return c && this.m_next == c.m_next;
384 }
385
386 override size_t getHash(scope const void* p) @trusted const
387 {
388 size_t addr = cast(size_t) *cast(const void**)p;
389 return addr ^ (addr >> 4);
390 }
391
392 override bool equals(in void* p1, in void* p2) const
393 {
394 return *cast(void**)p1 == *cast(void**)p2;
395 }
396
397 override int compare(in void* p1, in void* p2) const
398 {
399 if (*cast(void**)p1 < *cast(void**)p2)
400 return -1;
401 else if (*cast(void**)p1 > *cast(void**)p2)
402 return 1;
403 else
404 return 0;
405 }
406
407 override @property size_t tsize() nothrow pure const
408 {
409 return (void*).sizeof;
410 }
411
412 override const(void)[] initializer() const @trusted
413 {
414 return (cast(void *)null)[0 .. (void*).sizeof];
415 }
416
417 override void swap(void* p1, void* p2) const
418 {
419 void* tmp = *cast(void**)p1;
420 *cast(void**)p1 = *cast(void**)p2;
421 *cast(void**)p2 = tmp;
422 }
423
424 override @property inout(TypeInfo) next() nothrow pure inout { return m_next; }
425 override @property uint flags() nothrow pure const { return 1; }
426
427 TypeInfo m_next;
428 }
429
430 class TypeInfo_Array : TypeInfo
431 {
432 override string toString() const { return value.toString() ~ "[]"; }
433
434 override bool opEquals(Object o)
435 {
436 if (this is o)
437 return true;
438 auto c = cast(const TypeInfo_Array)o;
439 return c && this.value == c.value;
440 }
441
442 override size_t getHash(scope const void* p) @trusted const
443 {
444 void[] a = *cast(void[]*)p;
445 return getArrayHash(value, a.ptr, a.length);
446 }
447
448 override bool equals(in void* p1, in void* p2) const
449 {
450 void[] a1 = *cast(void[]*)p1;
451 void[] a2 = *cast(void[]*)p2;
452 if (a1.length != a2.length)
453 return false;
454 size_t sz = value.tsize;
455 for (size_t i = 0; i < a1.length; i++)
456 {
457 if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz))
458 return false;
459 }
460 return true;
461 }
462
463 override int compare(in void* p1, in void* p2) const
464 {
465 void[] a1 = *cast(void[]*)p1;
466 void[] a2 = *cast(void[]*)p2;
467 size_t sz = value.tsize;
468 size_t len = a1.length;
469
470 if (a2.length < len)
471 len = a2.length;
472 for (size_t u = 0; u < len; u++)
473 {
474 immutable int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz);
475 if (result)
476 return result;
477 }
478 return cast(int)a1.length - cast(int)a2.length;
479 }
480
481 override @property size_t tsize() nothrow pure const
482 {
483 return (void[]).sizeof;
484 }
485
486 override const(void)[] initializer() const @trusted
487 {
488 return (cast(void *)null)[0 .. (void[]).sizeof];
489 }
490
491 override void swap(void* p1, void* p2) const
492 {
493 void[] tmp = *cast(void[]*)p1;
494 *cast(void[]*)p1 = *cast(void[]*)p2;
495 *cast(void[]*)p2 = tmp;
496 }
497
498 TypeInfo value;
499
500 override @property inout(TypeInfo) next() nothrow pure inout
501 {
502 return value;
503 }
504
505 override @property uint flags() nothrow pure const { return 1; }
506
507 override @property size_t talign() nothrow pure const
508 {
509 return (void[]).alignof;
510 }
511
512 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
513 {
514 arg1 = typeid(size_t);
515 arg2 = typeid(void*);
516 return 0;
517 }
518 }
519
520 class TypeInfo_StaticArray : TypeInfo
521 {
522 override string toString() const
523 {
524 import core.internal.traits : externDFunc;
525 alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString",
526 char[] function(ulong, return char[], uint) @safe pure nothrow @nogc);
527
528 char[20] tmpBuff = void;
529 return value.toString() ~ "[" ~ sizeToTempString(len, tmpBuff, 10) ~ "]";
530 }
531
532 override bool opEquals(Object o)
533 {
534 if (this is o)
535 return true;
536 auto c = cast(const TypeInfo_StaticArray)o;
537 return c && this.len == c.len &&
538 this.value == c.value;
539 }
540
541 override size_t getHash(scope const void* p) @trusted const
542 {
543 return getArrayHash(value, p, len);
544 }
545
546 override bool equals(in void* p1, in void* p2) const
547 {
548 size_t sz = value.tsize;
549
550 for (size_t u = 0; u < len; u++)
551 {
552 if (!value.equals(p1 + u * sz, p2 + u * sz))
553 return false;
554 }
555 return true;
556 }
557
558 override int compare(in void* p1, in void* p2) const
559 {
560 size_t sz = value.tsize;
561
562 for (size_t u = 0; u < len; u++)
563 {
564 immutable int result = value.compare(p1 + u * sz, p2 + u * sz);
565 if (result)
566 return result;
567 }
568 return 0;
569 }
570
571 override @property size_t tsize() nothrow pure const
572 {
573 return len * value.tsize;
574 }
575
576 override void swap(void* p1, void* p2) const
577 {
578 import core.memory;
579 import core.stdc.string : memcpy;
580
581 void* tmp;
582 size_t sz = value.tsize;
583 ubyte[16] buffer;
584 void* pbuffer;
585
586 if (sz < buffer.sizeof)
587 tmp = buffer.ptr;
588 else
589 tmp = pbuffer = (new void[sz]).ptr;
590
591 for (size_t u = 0; u < len; u += sz)
592 {
593 size_t o = u * sz;
594 memcpy(tmp, p1 + o, sz);
595 memcpy(p1 + o, p2 + o, sz);
596 memcpy(p2 + o, tmp, sz);
597 }
598 if (pbuffer)
599 GC.free(pbuffer);
600 }
601
602 override const(void)[] initializer() nothrow pure const
603 {
604 return value.initializer();
605 }
606
607 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
608 override @property uint flags() nothrow pure const { return value.flags; }
609
610 override void destroy(void* p) const
611 {
612 immutable sz = value.tsize;
613 p += sz * len;
614 foreach (i; 0 .. len)
615 {
616 p -= sz;
617 value.destroy(p);
618 }
619 }
620
621 override void postblit(void* p) const
622 {
623 immutable sz = value.tsize;
624 foreach (i; 0 .. len)
625 {
626 value.postblit(p);
627 p += sz;
628 }
629 }
630
631 TypeInfo value;
632 size_t len;
633
634 override @property size_t talign() nothrow pure const
635 {
636 return value.talign;
637 }
638
639 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
640 {
641 arg1 = typeid(void*);
642 return 0;
643 }
644 }
645
646 class TypeInfo_AssociativeArray : TypeInfo
647 {
648 override string toString() const
649 {
650 return value.toString() ~ "[" ~ key.toString() ~ "]";
651 }
652
653 override bool opEquals(Object o)
654 {
655 if (this is o)
656 return true;
657 auto c = cast(const TypeInfo_AssociativeArray)o;
658 return c && this.key == c.key &&
659 this.value == c.value;
660 }
661
662 override bool equals(in void* p1, in void* p2) @trusted const
663 {
664 return !!_aaEqual(this, *cast(const AA*) p1, *cast(const AA*) p2);
665 }
666
667 override hash_t getHash(scope const void* p) nothrow @trusted const
668 {
669 return _aaGetHash(cast(AA*)p, this);
670 }
671
672 // BUG: need to add the rest of the functions
673
674 override @property size_t tsize() nothrow pure const
675 {
676 return (char[int]).sizeof;
677 }
678
679 override const(void)[] initializer() const @trusted
680 {
681 return (cast(void *)null)[0 .. (char[int]).sizeof];
682 }
683
684 override @property inout(TypeInfo) next() nothrow pure inout { return value; }
685 override @property uint flags() nothrow pure const { return 1; }
686
687 TypeInfo value;
688 TypeInfo key;
689
690 override @property size_t talign() nothrow pure const
691 {
692 return (char[int]).alignof;
693 }
694
695 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
696 {
697 arg1 = typeid(void*);
698 return 0;
699 }
700 }
701
702 class TypeInfo_Vector : TypeInfo
703 {
704 override string toString() const { return "__vector(" ~ base.toString() ~ ")"; }
705
706 override bool opEquals(Object o)
707 {
708 if (this is o)
709 return true;
710 auto c = cast(const TypeInfo_Vector)o;
711 return c && this.base == c.base;
712 }
713
714 override size_t getHash(scope const void* p) const { return base.getHash(p); }
715 override bool equals(in void* p1, in void* p2) const { return base.equals(p1, p2); }
716 override int compare(in void* p1, in void* p2) const { return base.compare(p1, p2); }
717 override @property size_t tsize() nothrow pure const { return base.tsize; }
718 override void swap(void* p1, void* p2) const { return base.swap(p1, p2); }
719
720 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
721 override @property uint flags() nothrow pure const { return base.flags; }
722
723 override const(void)[] initializer() nothrow pure const
724 {
725 return base.initializer();
726 }
727
728 override @property size_t talign() nothrow pure const { return 16; }
729
730 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
731 {
732 return base.argTypes(arg1, arg2);
733 }
734
735 TypeInfo base;
736 }
737
738 class TypeInfo_Function : TypeInfo
739 {
740 override string toString() const
741 {
742 import core.demangle : demangleType;
743
744 alias SafeDemangleFunctionType = char[] function (const(char)[] buf, char[] dst = null) @safe nothrow pure;
745 SafeDemangleFunctionType demangle = ( () @trusted => cast(SafeDemangleFunctionType)(&demangleType) ) ();
746
747 return (() @trusted => cast(string)(demangle(deco))) ();
748 }
749
750 override bool opEquals(Object o)
751 {
752 if (this is o)
753 return true;
754 auto c = cast(const TypeInfo_Function)o;
755 return c && this.deco == c.deco;
756 }
757
758 // BUG: need to add the rest of the functions
759
760 override @property size_t tsize() nothrow pure const
761 {
762 return 0; // no size for functions
763 }
764
765 override const(void)[] initializer() const @safe
766 {
767 return null;
768 }
769
770 TypeInfo next;
771
772 /**
773 * Mangled function type string
774 */
775 string deco;
776 }
777
778 unittest
779 {
780 abstract class C
781 {
782 void func();
783 void func(int a);
784 int func(int a, int b);
785 }
786
787 alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func"));
788 assert(typeid(functionTypes[0]).toString() == "void function()");
789 assert(typeid(functionTypes[1]).toString() == "void function(int)");
790 assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
791 }
792
793 class TypeInfo_Delegate : TypeInfo
794 {
795 override string toString() const
796 {
797 return cast(string)(next.toString() ~ " delegate()");
798 }
799
800 override bool opEquals(Object o)
801 {
802 if (this is o)
803 return true;
804 auto c = cast(const TypeInfo_Delegate)o;
805 return c && this.deco == c.deco;
806 }
807
808 override size_t getHash(scope const void* p) @trusted const
809 {
810 return hashOf(*cast(void delegate()*)p);
811 }
812
813 override bool equals(in void* p1, in void* p2) const
814 {
815 auto dg1 = *cast(void delegate()*)p1;
816 auto dg2 = *cast(void delegate()*)p2;
817 return dg1 == dg2;
818 }
819
820 override int compare(in void* p1, in void* p2) const
821 {
822 auto dg1 = *cast(void delegate()*)p1;
823 auto dg2 = *cast(void delegate()*)p2;
824
825 if (dg1 < dg2)
826 return -1;
827 else if (dg1 > dg2)
828 return 1;
829 else
830 return 0;
831 }
832
833 override @property size_t tsize() nothrow pure const
834 {
835 alias dg = int delegate();
836 return dg.sizeof;
837 }
838
839 override const(void)[] initializer() const @trusted
840 {
841 return (cast(void *)null)[0 .. (int delegate()).sizeof];
842 }
843
844 override @property uint flags() nothrow pure const { return 1; }
845
846 TypeInfo next;
847 string deco;
848
849 override @property size_t talign() nothrow pure const
850 {
851 alias dg = int delegate();
852 return dg.alignof;
853 }
854
855 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
856 {
857 arg1 = typeid(void*);
858 arg2 = typeid(void*);
859 return 0;
860 }
861 }
862
863 /**
864 * Runtime type information about a class.
865 * Can be retrieved from an object instance by using the
866 * $(DDSUBLINK spec/property,classinfo, .classinfo) property.
867 */
868 class TypeInfo_Class : TypeInfo
869 {
870 override string toString() const { return info.name; }
871
872 override bool opEquals(Object o)
873 {
874 if (this is o)
875 return true;
876 auto c = cast(const TypeInfo_Class)o;
877 return c && this.info.name == c.info.name;
878 }
879
880 override size_t getHash(scope const void* p) @trusted const
881 {
882 auto o = *cast(Object*)p;
883 return o ? o.toHash() : 0;
884 }
885
886 override bool equals(in void* p1, in void* p2) const
887 {
888 Object o1 = *cast(Object*)p1;
889 Object o2 = *cast(Object*)p2;
890
891 return (o1 is o2) || (o1 && o1.opEquals(o2));
892 }
893
894 override int compare(in void* p1, in void* p2) const
895 {
896 Object o1 = *cast(Object*)p1;
897 Object o2 = *cast(Object*)p2;
898 int c = 0;
899
900 // Regard null references as always being "less than"
901 if (o1 !is o2)
902 {
903 if (o1)
904 {
905 if (!o2)
906 c = 1;
907 else
908 c = o1.opCmp(o2);
909 }
910 else
911 c = -1;
912 }
913 return c;
914 }
915
916 override @property size_t tsize() nothrow pure const
917 {
918 return Object.sizeof;
919 }
920
921 override const(void)[] initializer() nothrow pure const @safe
922 {
923 return m_init;
924 }
925
926 override @property uint flags() nothrow pure const { return 1; }
927
928 override @property const(OffsetTypeInfo)[] offTi() nothrow pure const
929 {
930 return m_offTi;
931 }
932
933 @property auto info() @safe nothrow pure const { return this; }
934 @property auto typeinfo() @safe nothrow pure const { return this; }
935
936 byte[] m_init; /** class static initializer
937 * (init.length gives size in bytes of class)
938 */
939 string name; /// class name
940 void*[] vtbl; /// virtual function pointer table
941 Interface[] interfaces; /// interfaces this class implements
942 TypeInfo_Class base; /// base class
943 void* destructor;
944 void function(Object) classInvariant;
945 enum ClassFlags : uint
946 {
947 isCOMclass = 0x1,
948 noPointers = 0x2,
949 hasOffTi = 0x4,
950 hasCtor = 0x8,
951 hasGetMembers = 0x10,
952 hasTypeInfo = 0x20,
953 isAbstract = 0x40,
954 isCPPclass = 0x80,
955 hasDtor = 0x100,
956 }
957 ClassFlags m_flags;
958 void* deallocator;
959 OffsetTypeInfo[] m_offTi;
960 void function(Object) defaultConstructor; // default Constructor
961
962 immutable(void)* m_RTInfo; // data for precise GC
963 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
964
965 /**
966 * Search all modules for TypeInfo_Class corresponding to classname.
967 * Returns: null if not found
968 */
969 static const(TypeInfo_Class) find(in char[] classname)
970 {
971 foreach (m; ModuleInfo)
972 {
973 if (m)
974 {
975 //writefln("module %s, %d", m.name, m.localClasses.length);
976 foreach (c; m.localClasses)
977 {
978 if (c is null)
979 continue;
980 //writefln("\tclass %s", c.name);
981 if (c.name == classname)
982 return c;
983 }
984 }
985 }
986 return null;
987 }
988
989 /**
990 * Create instance of Object represented by 'this'.
991 */
992 Object create() const
993 {
994 if (m_flags & 8 && !defaultConstructor)
995 return null;
996 if (m_flags & 64) // abstract
997 return null;
998 Object o = _d_newclass(this);
999 if (m_flags & 8 && defaultConstructor)
1000 {
1001 defaultConstructor(o);
1002 }
1003 return o;
1004 }
1005 }
1006
1007 alias ClassInfo = TypeInfo_Class;
1008
1009 unittest
1010 {
1011 // Bugzilla 14401
1012 static class X
1013 {
1014 int a;
1015 }
1016
1017 assert(typeid(X).initializer is typeid(X).m_init);
1018 assert(typeid(X).initializer.length == typeid(const(X)).initializer.length);
1019 assert(typeid(X).initializer.length == typeid(shared(X)).initializer.length);
1020 assert(typeid(X).initializer.length == typeid(immutable(X)).initializer.length);
1021 }
1022
1023 class TypeInfo_Interface : TypeInfo
1024 {
1025 override string toString() const { return info.name; }
1026
1027 override bool opEquals(Object o)
1028 {
1029 if (this is o)
1030 return true;
1031 auto c = cast(const TypeInfo_Interface)o;
1032 return c && this.info.name == typeid(c).name;
1033 }
1034
1035 override size_t getHash(scope const void* p) @trusted const
1036 {
1037 if (!*cast(void**)p)
1038 {
1039 return 0;
1040 }
1041 Interface* pi = **cast(Interface ***)*cast(void**)p;
1042 Object o = cast(Object)(*cast(void**)p - pi.offset);
1043 assert(o);
1044 return o.toHash();
1045 }
1046
1047 override bool equals(in void* p1, in void* p2) const
1048 {
1049 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1050 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1051 pi = **cast(Interface ***)*cast(void**)p2;
1052 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1053
1054 return o1 == o2 || (o1 && o1.opCmp(o2) == 0);
1055 }
1056
1057 override int compare(in void* p1, in void* p2) const
1058 {
1059 Interface* pi = **cast(Interface ***)*cast(void**)p1;
1060 Object o1 = cast(Object)(*cast(void**)p1 - pi.offset);
1061 pi = **cast(Interface ***)*cast(void**)p2;
1062 Object o2 = cast(Object)(*cast(void**)p2 - pi.offset);
1063 int c = 0;
1064
1065 // Regard null references as always being "less than"
1066 if (o1 != o2)
1067 {
1068 if (o1)
1069 {
1070 if (!o2)
1071 c = 1;
1072 else
1073 c = o1.opCmp(o2);
1074 }
1075 else
1076 c = -1;
1077 }
1078 return c;
1079 }
1080
1081 override @property size_t tsize() nothrow pure const
1082 {
1083 return Object.sizeof;
1084 }
1085
1086 override const(void)[] initializer() const @trusted
1087 {
1088 return (cast(void *)null)[0 .. Object.sizeof];
1089 }
1090
1091 override @property uint flags() nothrow pure const { return 1; }
1092
1093 TypeInfo_Class info;
1094 }
1095
1096 class TypeInfo_Struct : TypeInfo
1097 {
1098 override string toString() const { return name; }
1099
1100 override bool opEquals(Object o)
1101 {
1102 if (this is o)
1103 return true;
1104 auto s = cast(const TypeInfo_Struct)o;
1105 return s && this.name == s.name &&
1106 this.initializer().length == s.initializer().length;
1107 }
1108
1109 override size_t getHash(scope const void* p) @trusted pure nothrow const
1110 {
1111 assert(p);
1112 if (xtoHash)
1113 {
1114 return (*xtoHash)(p);
1115 }
1116 else
1117 {
1118 return hashOf(p[0 .. initializer().length]);
1119 }
1120 }
1121
1122 override bool equals(in void* p1, in void* p2) @trusted pure nothrow const
1123 {
1124 import core.stdc.string : memcmp;
1125
1126 if (!p1 || !p2)
1127 return false;
1128 else if (xopEquals)
1129 {
1130 version (GNU)
1131 { // BUG: GDC and DMD use different calling conventions
1132 return (*xopEquals)(p2, p1);
1133 }
1134 else
1135 return (*xopEquals)(p1, p2);
1136 }
1137 else if (p1 == p2)
1138 return true;
1139 else
1140 // BUG: relies on the GC not moving objects
1141 return memcmp(p1, p2, initializer().length) == 0;
1142 }
1143
1144 override int compare(in void* p1, in void* p2) @trusted pure nothrow const
1145 {
1146 import core.stdc.string : memcmp;
1147
1148 // Regard null references as always being "less than"
1149 if (p1 != p2)
1150 {
1151 if (p1)
1152 {
1153 if (!p2)
1154 return true;
1155 else if (xopCmp)
1156 {
1157 version (GNU)
1158 { // BUG: GDC and DMD use different calling conventions
1159 return (*xopCmp)(p1, p2);
1160 }
1161 else
1162 return (*xopCmp)(p2, p1);
1163 }
1164 else
1165 // BUG: relies on the GC not moving objects
1166 return memcmp(p1, p2, initializer().length);
1167 }
1168 else
1169 return -1;
1170 }
1171 return 0;
1172 }
1173
1174 override @property size_t tsize() nothrow pure const
1175 {
1176 return initializer().length;
1177 }
1178
1179 override const(void)[] initializer() nothrow pure const @safe
1180 {
1181 return m_init;
1182 }
1183
1184 override @property uint flags() nothrow pure const { return m_flags; }
1185
1186 override @property size_t talign() nothrow pure const { return m_align; }
1187
1188 final override void destroy(void* p) const
1189 {
1190 if (xdtor)
1191 {
1192 if (m_flags & StructFlags.isDynamicType)
1193 (*xdtorti)(p, this);
1194 else
1195 (*xdtor)(p);
1196 }
1197 }
1198
1199 override void postblit(void* p) const
1200 {
1201 if (xpostblit)
1202 (*xpostblit)(p);
1203 }
1204
1205 string name;
1206 void[] m_init; // initializer; m_init.ptr == null if 0 initialize
1207
1208 @safe pure nothrow
1209 {
1210 size_t function(in void*) xtoHash;
1211 bool function(in void*, in void*) xopEquals;
1212 int function(in void*, in void*) xopCmp;
1213 string function(in void*) xtoString;
1214
1215 enum StructFlags : uint
1216 {
1217 hasPointers = 0x1,
1218 isDynamicType = 0x2, // built at runtime, needs type info in xdtor
1219 }
1220 StructFlags m_flags;
1221 }
1222 union
1223 {
1224 void function(void*) xdtor;
1225 void function(void*, const TypeInfo_Struct ti) xdtorti;
1226 }
1227 void function(void*) xpostblit;
1228
1229 uint m_align;
1230
1231 override @property immutable(void)* rtInfo() const { return m_RTInfo; }
1232
1233 version (X86_64)
1234 {
1235 override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1236 {
1237 arg1 = m_arg1;
1238 arg2 = m_arg2;
1239 return 0;
1240 }
1241 TypeInfo m_arg1;
1242 TypeInfo m_arg2;
1243 }
1244 immutable(void)* m_RTInfo; // data for precise GC
1245 }
1246
1247 unittest
1248 {
1249 struct S
1250 {
1251 bool opEquals(ref const S rhs) const
1252 {
1253 return false;
1254 }
1255 }
1256 S s;
1257 assert(!typeid(S).equals(&s, &s));
1258 }
1259
1260 class TypeInfo_Tuple : TypeInfo
1261 {
1262 TypeInfo[] elements;
1263
1264 override string toString() const
1265 {
1266 string s = "(";
1267 foreach (i, element; elements)
1268 {
1269 if (i)
1270 s ~= ',';
1271 s ~= element.toString();
1272 }
1273 s ~= ")";
1274 return s;
1275 }
1276
1277 override bool opEquals(Object o)
1278 {
1279 if (this is o)
1280 return true;
1281
1282 auto t = cast(const TypeInfo_Tuple)o;
1283 if (t && elements.length == t.elements.length)
1284 {
1285 for (size_t i = 0; i < elements.length; i++)
1286 {
1287 if (elements[i] != t.elements[i])
1288 return false;
1289 }
1290 return true;
1291 }
1292 return false;
1293 }
1294
1295 override size_t getHash(scope const void* p) const
1296 {
1297 assert(0);
1298 }
1299
1300 override bool equals(in void* p1, in void* p2) const
1301 {
1302 assert(0);
1303 }
1304
1305 override int compare(in void* p1, in void* p2) const
1306 {
1307 assert(0);
1308 }
1309
1310 override @property size_t tsize() nothrow pure const
1311 {
1312 assert(0);
1313 }
1314
1315 override const(void)[] initializer() const @trusted
1316 {
1317 assert(0);
1318 }
1319
1320 override void swap(void* p1, void* p2) const
1321 {
1322 assert(0);
1323 }
1324
1325 override void destroy(void* p) const
1326 {
1327 assert(0);
1328 }
1329
1330 override void postblit(void* p) const
1331 {
1332 assert(0);
1333 }
1334
1335 override @property size_t talign() nothrow pure const
1336 {
1337 assert(0);
1338 }
1339
1340 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1341 {
1342 assert(0);
1343 }
1344 }
1345
1346 class TypeInfo_Const : TypeInfo
1347 {
1348 override string toString() const
1349 {
1350 return cast(string) ("const(" ~ base.toString() ~ ")");
1351 }
1352
1353 //override bool opEquals(Object o) { return base.opEquals(o); }
1354 override bool opEquals(Object o)
1355 {
1356 if (this is o)
1357 return true;
1358
1359 if (typeid(this) != typeid(o))
1360 return false;
1361
1362 auto t = cast(TypeInfo_Const)o;
1363 return base.opEquals(t.base);
1364 }
1365
1366 override size_t getHash(scope const void *p) const { return base.getHash(p); }
1367 override bool equals(in void *p1, in void *p2) const { return base.equals(p1, p2); }
1368 override int compare(in void *p1, in void *p2) const { return base.compare(p1, p2); }
1369 override @property size_t tsize() nothrow pure const { return base.tsize; }
1370 override void swap(void *p1, void *p2) const { return base.swap(p1, p2); }
1371
1372 override @property inout(TypeInfo) next() nothrow pure inout { return base.next; }
1373 override @property uint flags() nothrow pure const { return base.flags; }
1374
1375 override const(void)[] initializer() nothrow pure const
1376 {
1377 return base.initializer();
1378 }
1379
1380 override @property size_t talign() nothrow pure const { return base.talign; }
1381
1382 version (X86_64) override int argTypes(out TypeInfo arg1, out TypeInfo arg2)
1383 {
1384 return base.argTypes(arg1, arg2);
1385 }
1386
1387 TypeInfo base;
1388 }
1389
1390 class TypeInfo_Invariant : TypeInfo_Const
1391 {
1392 override string toString() const
1393 {
1394 return cast(string) ("immutable(" ~ base.toString() ~ ")");
1395 }
1396 }
1397
1398 class TypeInfo_Shared : TypeInfo_Const
1399 {
1400 override string toString() const
1401 {
1402 return cast(string) ("shared(" ~ base.toString() ~ ")");
1403 }
1404 }
1405
1406 class TypeInfo_Inout : TypeInfo_Const
1407 {
1408 override string toString() const
1409 {
1410 return cast(string) ("inout(" ~ base.toString() ~ ")");
1411 }
1412 }
1413
1414
1415 ///////////////////////////////////////////////////////////////////////////////
1416 // ModuleInfo
1417 ///////////////////////////////////////////////////////////////////////////////
1418
1419
1420 enum
1421 {
1422 MIctorstart = 0x1, // we've started constructing it
1423 MIctordone = 0x2, // finished construction
1424 MIstandalone = 0x4, // module ctor does not depend on other module
1425 // ctors being done first
1426 MItlsctor = 8,
1427 MItlsdtor = 0x10,
1428 MIctor = 0x20,
1429 MIdtor = 0x40,
1430 MIxgetMembers = 0x80,
1431 MIictor = 0x100,
1432 MIunitTest = 0x200,
1433 MIimportedModules = 0x400,
1434 MIlocalClasses = 0x800,
1435 MIname = 0x1000,
1436 }
1437
1438
1439 struct ModuleInfo
1440 {
1441 uint _flags;
1442 uint _index; // index into _moduleinfo_array[]
1443
1444 version (all)
1445 {
1446 deprecated("ModuleInfo cannot be copy-assigned because it is a variable-sized struct.")
1447 void opAssign(in ModuleInfo m) { _flags = m._flags; _index = m._index; }
1448 }
1449 else
1450 {
1451 @disable this();
1452 @disable this(this) const;
1453 }
1454
1455 const:
1456 private void* addrOf(int flag) nothrow pure @nogc
1457 in
1458 {
1459 assert(flag >= MItlsctor && flag <= MIname);
1460 assert(!(flag & (flag - 1)) && !(flag & ~(flag - 1) << 1));
1461 }
1462 body
1463 {
1464 import core.stdc.string : strlen;
1465
1466 void* p = cast(void*)&this + ModuleInfo.sizeof;
1467
1468 if (flags & MItlsctor)
1469 {
1470 if (flag == MItlsctor) return p;
1471 p += typeof(tlsctor).sizeof;
1472 }
1473 if (flags & MItlsdtor)
1474 {
1475 if (flag == MItlsdtor) return p;
1476 p += typeof(tlsdtor).sizeof;
1477 }
1478 if (flags & MIctor)
1479 {
1480 if (flag == MIctor) return p;
1481 p += typeof(ctor).sizeof;
1482 }
1483 if (flags & MIdtor)
1484 {
1485 if (flag == MIdtor) return p;
1486 p += typeof(dtor).sizeof;
1487 }
1488 if (flags & MIxgetMembers)
1489 {
1490 if (flag == MIxgetMembers) return p;
1491 p += typeof(xgetMembers).sizeof;
1492 }
1493 if (flags & MIictor)
1494 {
1495 if (flag == MIictor) return p;
1496 p += typeof(ictor).sizeof;
1497 }
1498 if (flags & MIunitTest)
1499 {
1500 if (flag == MIunitTest) return p;
1501 p += typeof(unitTest).sizeof;
1502 }
1503 if (flags & MIimportedModules)
1504 {
1505 if (flag == MIimportedModules) return p;
1506 p += size_t.sizeof + *cast(size_t*)p * typeof(importedModules[0]).sizeof;
1507 }
1508 if (flags & MIlocalClasses)
1509 {
1510 if (flag == MIlocalClasses) return p;
1511 p += size_t.sizeof + *cast(size_t*)p * typeof(localClasses[0]).sizeof;
1512 }
1513 if (true || flags & MIname) // always available for now
1514 {
1515 if (flag == MIname) return p;
1516 p += strlen(cast(immutable char*)p);
1517 }
1518 assert(0);
1519 }
1520
1521 @property uint index() nothrow pure @nogc { return _index; }
1522
1523 @property uint flags() nothrow pure @nogc { return _flags; }
1524
1525 @property void function() tlsctor() nothrow pure @nogc
1526 {
1527 return flags & MItlsctor ? *cast(typeof(return)*)addrOf(MItlsctor) : null;
1528 }
1529
1530 @property void function() tlsdtor() nothrow pure @nogc
1531 {
1532 return flags & MItlsdtor ? *cast(typeof(return)*)addrOf(MItlsdtor) : null;
1533 }
1534
1535 @property void* xgetMembers() nothrow pure @nogc
1536 {
1537 return flags & MIxgetMembers ? *cast(typeof(return)*)addrOf(MIxgetMembers) : null;
1538 }
1539
1540 @property void function() ctor() nothrow pure @nogc
1541 {
1542 return flags & MIctor ? *cast(typeof(return)*)addrOf(MIctor) : null;
1543 }
1544
1545 @property void function() dtor() nothrow pure @nogc
1546 {
1547 return flags & MIdtor ? *cast(typeof(return)*)addrOf(MIdtor) : null;
1548 }
1549
1550 @property void function() ictor() nothrow pure @nogc
1551 {
1552 return flags & MIictor ? *cast(typeof(return)*)addrOf(MIictor) : null;
1553 }
1554
1555 @property void function() unitTest() nothrow pure @nogc
1556 {
1557 return flags & MIunitTest ? *cast(typeof(return)*)addrOf(MIunitTest) : null;
1558 }
1559
1560 @property immutable(ModuleInfo*)[] importedModules() nothrow pure @nogc
1561 {
1562 if (flags & MIimportedModules)
1563 {
1564 auto p = cast(size_t*)addrOf(MIimportedModules);
1565 return (cast(immutable(ModuleInfo*)*)(p + 1))[0 .. *p];
1566 }
1567 return null;
1568 }
1569
1570 @property TypeInfo_Class[] localClasses() nothrow pure @nogc
1571 {
1572 if (flags & MIlocalClasses)
1573 {
1574 auto p = cast(size_t*)addrOf(MIlocalClasses);
1575 return (cast(TypeInfo_Class*)(p + 1))[0 .. *p];
1576 }
1577 return null;
1578 }
1579
1580 @property string name() nothrow pure @nogc
1581 {
1582 if (true || flags & MIname) // always available for now
1583 {
1584 import core.stdc.string : strlen;
1585
1586 auto p = cast(immutable char*)addrOf(MIname);
1587 return p[0 .. strlen(p)];
1588 }
1589 // return null;
1590 }
1591
1592 static int opApply(scope int delegate(ModuleInfo*) dg)
1593 {
1594 import core.internal.traits : externDFunc;
1595 alias moduleinfos_apply = externDFunc!("rt.minfo.moduleinfos_apply",
1596 int function(scope int delegate(immutable(ModuleInfo*))));
1597 // Bugzilla 13084 - enforcing immutable ModuleInfo would break client code
1598 return moduleinfos_apply(
1599 (immutable(ModuleInfo*)m) => dg(cast(ModuleInfo*)m));
1600 }
1601 }
1602
1603 unittest
1604 {
1605 ModuleInfo* m1;
1606 foreach (m; ModuleInfo)
1607 {
1608 m1 = m;
1609 }
1610 }
1611
1612 ///////////////////////////////////////////////////////////////////////////////
1613 // Throwable
1614 ///////////////////////////////////////////////////////////////////////////////
1615
1616
1617 /**
1618 * The base class of all thrown objects.
1619 *
1620 * All thrown objects must inherit from Throwable. Class $(D Exception), which
1621 * derives from this class, represents the category of thrown objects that are
1622 * safe to catch and handle. In principle, one should not catch Throwable
1623 * objects that are not derived from $(D Exception), as they represent
1624 * unrecoverable runtime errors. Certain runtime guarantees may fail to hold
1625 * when these errors are thrown, making it unsafe to continue execution after
1626 * catching them.
1627 */
1628 class Throwable : Object
1629 {
1630 interface TraceInfo
1631 {
1632 int opApply(scope int delegate(ref const(char[]))) const;
1633 int opApply(scope int delegate(ref size_t, ref const(char[]))) const;
1634 string toString() const;
1635 }
1636
1637 string msg; /// A message describing the error.
1638
1639 /**
1640 * The _file name of the D source code corresponding with
1641 * where the error was thrown from.
1642 */
1643 string file;
1644 /**
1645 * The _line number of the D source code corresponding with
1646 * where the error was thrown from.
1647 */
1648 size_t line;
1649
1650 /**
1651 * The stack trace of where the error happened. This is an opaque object
1652 * that can either be converted to $(D string), or iterated over with $(D
1653 * foreach) to extract the items in the stack trace (as strings).
1654 */
1655 TraceInfo info;
1656
1657 /**
1658 * A reference to the _next error in the list. This is used when a new
1659 * $(D Throwable) is thrown from inside a $(D catch) block. The originally
1660 * caught $(D Exception) will be chained to the new $(D Throwable) via this
1661 * field.
1662 */
1663 Throwable next;
1664
1665 @nogc @safe pure nothrow this(string msg, Throwable next = null)
1666 {
1667 this.msg = msg;
1668 this.next = next;
1669 //this.info = _d_traceContext();
1670 }
1671
1672 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable next = null)
1673 {
1674 this(msg, next);
1675 this.file = file;
1676 this.line = line;
1677 //this.info = _d_traceContext();
1678 }
1679
1680 /**
1681 * Overrides $(D Object.toString) and returns the error message.
1682 * Internally this forwards to the $(D toString) overload that
1683 * takes a $(D_PARAM sink) delegate.
1684 */
1685 override string toString()
1686 {
1687 string s;
1688 toString((buf) { s ~= buf; });
1689 return s;
1690 }
1691
1692 /**
1693 * The Throwable hierarchy uses a toString overload that takes a
1694 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be
1695 * performed in certain error situations. Override this $(D
1696 * toString) method to customize the error message.
1697 */
1698 void toString(scope void delegate(in char[]) sink) const
1699 {
1700 import core.internal.traits : externDFunc;
1701 alias sizeToTempString = externDFunc!("core.internal.string.unsignedToTempString",
1702 char[] function(ulong, return char[], uint) @safe pure nothrow @nogc);
1703
1704 char[20] tmpBuff = void;
1705
1706 sink(typeid(this).name);
1707 sink("@"); sink(file);
1708 sink("("); sink(sizeToTempString(line, tmpBuff, 10)); sink(")");
1709
1710 if (msg.length)
1711 {
1712 sink(": "); sink(msg);
1713 }
1714 if (info)
1715 {
1716 try
1717 {
1718 sink("\n----------------");
1719 foreach (t; info)
1720 {
1721 sink("\n"); sink(t);
1722 }
1723 }
1724 catch (Throwable)
1725 {
1726 // ignore more errors
1727 }
1728 }
1729 }
1730 }
1731
1732
1733 /**
1734 * The base class of all errors that are safe to catch and handle.
1735 *
1736 * In principle, only thrown objects derived from this class are safe to catch
1737 * inside a $(D catch) block. Thrown objects not derived from Exception
1738 * represent runtime errors that should not be caught, as certain runtime
1739 * guarantees may not hold, making it unsafe to continue program execution.
1740 */
1741 class Exception : Throwable
1742 {
1743
1744 /**
1745 * Creates a new instance of Exception. The next parameter is used
1746 * internally and should always be $(D null) when passed by user code.
1747 * This constructor does not automatically throw the newly-created
1748 * Exception; the $(D throw) statement should be used for that purpose.
1749 */
1750 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null)
1751 {
1752 super(msg, file, line, next);
1753 }
1754
1755 @nogc @safe pure nothrow this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__)
1756 {
1757 super(msg, file, line, next);
1758 }
1759 }
1760
1761 unittest
1762 {
1763 {
1764 auto e = new Exception("msg");
1765 assert(e.file == __FILE__);
1766 assert(e.line == __LINE__ - 2);
1767 assert(e.next is null);
1768 assert(e.msg == "msg");
1769 }
1770
1771 {
1772 auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42);
1773 assert(e.file == "hello");
1774 assert(e.line == 42);
1775 assert(e.next !is null);
1776 assert(e.msg == "msg");
1777 }
1778
1779 {
1780 auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!"));
1781 assert(e.file == "hello");
1782 assert(e.line == 42);
1783 assert(e.next !is null);
1784 assert(e.msg == "msg");
1785 }
1786 }
1787
1788
1789 /**
1790 * The base class of all unrecoverable runtime errors.
1791 *
1792 * This represents the category of $(D Throwable) objects that are $(B not)
1793 * safe to catch and handle. In principle, one should not catch Error
1794 * objects, as they represent unrecoverable runtime errors.
1795 * Certain runtime guarantees may fail to hold when these errors are
1796 * thrown, making it unsafe to continue execution after catching them.
1797 */
1798 class Error : Throwable
1799 {
1800 /**
1801 * Creates a new instance of Error. The next parameter is used
1802 * internally and should always be $(D null) when passed by user code.
1803 * This constructor does not automatically throw the newly-created
1804 * Error; the $(D throw) statement should be used for that purpose.
1805 */
1806 @nogc @safe pure nothrow this(string msg, Throwable next = null)
1807 {
1808 super(msg, next);
1809 bypassedException = null;
1810 }
1811
1812 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable next = null)
1813 {
1814 super(msg, file, line, next);
1815 bypassedException = null;
1816 }
1817
1818 /** The first $(D Exception) which was bypassed when this Error was thrown,
1819 or $(D null) if no $(D Exception)s were pending. */
1820 Throwable bypassedException;
1821 }
1822
1823 unittest
1824 {
1825 {
1826 auto e = new Error("msg");
1827 assert(e.file is null);
1828 assert(e.line == 0);
1829 assert(e.next is null);
1830 assert(e.msg == "msg");
1831 assert(e.bypassedException is null);
1832 }
1833
1834 {
1835 auto e = new Error("msg", new Exception("It's an Exception!"));
1836 assert(e.file is null);
1837 assert(e.line == 0);
1838 assert(e.next !is null);
1839 assert(e.msg == "msg");
1840 assert(e.bypassedException is null);
1841 }
1842
1843 {
1844 auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!"));
1845 assert(e.file == "hello");
1846 assert(e.line == 42);
1847 assert(e.next !is null);
1848 assert(e.msg == "msg");
1849 assert(e.bypassedException is null);
1850 }
1851 }
1852
1853 /* Used in Exception Handling LSDA tables to 'wrap' C++ type info
1854 * so it can be distinguished from D TypeInfo
1855 */
1856 class __cpp_type_info_ptr
1857 {
1858 void* ptr; // opaque pointer to C++ RTTI type info
1859 }
1860
1861 extern (C)
1862 {
1863 // from druntime/src/rt/aaA.d
1864
1865 private struct AA { void* impl; }
1866 // size_t _aaLen(in AA aa) pure nothrow @nogc;
1867 private void* _aaGetY(AA* paa, const TypeInfo_AssociativeArray ti, in size_t valsz, in void* pkey) pure nothrow;
1868 private void* _aaGetX(AA* paa, const TypeInfo_AssociativeArray ti, in size_t valsz, in void* pkey, out bool found) pure nothrow;
1869 // inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey);
1870 inout(void[]) _aaValues(inout AA aa, in size_t keysz, in size_t valsz, const TypeInfo tiValueArray) pure nothrow;
1871 inout(void[]) _aaKeys(inout AA aa, in size_t keysz, const TypeInfo tiKeyArray) pure nothrow;
1872 void* _aaRehash(AA* paa, in TypeInfo keyti) pure nothrow;
1873 void _aaClear(AA aa) pure nothrow;
1874
1875 // alias _dg_t = extern(D) int delegate(void*);
1876 // int _aaApply(AA aa, size_t keysize, _dg_t dg);
1877
1878 // alias _dg2_t = extern(D) int delegate(void*, void*);
1879 // int _aaApply2(AA aa, size_t keysize, _dg2_t dg);
1880
1881 private struct AARange { AA impl; size_t idx; }
1882 AARange _aaRange(AA aa) pure nothrow @nogc @safe;
1883 bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe;
1884 void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe;
1885 void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe;
1886 void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe;
1887
1888 int _aaEqual(in TypeInfo tiRaw, in AA aa1, in AA aa2);
1889 hash_t _aaGetHash(in AA* aa, in TypeInfo tiRaw) nothrow;
1890
1891 /*
1892 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code.
1893 This is a typesystem hole, however this is existing hole.
1894 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus
1895 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods.
1896 */
1897 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure;
1898 }
1899
1900 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure
1901 {
1902 return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values);
1903 }
1904
1905 alias AssociativeArray(Key, Value) = Value[Key];
1906
1907 /***********************************
1908 * Removes all remaining keys and values from an associative array.
1909 * Params:
1910 * aa = The associative array.
1911 */
1912 void clear(T : Value[Key], Value, Key)(T aa)
1913 {
1914 _aaClear(*cast(AA *) &aa);
1915 }
1916
1917 /* ditto */
1918 void clear(T : Value[Key], Value, Key)(T* aa)
1919 {
1920 _aaClear(*cast(AA *) aa);
1921 }
1922
1923 /***********************************
1924 * Reorganizes the associative array in place so that lookups are more
1925 * efficient.
1926 * Params:
1927 * aa = The associative array.
1928 * Returns:
1929 * The rehashed associative array.
1930 */
1931 T rehash(T : Value[Key], Value, Key)(T aa)
1932 {
1933 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
1934 return aa;
1935 }
1936
1937 /* ditto */
1938 T rehash(T : Value[Key], Value, Key)(T* aa)
1939 {
1940 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
1941 return *aa;
1942 }
1943
1944 /* ditto */
1945 T rehash(T : shared Value[Key], Value, Key)(T aa)
1946 {
1947 _aaRehash(cast(AA*)&aa, typeid(Value[Key]));
1948 return aa;
1949 }
1950
1951 /* ditto */
1952 T rehash(T : shared Value[Key], Value, Key)(T* aa)
1953 {
1954 _aaRehash(cast(AA*)aa, typeid(Value[Key]));
1955 return *aa;
1956 }
1957
1958 /***********************************
1959 * Create a new associative array of the same size and copy the contents of the
1960 * associative array into it.
1961 * Params:
1962 * aa = The associative array.
1963 */
1964 V[K] dup(T : V[K], K, V)(T aa)
1965 {
1966 //pragma(msg, "K = ", K, ", V = ", V);
1967
1968 // Bug10720 - check whether V is copyable
1969 static assert(is(typeof({ V v = aa[K.init]; })),
1970 "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable");
1971
1972 V[K] result;
1973
1974 //foreach (k, ref v; aa)
1975 // result[k] = v; // Bug13701 - won't work if V is not mutable
1976
1977 ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow
1978 {
1979 import core.stdc.string : memcpy;
1980
1981 void* pv = _aaGetY(cast(AA*)&result, typeid(V[K]), V.sizeof, &k);
1982 memcpy(pv, &v, V.sizeof);
1983 return *cast(V*)pv;
1984 }
1985
1986 if (auto postblit = _getPostblit!V())
1987 {
1988 foreach (k, ref v; aa)
1989 postblit(duplicateElem(k, v));
1990 }
1991 else
1992 {
1993 foreach (k, ref v; aa)
1994 duplicateElem(k, v);
1995 }
1996
1997 return result;
1998 }
1999
2000 /* ditto */
2001 V[K] dup(T : V[K], K, V)(T* aa)
2002 {
2003 return (*aa).dup;
2004 }
2005
2006 // this should never be made public.
2007 private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe
2008 {
2009 // ensure we are dealing with a genuine AA.
2010 static if (is(const(V[K]) == const(T)))
2011 alias realAA = aa;
2012 else
2013 const(V[K]) realAA = aa;
2014 return _aaRange(() @trusted { return *cast(AA*)&realAA; } ());
2015 }
2016
2017 /***********************************
2018 * Returns a forward range over the keys of the associative array.
2019 * Params:
2020 * aa = The associative array.
2021 * Returns:
2022 * A forward range.
2023 */
2024 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
2025 {
2026 import core.internal.traits : substInout;
2027
2028 static struct Result
2029 {
2030 AARange r;
2031
2032 pure nothrow @nogc:
2033 @property bool empty() @safe { return _aaRangeEmpty(r); }
2034 @property ref front()
2035 {
2036 auto p = (() @trusted => cast(substInout!K*) _aaRangeFrontKey(r)) ();
2037 return *p;
2038 }
2039 void popFront() @safe { _aaRangePopFront(r); }
2040 @property Result save() { return this; }
2041 }
2042
2043 return Result(_aaToRange(aa));
2044 }
2045
2046 /* ditto */
2047 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc
2048 {
2049 return (*aa).byKey();
2050 }
2051
2052 /***********************************
2053 * Returns a forward range over the values of the associative array.
2054 * Params:
2055 * aa = The associative array.
2056 * Returns:
2057 * A forward range.
2058 */
2059 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
2060 {
2061 import core.internal.traits : substInout;
2062
2063 static struct Result
2064 {
2065 AARange r;
2066
2067 pure nothrow @nogc:
2068 @property bool empty() @safe { return _aaRangeEmpty(r); }
2069 @property ref front()
2070 {
2071 auto p = (() @trusted => cast(substInout!V*) _aaRangeFrontValue(r)) ();
2072 return *p;
2073 }
2074 void popFront() @safe { _aaRangePopFront(r); }
2075 @property Result save() { return this; }
2076 }
2077
2078 return Result(_aaToRange(aa));
2079 }
2080
2081 /* ditto */
2082 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
2083 {
2084 return (*aa).byValue();
2085 }
2086
2087 /***********************************
2088 * Returns a forward range over the key value pairs of the associative array.
2089 * Params:
2090 * aa = The associative array.
2091 * Returns:
2092 * A forward range.
2093 */
2094 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe
2095 {
2096 import core.internal.traits : substInout;
2097
2098 static struct Result
2099 {
2100 AARange r;
2101
2102 pure nothrow @nogc:
2103 @property bool empty() @safe { return _aaRangeEmpty(r); }
2104 @property auto front()
2105 {
2106 static struct Pair
2107 {
2108 // We save the pointers here so that the Pair we return
2109 // won't mutate when Result.popFront is called afterwards.
2110 private void* keyp;
2111 private void* valp;
2112
2113 @property ref key() inout
2114 {
2115 auto p = (() @trusted => cast(substInout!K*) keyp) ();
2116 return *p;
2117 }
2118 @property ref value() inout
2119 {
2120 auto p = (() @trusted => cast(substInout!V*) valp) ();
2121 return *p;
2122 }
2123 }
2124 return Pair(_aaRangeFrontKey(r),
2125 _aaRangeFrontValue(r));
2126 }
2127 void popFront() @safe { return _aaRangePopFront(r); }
2128 @property Result save() { return this; }
2129 }
2130
2131 return Result(_aaToRange(aa));
2132 }
2133
2134 /* ditto */
2135 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc
2136 {
2137 return (*aa).byKeyValue();
2138 }
2139
2140 /***********************************
2141 * Returns a dynamic array, the elements of which are the keys in the
2142 * associative array.
2143 * Params:
2144 * aa = The associative array.
2145 * Returns:
2146 * A dynamic array.
2147 */
2148 Key[] keys(T : Value[Key], Value, Key)(T aa) @property
2149 {
2150 // ensure we are dealing with a genuine AA.
2151 static if (is(const(Value[Key]) == const(T)))
2152 alias realAA = aa;
2153 else
2154 const(Value[Key]) realAA = aa;
2155 auto a = cast(void[])_aaKeys(*cast(inout(AA)*)&realAA, Key.sizeof, typeid(Key[]));
2156 auto res = *cast(Key[]*)&a;
2157 _doPostblit(res);
2158 return res;
2159 }
2160
2161 /* ditto */
2162 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property
2163 {
2164 return (*aa).keys;
2165 }
2166
2167 @system unittest
2168 {
2169 static struct S
2170 {
2171 string str;
2172 void[][string] dict;
2173 alias dict this;
2174 }
2175
2176 auto s = S("a");
2177 assert(s.keys.length == 0);
2178 }
2179
2180 /***********************************
2181 * Returns a dynamic array, the elements of which are the values in the
2182 * associative array.
2183 * Params:
2184 * aa = The associative array.
2185 * Returns:
2186 * A dynamic array.
2187 */
2188 Value[] values(T : Value[Key], Value, Key)(T aa) @property
2189 {
2190 // ensure we are dealing with a genuine AA.
2191 static if (is(const(Value[Key]) == const(T)))
2192 alias realAA = aa;
2193 else
2194 const(Value[Key]) realAA = aa;
2195 auto a = cast(void[])_aaValues(*cast(inout(AA)*)&realAA, Key.sizeof, Value.sizeof, typeid(Value[]));
2196 auto res = *cast(Value[]*)&a;
2197 _doPostblit(res);
2198 return res;
2199 }
2200
2201 /* ditto */
2202 Value[] values(T : Value[Key], Value, Key)(T *aa) @property
2203 {
2204 return (*aa).values;
2205 }
2206
2207 @system unittest
2208 {
2209 static struct S
2210 {
2211 string str;
2212 void[][string] dict;
2213 alias dict this;
2214 }
2215
2216 auto s = S("a");
2217 assert(s.values.length == 0);
2218 }
2219
2220 /***********************************
2221 * Looks up key; if it exists returns corresponding value else evaluates and
2222 * returns defaultValue.
2223 * Params:
2224 * aa = The associative array.
2225 * key = The key.
2226 * defaultValue = The default value.
2227 * Returns:
2228 * The value.
2229 */
2230 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue)
2231 {
2232 auto p = key in aa;
2233 return p ? *p : defaultValue;
2234 }
2235
2236 /* ditto */
2237 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue)
2238 {
2239 return (*aa).get(key, defaultValue);
2240 }
2241
2242 /***********************************
2243 * Looks up key; if it exists returns corresponding value else evaluates
2244 * value, adds it to the associative array and returns it.
2245 * Params:
2246 * aa = The associative array.
2247 * key = The key.
2248 * value = The required value.
2249 * Returns:
2250 * The value.
2251 */
2252 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
2253 {
2254 bool found;
2255 // if key is @safe-ly copyable, `require` can infer @safe
2256 static if (isSafeCopyable!K)
2257 {
2258 auto p = () @trusted
2259 {
2260 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
2261 } ();
2262 }
2263 else
2264 {
2265 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
2266 }
2267 return found ? *p : (*p = value);
2268 }
2269
2270 // Constraints for aa update. Delegates, Functions or Functors (classes that
2271 // provide opCall) are allowed. See unittest for an example.
2272 private
2273 {
2274 template isCreateOperation(C, V)
2275 {
2276 static if (is(C : V delegate()) || is(C : V function()))
2277 enum bool isCreateOperation = true;
2278 else static if (isCreateOperation!(typeof(&C.opCall), V))
2279 enum bool isCreateOperation = true;
2280 else
2281 enum bool isCreateOperation = false;
2282 }
2283
2284 template isUpdateOperation(U, V)
2285 {
2286 static if (is(U : V delegate(ref V)) || is(U : V function(ref V)))
2287 enum bool isUpdateOperation = true;
2288 else static if (isUpdateOperation!(typeof(&U.opCall), V))
2289 enum bool isUpdateOperation = true;
2290 else
2291 enum bool isUpdateOperation = false;
2292 }
2293 }
2294
2295 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test.
2296 private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); }));
2297
2298 /***********************************
2299 * Looks up key; if it exists applies the update delegate else evaluates the
2300 * create delegate and adds it to the associative array
2301 * Params:
2302 * aa = The associative array.
2303 * key = The key.
2304 * create = The delegate to apply on create.
2305 * update = The delegate to apply on update.
2306 */
2307 void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
2308 if (isCreateOperation!(C, V) && isUpdateOperation!(U, V))
2309 {
2310 bool found;
2311 // if key is @safe-ly copyable, `update` may infer @safe
2312 static if (isSafeCopyable!K)
2313 {
2314 auto p = () @trusted
2315 {
2316 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
2317 } ();
2318 }
2319 else
2320 {
2321 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found);
2322 }
2323 if (!found)
2324 *p = create();
2325 else
2326 *p = update(*p);
2327 }
2328
2329 unittest
2330 {
2331 static struct S
2332 {
2333 int x;
2334 @nogc nothrow pure:
2335 this(this) @system {}
2336
2337 @safe const:
2338 // stubs
2339 bool opEquals(S rhs) { assert(0); }
2340 size_t toHash() { assert(0); }
2341 }
2342
2343 int[string] aai;
2344 static assert(is(typeof(() @safe { aai.require("a", 1234); })));
2345 static assert(is(typeof(() @safe { aai.update("a", { return 1234; }, (ref int x) { x++; return x; }); })));
2346
2347 S[string] aas;
2348 static assert(is(typeof(() { aas.require("a", S(1234)); })));
2349 static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
2350 static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); })));
2351
2352 int[S] aais;
2353 static assert(is(typeof(() { aais.require(S(1234), 1234); })));
2354 static assert(is(typeof(() { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
2355 static assert(!is(typeof(() @safe { aais.require(S(1234), 1234); })));
2356 static assert(!is(typeof(() @safe { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); })));
2357 }
2358
2359 private void _destructRecurse(S)(ref S s)
2360 if (is(S == struct))
2361 {
2362 static if (__traits(hasMember, S, "__xdtor") &&
2363 // Bugzilla 14746: Check that it's the exact member of S.
2364 __traits(isSame, S, __traits(parent, s.__xdtor)))
2365 s.__xdtor();
2366 }
2367
2368 private void _destructRecurse(E, size_t n)(ref E[n] arr)
2369 {
2370 import core.internal.traits : hasElaborateDestructor;
2371
2372 static if (hasElaborateDestructor!E)
2373 {
2374 foreach_reverse (ref elem; arr)
2375 _destructRecurse(elem);
2376 }
2377 }
2378
2379 // Public and explicitly undocumented
2380 void _postblitRecurse(S)(ref S s)
2381 if (is(S == struct))
2382 {
2383 static if (__traits(hasMember, S, "__xpostblit") &&
2384 // Bugzilla 14746: Check that it's the exact member of S.
2385 __traits(isSame, S, __traits(parent, s.__xpostblit)))
2386 s.__xpostblit();
2387 }
2388
2389 // Ditto
2390 void _postblitRecurse(E, size_t n)(ref E[n] arr)
2391 {
2392 import core.internal.traits : hasElaborateCopyConstructor;
2393
2394 static if (hasElaborateCopyConstructor!E)
2395 {
2396 size_t i;
2397 scope(failure)
2398 {
2399 for (; i != 0; --i)
2400 {
2401 _destructRecurse(arr[i - 1]); // What to do if this throws?
2402 }
2403 }
2404
2405 for (i = 0; i < arr.length; ++i)
2406 _postblitRecurse(arr[i]);
2407 }
2408 }
2409
2410 // Test destruction/postblit order
2411 @safe nothrow pure unittest
2412 {
2413 string[] order;
2414
2415 struct InnerTop
2416 {
2417 ~this() @safe nothrow pure
2418 {
2419 order ~= "destroy inner top";
2420 }
2421
2422 this(this) @safe nothrow pure
2423 {
2424 order ~= "copy inner top";
2425 }
2426 }
2427
2428 struct InnerMiddle {}
2429
2430 version (none) // https://issues.dlang.org/show_bug.cgi?id=14242
2431 struct InnerElement
2432 {
2433 static char counter = '1';
2434
2435 ~this() @safe nothrow pure
2436 {
2437 order ~= "destroy inner element #" ~ counter++;
2438 }
2439
2440 this(this) @safe nothrow pure
2441 {
2442 order ~= "copy inner element #" ~ counter++;
2443 }
2444 }
2445
2446 struct InnerBottom
2447 {
2448 ~this() @safe nothrow pure
2449 {
2450 order ~= "destroy inner bottom";
2451 }
2452
2453 this(this) @safe nothrow pure
2454 {
2455 order ~= "copy inner bottom";
2456 }
2457 }
2458
2459 struct S
2460 {
2461 char[] s;
2462 InnerTop top;
2463 InnerMiddle middle;
2464 version (none) InnerElement[3] array; // https://issues.dlang.org/show_bug.cgi?id=14242
2465 int a;
2466 InnerBottom bottom;
2467 ~this() @safe nothrow pure { order ~= "destroy outer"; }
2468 this(this) @safe nothrow pure { order ~= "copy outer"; }
2469 }
2470
2471 string[] destructRecurseOrder;
2472 {
2473 S s;
2474 _destructRecurse(s);
2475 destructRecurseOrder = order;
2476 order = null;
2477 }
2478
2479 assert(order.length);
2480 assert(destructRecurseOrder == order);
2481 order = null;
2482
2483 S s;
2484 _postblitRecurse(s);
2485 assert(order.length);
2486 auto postblitRecurseOrder = order;
2487 order = null;
2488 S s2 = s;
2489 assert(order.length);
2490 assert(postblitRecurseOrder == order);
2491 }
2492
2493 // Test static struct
2494 nothrow @safe @nogc unittest
2495 {
2496 static int i = 0;
2497 static struct S { ~this() nothrow @safe @nogc { i = 42; } }
2498 S s;
2499 _destructRecurse(s);
2500 assert(i == 42);
2501 }
2502
2503 unittest
2504 {
2505 // Bugzilla 14746
2506 static struct HasDtor
2507 {
2508 ~this() { assert(0); }
2509 }
2510 static struct Owner
2511 {
2512 HasDtor* ptr;
2513 alias ptr this;
2514 }
2515
2516 Owner o;
2517 assert(o.ptr is null);
2518 destroy(o); // must not reach in HasDtor.__dtor()
2519 }
2520
2521 unittest
2522 {
2523 // Bugzilla 14746
2524 static struct HasPostblit
2525 {
2526 this(this) { assert(0); }
2527 }
2528 static struct Owner
2529 {
2530 HasPostblit* ptr;
2531 alias ptr this;
2532 }
2533
2534 Owner o;
2535 assert(o.ptr is null);
2536 _postblitRecurse(o); // must not reach in HasPostblit.__postblit()
2537 }
2538
2539 // Test handling of fixed-length arrays
2540 // Separate from first test because of https://issues.dlang.org/show_bug.cgi?id=14242
2541 unittest
2542 {
2543 string[] order;
2544
2545 struct S
2546 {
2547 char id;
2548
2549 this(this)
2550 {
2551 order ~= "copy #" ~ id;
2552 }
2553
2554 ~this()
2555 {
2556 order ~= "destroy #" ~ id;
2557 }
2558 }
2559
2560 string[] destructRecurseOrder;
2561 {
2562 S[3] arr = [S('1'), S('2'), S('3')];
2563 _destructRecurse(arr);
2564 destructRecurseOrder = order;
2565 order = null;
2566 }
2567 assert(order.length);
2568 assert(destructRecurseOrder == order);
2569 order = null;
2570
2571 S[3] arr = [S('1'), S('2'), S('3')];
2572 _postblitRecurse(arr);
2573 assert(order.length);
2574 auto postblitRecurseOrder = order;
2575 order = null;
2576
2577 auto arrCopy = arr;
2578 assert(order.length);
2579 assert(postblitRecurseOrder == order);
2580 }
2581
2582 // Test handling of failed postblit
2583 // Not nothrow or @safe because of https://issues.dlang.org/show_bug.cgi?id=14242
2584 /+ nothrow @safe +/ unittest
2585 {
2586 static class FailedPostblitException : Exception { this() nothrow @safe { super(null); } }
2587 static string[] order;
2588 static struct Inner
2589 {
2590 char id;
2591
2592 @safe:
2593 this(this)
2594 {
2595 order ~= "copy inner #" ~ id;
2596 if (id == '2')
2597 throw new FailedPostblitException();
2598 }
2599
2600 ~this() nothrow
2601 {
2602 order ~= "destroy inner #" ~ id;
2603 }
2604 }
2605
2606 static struct Outer
2607 {
2608 Inner inner1, inner2, inner3;
2609
2610 nothrow @safe:
2611 this(char first, char second, char third)
2612 {
2613 inner1 = Inner(first);
2614 inner2 = Inner(second);
2615 inner3 = Inner(third);
2616 }
2617
2618 this(this)
2619 {
2620 order ~= "copy outer";
2621 }
2622
2623 ~this()
2624 {
2625 order ~= "destroy outer";
2626 }
2627 }
2628
2629 auto outer = Outer('1', '2', '3');
2630
2631 try _postblitRecurse(outer);
2632 catch (FailedPostblitException) {}
2633 catch (Exception) assert(false);
2634
2635 auto postblitRecurseOrder = order;
2636 order = null;
2637
2638 try auto copy = outer;
2639 catch (FailedPostblitException) {}
2640 catch (Exception) assert(false);
2641
2642 assert(postblitRecurseOrder == order);
2643 order = null;
2644
2645 Outer[3] arr = [Outer('1', '1', '1'), Outer('1', '2', '3'), Outer('3', '3', '3')];
2646
2647 try _postblitRecurse(arr);
2648 catch (FailedPostblitException) {}
2649 catch (Exception) assert(false);
2650
2651 postblitRecurseOrder = order;
2652 order = null;
2653
2654 try auto arrCopy = arr;
2655 catch (FailedPostblitException) {}
2656 catch (Exception) assert(false);
2657
2658 assert(postblitRecurseOrder == order);
2659 }
2660
2661 /++
2662 Destroys the given object and puts it in an invalid state. It's used to
2663 _destroy an object so that any cleanup which its destructor or finalizer
2664 does is done and so that it no longer references any other objects. It does
2665 $(I not) initiate a GC cycle or free any GC memory.
2666 +/
2667 void destroy(T)(T obj) if (is(T == class))
2668 {
2669 rt_finalize(cast(void*)obj);
2670 }
2671
2672 /// ditto
2673 void destroy(T)(T obj) if (is(T == interface))
2674 {
2675 destroy(cast(Object)obj);
2676 }
2677
2678 version (unittest) unittest
2679 {
2680 interface I { }
2681 {
2682 class A: I { string s = "A"; this() {} }
2683 auto a = new A, b = new A;
2684 a.s = b.s = "asd";
2685 destroy(a);
2686 assert(a.s == "A");
2687
2688 I i = b;
2689 destroy(i);
2690 assert(b.s == "A");
2691 }
2692 {
2693 static bool destroyed = false;
2694 class B: I
2695 {
2696 string s = "B";
2697 this() {}
2698 ~this()
2699 {
2700 destroyed = true;
2701 }
2702 }
2703 auto a = new B, b = new B;
2704 a.s = b.s = "asd";
2705 destroy(a);
2706 assert(destroyed);
2707 assert(a.s == "B");
2708
2709 destroyed = false;
2710 I i = b;
2711 destroy(i);
2712 assert(destroyed);
2713 assert(b.s == "B");
2714 }
2715 // this test is invalid now that the default ctor is not run after clearing
2716 version (none)
2717 {
2718 class C
2719 {
2720 string s;
2721 this()
2722 {
2723 s = "C";
2724 }
2725 }
2726 auto a = new C;
2727 a.s = "asd";
2728 destroy(a);
2729 assert(a.s == "C");
2730 }
2731 }
2732
2733 /// ditto
2734 void destroy(T)(ref T obj) if (is(T == struct))
2735 {
2736 _destructRecurse(obj);
2737 () @trusted {
2738 auto buf = (cast(ubyte*) &obj)[0 .. T.sizeof];
2739 auto init = cast(ubyte[])typeid(T).initializer();
2740 if (init.ptr is null) // null ptr means initialize to 0s
2741 buf[] = 0;
2742 else
2743 buf[] = init[];
2744 } ();
2745 }
2746
2747 version (unittest) nothrow @safe @nogc unittest
2748 {
2749 {
2750 struct A { string s = "A"; }
2751 A a;
2752 a.s = "asd";
2753 destroy(a);
2754 assert(a.s == "A");
2755 }
2756 {
2757 static int destroyed = 0;
2758 struct C
2759 {
2760 string s = "C";
2761 ~this() nothrow @safe @nogc
2762 {
2763 destroyed ++;
2764 }
2765 }
2766
2767 struct B
2768 {
2769 C c;
2770 string s = "B";
2771 ~this() nothrow @safe @nogc
2772 {
2773 destroyed ++;
2774 }
2775 }
2776 B a;
2777 a.s = "asd";
2778 a.c.s = "jkl";
2779 destroy(a);
2780 assert(destroyed == 2);
2781 assert(a.s == "B");
2782 assert(a.c.s == "C" );
2783 }
2784 }
2785
2786 /// ditto
2787 void destroy(T : U[n], U, size_t n)(ref T obj) if (!is(T == struct))
2788 {
2789 foreach_reverse (ref e; obj[])
2790 destroy(e);
2791 }
2792
2793 version (unittest) unittest
2794 {
2795 int[2] a;
2796 a[0] = 1;
2797 a[1] = 2;
2798 destroy(a);
2799 assert(a == [ 0, 0 ]);
2800 }
2801
2802 unittest
2803 {
2804 static struct vec2f {
2805 float[2] values;
2806 alias values this;
2807 }
2808
2809 vec2f v;
2810 destroy!vec2f(v);
2811 }
2812
2813 unittest
2814 {
2815 // Bugzilla 15009
2816 static string op;
2817 static struct S
2818 {
2819 int x;
2820 this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; }
2821 this(this) { op ~= "P" ~ cast(char)('0'+x); }
2822 ~this() { op ~= "D" ~ cast(char)('0'+x); }
2823 }
2824
2825 {
2826 S[2] a1 = [S(1), S(2)];
2827 op = "";
2828 }
2829 assert(op == "D2D1"); // built-in scope destruction
2830 {
2831 S[2] a1 = [S(1), S(2)];
2832 op = "";
2833 destroy(a1);
2834 assert(op == "D2D1"); // consistent with built-in behavior
2835 }
2836
2837 {
2838 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
2839 op = "";
2840 }
2841 assert(op == "D4D3D2D1");
2842 {
2843 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]];
2844 op = "";
2845 destroy(a2);
2846 assert(op == "D4D3D2D1", op);
2847 }
2848 }
2849
2850 /// ditto
2851 void destroy(T)(ref T obj)
2852 if (!is(T == struct) && !is(T == interface) && !is(T == class) && !_isStaticArray!T)
2853 {
2854 obj = T.init;
2855 }
2856
2857 template _isStaticArray(T : U[N], U, size_t N)
2858 {
2859 enum bool _isStaticArray = true;
2860 }
2861
2862 template _isStaticArray(T)
2863 {
2864 enum bool _isStaticArray = false;
2865 }
2866
2867 version (unittest) unittest
2868 {
2869 {
2870 int a = 42;
2871 destroy(a);
2872 assert(a == 0);
2873 }
2874 {
2875 float a = 42;
2876 destroy(a);
2877 assert(isnan(a));
2878 }
2879 }
2880
2881 version (unittest)
2882 {
2883 private bool isnan(float x)
2884 {
2885 return x != x;
2886 }
2887 }
2888
2889 private
2890 {
2891 extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow;
2892 extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void *arrptr) pure nothrow;
2893 }
2894
2895 /**
2896 * (Property) Gets the current _capacity of a slice. The _capacity is the size
2897 * that the slice can grow to before the underlying array must be
2898 * reallocated or extended.
2899 *
2900 * If an append must reallocate a slice with no possibility of extension, then
2901 * `0` is returned. This happens when the slice references a static array, or
2902 * if another slice references elements past the end of the current slice.
2903 *
2904 * Note: The _capacity of a slice may be impacted by operations on other slices.
2905 */
2906 @property size_t capacity(T)(T[] arr) pure nothrow @trusted
2907 {
2908 return _d_arraysetcapacity(typeid(T[]), 0, cast(void *)&arr);
2909 }
2910 ///
2911 @safe unittest
2912 {
2913 //Static array slice: no capacity
2914 int[4] sarray = [1, 2, 3, 4];
2915 int[] slice = sarray[];
2916 assert(sarray.capacity == 0);
2917 //Appending to slice will reallocate to a new array
2918 slice ~= 5;
2919 assert(slice.capacity >= 5);
2920
2921 //Dynamic array slices
2922 int[] a = [1, 2, 3, 4];
2923 int[] b = a[1 .. $];
2924 int[] c = a[1 .. $ - 1];
2925 debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation
2926 {
2927 assert(a.capacity != 0);
2928 assert(a.capacity == b.capacity + 1); //both a and b share the same tail
2929 }
2930 assert(c.capacity == 0); //an append to c must relocate c.
2931 }
2932
2933 /**
2934 * Reserves capacity for a slice. The capacity is the size
2935 * that the slice can grow to before the underlying array must be
2936 * reallocated or extended.
2937 *
2938 * Returns: The new capacity of the array (which may be larger than
2939 * the requested capacity).
2940 */
2941 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted
2942 {
2943 return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void *)&arr);
2944 }
2945 ///
2946 unittest
2947 {
2948 //Static array slice: no capacity. Reserve relocates.
2949 int[4] sarray = [1, 2, 3, 4];
2950 int[] slice = sarray[];
2951 auto u = slice.reserve(8);
2952 assert(u >= 8);
2953 assert(sarray.ptr !is slice.ptr);
2954 assert(slice.capacity == u);
2955
2956 //Dynamic array slices
2957 int[] a = [1, 2, 3, 4];
2958 a.reserve(8); //prepare a for appending 4 more items
2959 auto p = a.ptr;
2960 u = a.capacity;
2961 a ~= [5, 6, 7, 8];
2962 assert(p == a.ptr); //a should not have been reallocated
2963 assert(u == a.capacity); //a should not have been extended
2964 }
2965
2966 // Issue 6646: should be possible to use array.reserve from SafeD.
2967 @safe unittest
2968 {
2969 int[] a;
2970 a.reserve(10);
2971 }
2972
2973 /**
2974 * Assume that it is safe to append to this array. Appends made to this array
2975 * after calling this function may append in place, even if the array was a
2976 * slice of a larger array to begin with.
2977 *
2978 * Use this only when it is certain there are no elements in use beyond the
2979 * array in the memory block. If there are, those elements will be
2980 * overwritten by appending to this array.
2981 *
2982 * Warning: Calling this function, and then using references to data located after the
2983 * given array results in undefined behavior.
2984 *
2985 * Returns:
2986 * The input is returned.
2987 */
2988 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow
2989 {
2990 _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr));
2991 return arr;
2992 }
2993 ///
2994 unittest
2995 {
2996 int[] a = [1, 2, 3, 4];
2997
2998 // Without assumeSafeAppend. Appending relocates.
2999 int[] b = a [0 .. 3];
3000 b ~= 5;
3001 assert(a.ptr != b.ptr);
3002
3003 debug(SENTINEL) {} else
3004 {
3005 // With assumeSafeAppend. Appending overwrites.
3006 int[] c = a [0 .. 3];
3007 c.assumeSafeAppend() ~= 5;
3008 assert(a.ptr == c.ptr);
3009 }
3010 }
3011
3012 unittest
3013 {
3014 int[] arr;
3015 auto newcap = arr.reserve(2000);
3016 assert(newcap >= 2000);
3017 assert(newcap == arr.capacity);
3018 auto ptr = arr.ptr;
3019 foreach (i; 0..2000)
3020 arr ~= i;
3021 assert(ptr == arr.ptr);
3022 arr = arr[0..1];
3023 arr.assumeSafeAppend();
3024 arr ~= 5;
3025 assert(ptr == arr.ptr);
3026 }
3027
3028 unittest
3029 {
3030 int[] arr = [1, 2, 3];
3031 void foo(ref int[] i)
3032 {
3033 i ~= 5;
3034 }
3035 arr = arr[0 .. 2];
3036 foo(assumeSafeAppend(arr)); //pass by ref
3037 assert(arr[]==[1, 2, 5]);
3038 arr = arr[0 .. 1].assumeSafeAppend(); //pass by value
3039 }
3040
3041 // https://issues.dlang.org/show_bug.cgi?id=10574
3042 unittest
3043 {
3044 int[] a;
3045 immutable(int[]) b;
3046 auto a2 = &assumeSafeAppend(a);
3047 auto b2 = &assumeSafeAppend(b);
3048 auto a3 = assumeSafeAppend(a[]);
3049 auto b3 = assumeSafeAppend(b[]);
3050 assert(is(typeof(*a2) == int[]));
3051 assert(is(typeof(*b2) == immutable(int[])));
3052 assert(is(typeof(a3) == int[]));
3053 assert(is(typeof(b3) == immutable(int[])));
3054 }
3055
3056 version (none)
3057 {
3058 // enforce() copied from Phobos std.contracts for destroy(), left out until
3059 // we decide whether to use it.
3060
3061
3062 T _enforce(T, string file = __FILE__, int line = __LINE__)
3063 (T value, lazy const(char)[] msg = null)
3064 {
3065 if (!value) bailOut(file, line, msg);
3066 return value;
3067 }
3068
3069 T _enforce(T, string file = __FILE__, int line = __LINE__)
3070 (T value, scope void delegate() dg)
3071 {
3072 if (!value) dg();
3073 return value;
3074 }
3075
3076 T _enforce(T)(T value, lazy Exception ex)
3077 {
3078 if (!value) throw ex();
3079 return value;
3080 }
3081
3082 private void _bailOut(string file, int line, in char[] msg)
3083 {
3084 char[21] buf;
3085 throw new Exception(cast(string)(file ~ "(" ~ ulongToString(buf[], line) ~ "): " ~ (msg ? msg : "Enforcement failed")));
3086 }
3087 }
3088
3089
3090 /***************************************
3091 * Helper function used to see if two containers of different
3092 * types have the same contents in the same sequence.
3093 */
3094
3095 bool _ArrayEq(T1, T2)(T1[] a1, T2[] a2)
3096 {
3097 if (a1.length != a2.length)
3098 return false;
3099
3100 // This is function is used as a compiler intrinsic and explicitly written
3101 // in a lowered flavor to use as few CTFE instructions as possible.
3102 size_t idx = 0;
3103 immutable length = a1.length;
3104
3105 for (;idx < length;++idx)
3106 {
3107 if (a1[idx] != a2[idx])
3108 return false;
3109 }
3110 return true;
3111 }
3112
3113 version (D_Ddoc)
3114 {
3115 // This lets DDoc produce better documentation.
3116
3117 /**
3118 Calculates the hash value of `arg` with an optional `seed` initial value.
3119 The result might not be equal to `typeid(T).getHash(&arg)`.
3120
3121 Params:
3122 arg = argument to calculate the hash value of
3123 seed = optional `seed` value (may be used for hash chaining)
3124
3125 Return: calculated hash value of `arg`
3126 */
3127 size_t hashOf(T)(auto ref T arg, size_t seed)
3128 {
3129 static import core.internal.hash;
3130 return core.internal.hash.hashOf(arg, seed);
3131 }
3132 /// ditto
3133 size_t hashOf(T)(auto ref T arg)
3134 {
3135 static import core.internal.hash;
3136 return core.internal.hash.hashOf(arg);
3137 }
3138 }
3139 else
3140 {
3141 public import core.internal.hash : hashOf;
3142 }
3143
3144 unittest
3145 {
3146 // Issue # 16654 / 16764
3147 auto a = [1];
3148 auto b = a.dup;
3149 assert(hashOf(a) == hashOf(b));
3150 }
3151
3152 bool _xopEquals(in void*, in void*)
3153 {
3154 throw new Error("TypeInfo.equals is not implemented");
3155 }
3156
3157 bool _xopCmp(in void*, in void*)
3158 {
3159 throw new Error("TypeInfo.compare is not implemented");
3160 }
3161
3162 void __ctfeWrite(const string s) @nogc @safe pure nothrow {}
3163
3164 /******************************************
3165 * Create RTInfo for type T
3166 */
3167
3168 template RTInfo(T)
3169 {
3170 enum RTInfo = null;
3171 }
3172
3173 // lhs == rhs lowers to __equals(lhs, rhs) for dynamic arrays
3174 bool __equals(T1, T2)(T1[] lhs, T2[] rhs)
3175 {
3176 import core.internal.traits : Unqual;
3177 alias U1 = Unqual!T1;
3178 alias U2 = Unqual!T2;
3179
3180 static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
3181 static @trusted R trustedCast(R, S)(S[] r) { return cast(R) r; }
3182
3183 if (lhs.length != rhs.length)
3184 return false;
3185
3186 if (lhs.length == 0 && rhs.length == 0)
3187 return true;
3188
3189 static if (is(U1 == void) && is(U2 == void))
3190 {
3191 return __equals(trustedCast!(ubyte[])(lhs), trustedCast!(ubyte[])(rhs));
3192 }
3193 else static if (is(U1 == void))
3194 {
3195 return __equals(trustedCast!(ubyte[])(lhs), rhs);
3196 }
3197 else static if (is(U2 == void))
3198 {
3199 return __equals(lhs, trustedCast!(ubyte[])(rhs));
3200 }
3201 else static if (!is(U1 == U2))
3202 {
3203 // This should replace src/object.d _ArrayEq which
3204 // compares arrays of different types such as long & int,
3205 // char & wchar.
3206 // Compiler lowers to __ArrayEq in dmd/src/opover.d
3207 foreach (const u; 0 .. lhs.length)
3208 {
3209 if (at(lhs, u) != at(rhs, u))
3210 return false;
3211 }
3212 return true;
3213 }
3214 else static if (__traits(isIntegral, U1))
3215 {
3216
3217 if (!__ctfe)
3218 {
3219 import core.stdc.string : memcmp;
3220 return () @trusted { return memcmp(cast(void*)lhs.ptr, cast(void*)rhs.ptr, lhs.length * U1.sizeof) == 0; }();
3221 }
3222 else
3223 {
3224 foreach (const u; 0 .. lhs.length)
3225 {
3226 if (at(lhs, u) != at(rhs, u))
3227 return false;
3228 }
3229 return true;
3230 }
3231 }
3232 else
3233 {
3234 foreach (const u; 0 .. lhs.length)
3235 {
3236 static if (__traits(compiles, __equals(at(lhs, u), at(rhs, u))))
3237 {
3238 if (!__equals(at(lhs, u), at(rhs, u)))
3239 return false;
3240 }
3241 else static if (__traits(isFloating, U1))
3242 {
3243 if (at(lhs, u) != at(rhs, u))
3244 return false;
3245 }
3246 else static if (is(U1 : Object) && is(U2 : Object))
3247 {
3248 if (!(cast(Object)at(lhs, u) is cast(Object)at(rhs, u)
3249 || at(lhs, u) && (cast(Object)at(lhs, u)).opEquals(cast(Object)at(rhs, u))))
3250 return false;
3251 }
3252 else static if (__traits(hasMember, U1, "opEquals"))
3253 {
3254 if (!at(lhs, u).opEquals(at(rhs, u)))
3255 return false;
3256 }
3257 else static if (is(U1 == delegate))
3258 {
3259 if (at(lhs, u) != at(rhs, u))
3260 return false;
3261 }
3262 else static if (is(U1 == U11*, U11))
3263 {
3264 if (at(lhs, u) != at(rhs, u))
3265 return false;
3266 }
3267 else
3268 {
3269 if (at(lhs, u).tupleof != at(rhs, u).tupleof)
3270 return false;
3271 }
3272 }
3273
3274 return true;
3275 }
3276 }
3277
3278 unittest {
3279 assert(__equals([], []));
3280 assert(!__equals([1, 2], [1, 2, 3]));
3281 }
3282
3283 unittest
3284 {
3285 struct A
3286 {
3287 int a;
3288 }
3289
3290 auto arr1 = [A(0), A(2)];
3291 auto arr2 = [A(0), A(1)];
3292 auto arr3 = [A(0), A(1)];
3293
3294 assert(arr1 != arr2);
3295 assert(arr2 == arr3);
3296 }
3297
3298 unittest
3299 {
3300 struct A
3301 {
3302 int a;
3303 int b;
3304
3305 bool opEquals(const A other)
3306 {
3307 return this.a == other.b && this.b == other.a;
3308 }
3309 }
3310
3311 auto arr1 = [A(1, 0), A(0, 1)];
3312 auto arr2 = [A(1, 0), A(0, 1)];
3313 auto arr3 = [A(0, 1), A(1, 0)];
3314
3315 assert(arr1 != arr2);
3316 assert(arr2 == arr3);
3317 }
3318
3319 // Compare class and interface objects for ordering.
3320 private int __cmp(Obj)(Obj lhs, Obj rhs)
3321 if (is(Obj : Object))
3322 {
3323 if (lhs is rhs)
3324 return 0;
3325 // Regard null references as always being "less than"
3326 if (!lhs)
3327 return -1;
3328 if (!rhs)
3329 return 1;
3330 return lhs.opCmp(rhs);
3331 }
3332
3333 int __cmp(T)(const T[] lhs, const T[] rhs) @trusted
3334 if (__traits(isScalar, T))
3335 {
3336 // Compute U as the implementation type for T
3337 static if (is(T == ubyte) || is(T == void) || is(T == bool))
3338 alias U = char;
3339 else static if (is(T == wchar))
3340 alias U = ushort;
3341 else static if (is(T == dchar))
3342 alias U = uint;
3343 else static if (is(T == ifloat))
3344 alias U = float;
3345 else static if (is(T == idouble))
3346 alias U = double;
3347 else static if (is(T == ireal))
3348 alias U = real;
3349 else
3350 alias U = T;
3351
3352 static if (is(U == char))
3353 {
3354 import core.internal.string : dstrcmp;
3355 return dstrcmp(cast(char[]) lhs, cast(char[]) rhs);
3356 }
3357 else static if (!is(U == T))
3358 {
3359 // Reuse another implementation
3360 return __cmp(cast(U[]) lhs, cast(U[]) rhs);
3361 }
3362 else
3363 {
3364 immutable len = lhs.length <= rhs.length ? lhs.length : rhs.length;
3365 foreach (const u; 0 .. len)
3366 {
3367 static if (__traits(isFloating, T))
3368 {
3369 immutable a = lhs.ptr[u], b = rhs.ptr[u];
3370 static if (is(T == cfloat) || is(T == cdouble)
3371 || is(T == creal))
3372 {
3373 // Use rt.cmath2._Ccmp instead ?
3374 auto r = (a.re > b.re) - (a.re < b.re);
3375 if (!r) r = (a.im > b.im) - (a.im < b.im);
3376 }
3377 else
3378 {
3379 const r = (a > b) - (a < b);
3380 }
3381 if (r) return r;
3382 }
3383 else if (lhs.ptr[u] != rhs.ptr[u])
3384 return lhs.ptr[u] < rhs.ptr[u] ? -1 : 1;
3385 }
3386 return lhs.length < rhs.length ? -1 : (lhs.length > rhs.length);
3387 }
3388 }
3389
3390 // This function is called by the compiler when dealing with array
3391 // comparisons in the semantic analysis phase of CmpExp. The ordering
3392 // comparison is lowered to a call to this template.
3393 int __cmp(T1, T2)(T1[] s1, T2[] s2)
3394 if (!__traits(isScalar, T1) && !__traits(isScalar, T2))
3395 {
3396 import core.internal.traits : Unqual;
3397 alias U1 = Unqual!T1;
3398 alias U2 = Unqual!T2;
3399
3400 static if (is(U1 == void) && is(U2 == void))
3401 static @trusted ref inout(ubyte) at(inout(void)[] r, size_t i) { return (cast(inout(ubyte)*) r.ptr)[i]; }
3402 else
3403 static @trusted ref R at(R)(R[] r, size_t i) { return r.ptr[i]; }
3404
3405 // All unsigned byte-wide types = > dstrcmp
3406 immutable len = s1.length <= s2.length ? s1.length : s2.length;
3407
3408 foreach (const u; 0 .. len)
3409 {
3410 static if (__traits(compiles, __cmp(at(s1, u), at(s2, u))))
3411 {
3412 auto c = __cmp(at(s1, u), at(s2, u));
3413 if (c != 0)
3414 return c;
3415 }
3416 else static if (__traits(compiles, at(s1, u).opCmp(at(s2, u))))
3417 {
3418 auto c = at(s1, u).opCmp(at(s2, u));
3419 if (c != 0)
3420 return c;
3421 }
3422 else static if (__traits(compiles, at(s1, u) < at(s2, u)))
3423 {
3424 if (at(s1, u) != at(s2, u))
3425 return at(s1, u) < at(s2, u) ? -1 : 1;
3426 }
3427 else
3428 {
3429 // TODO: fix this legacy bad behavior, see
3430 // https://issues.dlang.org/show_bug.cgi?id=17244
3431 static assert(is(U1 == U2), "Internal error.");
3432 import core.stdc.string : memcmp;
3433 auto c = (() @trusted => memcmp(&at(s1, u), &at(s2, u), U1.sizeof))();
3434 if (c != 0)
3435 return c;
3436 }
3437 }
3438 return s1.length < s2.length ? -1 : (s1.length > s2.length);
3439 }
3440
3441 // integral types
3442 @safe unittest
3443 {
3444 void compareMinMax(T)()
3445 {
3446 T[2] a = [T.max, T.max];
3447 T[2] b = [T.min, T.min];
3448
3449 assert(__cmp(a, b) > 0);
3450 assert(__cmp(b, a) < 0);
3451 }
3452
3453 compareMinMax!int;
3454 compareMinMax!uint;
3455 compareMinMax!long;
3456 compareMinMax!ulong;
3457 compareMinMax!short;
3458 compareMinMax!ushort;
3459 compareMinMax!byte;
3460 compareMinMax!dchar;
3461 compareMinMax!wchar;
3462 }
3463
3464 // char types (dstrcmp)
3465 @safe unittest
3466 {
3467 void compareMinMax(T)()
3468 {
3469 T[2] a = [T.max, T.max];
3470 T[2] b = [T.min, T.min];
3471
3472 assert(__cmp(a, b) > 0);
3473 assert(__cmp(b, a) < 0);
3474 }
3475
3476 compareMinMax!ubyte;
3477 compareMinMax!bool;
3478 compareMinMax!char;
3479 compareMinMax!(const char);
3480
3481 string s1 = "aaaa";
3482 string s2 = "bbbb";
3483 assert(__cmp(s2, s1) > 0);
3484 assert(__cmp(s1, s2) < 0);
3485 }
3486
3487 // fp types
3488 @safe unittest
3489 {
3490 void compareMinMax(T)()
3491 {
3492 T[2] a = [T.max, T.max];
3493 T[2] b = [T.min_normal, T.min_normal];
3494 T[2] c = [T.max, T.min_normal];
3495 T[1] d = [T.max];
3496
3497 assert(__cmp(a, b) > 0);
3498 assert(__cmp(b, a) < 0);
3499 assert(__cmp(a, c) > 0);
3500 assert(__cmp(a, d) > 0);
3501 assert(__cmp(d, c) < 0);
3502 assert(__cmp(c, c) == 0);
3503 }
3504
3505 compareMinMax!real;
3506 compareMinMax!float;
3507 compareMinMax!double;
3508 compareMinMax!ireal;
3509 compareMinMax!ifloat;
3510 compareMinMax!idouble;
3511 compareMinMax!creal;
3512 //compareMinMax!cfloat;
3513 compareMinMax!cdouble;
3514
3515 // qualifiers
3516 compareMinMax!(const real);
3517 compareMinMax!(immutable real);
3518 }
3519
3520 // void[]
3521 @safe unittest
3522 {
3523 void[] a;
3524 const(void)[] b;
3525
3526 (() @trusted
3527 {
3528 a = cast(void[]) "bb";
3529 b = cast(const(void)[]) "aa";
3530 })();
3531
3532 assert(__cmp(a, b) > 0);
3533 assert(__cmp(b, a) < 0);
3534 }
3535
3536 // arrays of arrays with mixed modifiers
3537 @safe unittest
3538 {
3539 // https://issues.dlang.org/show_bug.cgi?id=17876
3540 bool less1(immutable size_t[][] a, size_t[][] b) { return a < b; }
3541 bool less2(const void[][] a, void[][] b) { return a < b; }
3542 bool less3(inout size_t[][] a, size_t[][] b) { return a < b; }
3543
3544 immutable size_t[][] a = [[1, 2], [3, 4]];
3545 size_t[][] b = [[1, 2], [3, 5]];
3546 assert(less1(a, b));
3547 assert(less3(a, b));
3548
3549 auto va = [cast(immutable void[])a[0], a[1]];
3550 auto vb = [cast(void[])b[0], b[1]];
3551 assert(less2(va, vb));
3552 }
3553
3554 // objects
3555 @safe unittest
3556 {
3557 class C
3558 {
3559 int i;
3560 this(int i) { this.i = i; }
3561
3562 override int opCmp(Object c) const @safe
3563 {
3564 return i - (cast(C)c).i;
3565 }
3566 }
3567
3568 auto c1 = new C(1);
3569 auto c2 = new C(2);
3570 assert(__cmp(c1, null) > 0);
3571 assert(__cmp(null, c1) < 0);
3572 assert(__cmp(c1, c1) == 0);
3573 assert(__cmp(c1, c2) < 0);
3574 assert(__cmp(c2, c1) > 0);
3575
3576 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
3577 assert(__cmp([c2, c2], [c1, c1]) > 0);
3578 }
3579
3580 // structs
3581 @safe unittest
3582 {
3583 struct C
3584 {
3585 ubyte i;
3586 this(ubyte i) { this.i = i; }
3587 }
3588
3589 auto c1 = C(1);
3590 auto c2 = C(2);
3591
3592 assert(__cmp([c1, c1][], [c2, c2][]) < 0);
3593 assert(__cmp([c2, c2], [c1, c1]) > 0);
3594 assert(__cmp([c2, c2], [c2, c1]) > 0);
3595 }
3596
3597 // Compiler hook into the runtime implementation of array (vector) operations.
3598 template _arrayOp(Args...)
3599 {
3600 import core.internal.arrayop;
3601 alias _arrayOp = arrayOp!Args;
3602 }
3603
3604 // Helper functions
3605
3606 private inout(TypeInfo) getElement(inout TypeInfo value) @trusted pure nothrow
3607 {
3608 TypeInfo element = cast() value;
3609 for (;;)
3610 {
3611 if (auto qualified = cast(TypeInfo_Const) element)
3612 element = qualified.base;
3613 else if (auto redefined = cast(TypeInfo_Enum) element)
3614 element = redefined.base;
3615 else if (auto staticArray = cast(TypeInfo_StaticArray) element)
3616 element = staticArray.value;
3617 else if (auto vector = cast(TypeInfo_Vector) element)
3618 element = vector.base;
3619 else
3620 break;
3621 }
3622 return cast(inout) element;
3623 }
3624
3625 private size_t getArrayHash(in TypeInfo element, in void* ptr, in size_t count) @trusted nothrow
3626 {
3627 if (!count)
3628 return 0;
3629
3630 const size_t elementSize = element.tsize;
3631 if (!elementSize)
3632 return 0;
3633
3634 static bool hasCustomToHash(in TypeInfo value) @trusted pure nothrow
3635 {
3636 const element = getElement(value);
3637
3638 if (const struct_ = cast(const TypeInfo_Struct) element)
3639 return !!struct_.xtoHash;
3640
3641 return cast(const TypeInfo_Array) element
3642 || cast(const TypeInfo_AssociativeArray) element
3643 || cast(const ClassInfo) element
3644 || cast(const TypeInfo_Interface) element;
3645 }
3646
3647 import core.internal.traits : externDFunc;
3648 if (!hasCustomToHash(element))
3649 return hashOf(ptr[0 .. elementSize * count]);
3650
3651 size_t hash = 0;
3652 foreach (size_t i; 0 .. count)
3653 hash = hashOf(element.getHash(ptr + i * elementSize), hash);
3654 return hash;
3655 }
3656
3657 /// Provide the .dup array property.
3658 @property auto dup(T)(T[] a)
3659 if (!is(const(T) : T))
3660 {
3661 import core.internal.traits : Unconst;
3662 static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~
3663 " to "~Unconst!T.stringof~" in dup.");
3664
3665 // wrap unsafe _dup in @trusted to preserve @safe postblit
3666 static if (__traits(compiles, (T b) @safe { T a = b; }))
3667 return _trustedDup!(T, Unconst!T)(a);
3668 else
3669 return _dup!(T, Unconst!T)(a);
3670 }
3671
3672 /// ditto
3673 // const overload to support implicit conversion to immutable (unique result, see DIP29)
3674 @property T[] dup(T)(const(T)[] a)
3675 if (is(const(T) : T))
3676 {
3677 // wrap unsafe _dup in @trusted to preserve @safe postblit
3678 static if (__traits(compiles, (T b) @safe { T a = b; }))
3679 return _trustedDup!(const(T), T)(a);
3680 else
3681 return _dup!(const(T), T)(a);
3682 }
3683
3684
3685 /// Provide the .idup array property.
3686 @property immutable(T)[] idup(T)(T[] a)
3687 {
3688 static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~
3689 " to immutable in idup.");
3690
3691 // wrap unsafe _dup in @trusted to preserve @safe postblit
3692 static if (__traits(compiles, (T b) @safe { T a = b; }))
3693 return _trustedDup!(T, immutable(T))(a);
3694 else
3695 return _dup!(T, immutable(T))(a);
3696 }
3697
3698 /// ditto
3699 @property immutable(T)[] idup(T:void)(const(T)[] a)
3700 {
3701 return a.dup;
3702 }
3703
3704 private U[] _trustedDup(T, U)(T[] a) @trusted
3705 {
3706 return _dup!(T, U)(a);
3707 }
3708
3709 private U[] _dup(T, U)(T[] a) // pure nothrow depends on postblit
3710 {
3711 if (__ctfe)
3712 {
3713 static if (is(T : void))
3714 assert(0, "Cannot dup a void[] array at compile time.");
3715 else
3716 {
3717 U[] res;
3718 foreach (ref e; a)
3719 res ~= e;
3720 return res;
3721 }
3722 }
3723
3724 import core.stdc.string : memcpy;
3725
3726 void[] arr = _d_newarrayU(typeid(T[]), a.length);
3727 memcpy(arr.ptr, cast(const(void)*)a.ptr, T.sizeof * a.length);
3728 auto res = *cast(U[]*)&arr;
3729
3730 static if (!is(T : void))
3731 _doPostblit(res);
3732 return res;
3733 }
3734
3735 private extern (C) void[] _d_newarrayU(const TypeInfo ti, size_t length) pure nothrow;
3736
3737
3738 /**************
3739 * Get the postblit for type T.
3740 * Returns:
3741 * null if no postblit is necessary
3742 * function pointer for struct postblits
3743 * delegate for class postblits
3744 */
3745 private auto _getPostblit(T)() @trusted pure nothrow @nogc
3746 {
3747 // infer static postblit type, run postblit if any
3748 static if (is(T == struct))
3749 {
3750 import core.internal.traits : Unqual;
3751 // use typeid(Unqual!T) here to skip TypeInfo_Const/Shared/...
3752 alias _PostBlitType = typeof(function (ref T t){ T a = t; });
3753 return cast(_PostBlitType)typeid(Unqual!T).xpostblit;
3754 }
3755 else if ((&typeid(T).postblit).funcptr !is &TypeInfo.postblit)
3756 {
3757 alias _PostBlitType = typeof(delegate (ref T t){ T a = t; });
3758 return cast(_PostBlitType)&typeid(T).postblit;
3759 }
3760 else
3761 return null;
3762 }
3763
3764 private void _doPostblit(T)(T[] arr)
3765 {
3766 // infer static postblit type, run postblit if any
3767 if (auto postblit = _getPostblit!T())
3768 {
3769 foreach (ref elem; arr)
3770 postblit(elem);
3771 }
3772 }
3773
3774 unittest
3775 {
3776 static struct S1 { int* p; }
3777 static struct S2 { @disable this(); }
3778 static struct S3 { @disable this(this); }
3779
3780 int dg1() pure nothrow @safe
3781 {
3782 {
3783 char[] m;
3784 string i;
3785 m = m.dup;
3786 i = i.idup;
3787 m = i.dup;
3788 i = m.idup;
3789 }
3790 {
3791 S1[] m;
3792 immutable(S1)[] i;
3793 m = m.dup;
3794 i = i.idup;
3795 static assert(!is(typeof(m.idup)));
3796 static assert(!is(typeof(i.dup)));
3797 }
3798 {
3799 S3[] m;
3800 immutable(S3)[] i;
3801 static assert(!is(typeof(m.dup)));
3802 static assert(!is(typeof(i.idup)));
3803 }
3804 {
3805 shared(S1)[] m;
3806 m = m.dup;
3807 static assert(!is(typeof(m.idup)));
3808 }
3809 {
3810 int[] a = (inout(int)) { inout(const(int))[] a; return a.dup; }(0);
3811 }
3812 return 1;
3813 }
3814
3815 int dg2() pure nothrow @safe
3816 {
3817 {
3818 S2[] m = [S2.init, S2.init];
3819 immutable(S2)[] i = [S2.init, S2.init];
3820 m = m.dup;
3821 m = i.dup;
3822 i = m.idup;
3823 i = i.idup;
3824 }
3825 return 2;
3826 }
3827
3828 enum a = dg1();
3829 enum b = dg2();
3830 assert(dg1() == a);
3831 assert(dg2() == b);
3832 }
3833
3834 unittest
3835 {
3836 static struct Sunpure { this(this) @safe nothrow {} }
3837 static struct Sthrow { this(this) @safe pure {} }
3838 static struct Sunsafe { this(this) @system pure nothrow {} }
3839
3840 static assert( __traits(compiles, () { [].dup!Sunpure; }));
3841 static assert(!__traits(compiles, () pure { [].dup!Sunpure; }));
3842 static assert( __traits(compiles, () { [].dup!Sthrow; }));
3843 static assert(!__traits(compiles, () nothrow { [].dup!Sthrow; }));
3844 static assert( __traits(compiles, () { [].dup!Sunsafe; }));
3845 static assert(!__traits(compiles, () @safe { [].dup!Sunsafe; }));
3846
3847 static assert( __traits(compiles, () { [].idup!Sunpure; }));
3848 static assert(!__traits(compiles, () pure { [].idup!Sunpure; }));
3849 static assert( __traits(compiles, () { [].idup!Sthrow; }));
3850 static assert(!__traits(compiles, () nothrow { [].idup!Sthrow; }));
3851 static assert( __traits(compiles, () { [].idup!Sunsafe; }));
3852 static assert(!__traits(compiles, () @safe { [].idup!Sunsafe; }));
3853 }
3854
3855 unittest
3856 {
3857 static int*[] pureFoo() pure { return null; }
3858 { char[] s; immutable x = s.dup; }
3859 { immutable x = (cast(int*[])null).dup; }
3860 { immutable x = pureFoo(); }
3861 { immutable x = pureFoo().dup; }
3862 }
3863
3864 unittest
3865 {
3866 auto a = [1, 2, 3];
3867 auto b = a.dup;
3868 debug(SENTINEL) {} else
3869 assert(b.capacity >= 3);
3870 }
3871
3872 unittest
3873 {
3874 // Bugzilla 12580
3875 void[] m = [0];
3876 shared(void)[] s = [cast(shared)1];
3877 immutable(void)[] i = [cast(immutable)2];
3878
3879 s = s.dup;
3880 static assert(is(typeof(s.dup) == shared(void)[]));
3881
3882 m = i.dup;
3883 i = m.dup;
3884 i = i.idup;
3885 i = m.idup;
3886 i = s.idup;
3887 i = s.dup;
3888 static assert(!__traits(compiles, m = s.dup));
3889 }
3890
3891 unittest
3892 {
3893 // Bugzilla 13809
3894 static struct S
3895 {
3896 this(this) {}
3897 ~this() {}
3898 }
3899
3900 S[] arr;
3901 auto a = arr.dup;
3902 }
3903
3904 unittest
3905 {
3906 // Bugzilla 16504
3907 static struct S
3908 {
3909 __gshared int* gp;
3910 int* p;
3911 // postblit and hence .dup could escape
3912 this(this) { gp = p; }
3913 }
3914
3915 int p;
3916 scope arr = [S(&p)];
3917 auto a = arr.dup; // dup does escape
3918 }
3919
3920 // compiler frontend lowers dynamic array comparison to this
3921 bool __ArrayEq(T1, T2)(T1[] a, T2[] b)
3922 {
3923 if (a.length != b.length)
3924 return false;
3925 foreach (size_t i; 0 .. a.length)
3926 {
3927 if (a[i] != b[i])
3928 return false;
3929 }
3930 return true;
3931 }
3932
3933 // compiler frontend lowers struct array postblitting to this
3934 void __ArrayPostblit(T)(T[] a)
3935 {
3936 foreach (ref T e; a)
3937 e.__xpostblit();
3938 }
3939
3940 // compiler frontend lowers dynamic array deconstruction to this
3941 void __ArrayDtor(T)(T[] a)
3942 {
3943 foreach_reverse (ref T e; a)
3944 e.__xdtor();
3945 }