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