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