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 } 3946