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