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