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 private Throwable nextInChain; 2576 2577 private uint _refcount; // 0 : allocated by GC 2578 // 1 : allocated by _d_newThrowable() 2579 // 2.. : reference count + 1 2580 2581 /** 2582 * Returns: 2583 * A reference to the _next error in the list. This is used when a new 2584 * $(D Throwable) is thrown from inside a $(D catch) block. The originally 2585 * caught $(D Exception) will be chained to the new $(D Throwable) via this 2586 * field. 2587 */ 2588 @property inout(Throwable) next() @safe inout return scope pure nothrow @nogc { return nextInChain; } 2589 2590 /** 2591 * Replace next in chain with `tail`. 2592 * Use `chainTogether` instead if at all possible. 2593 */ 2594 @property void next(Throwable tail) @safe scope pure nothrow @nogc 2595 { 2596 if (tail && tail._refcount) 2597 ++tail._refcount; // increment the replacement *first* 2598 2599 auto n = nextInChain; 2600 nextInChain = null; // sever the tail before deleting it 2601 2602 if (n && n._refcount) 2603 _d_delThrowable(n); // now delete the old tail 2604 2605 nextInChain = tail; // and set the new tail 2606 } 2607 2608 /** 2609 * Returns: 2610 * mutable reference to the reference count, which is 2611 * 0 - allocated by the GC, 1 - allocated by _d_newThrowable(), 2612 * and >=2 which is the reference count + 1 2613 * Note: 2614 * Marked as `@system` to discourage casual use of it. 2615 */ 2616 @system @nogc final pure nothrow ref uint refcount() return { return _refcount; } 2617 2618 /** 2619 * Loop over the chain of Throwables. 2620 */ 2621 int opApply(scope int delegate(Throwable) dg) 2622 { 2623 int result = 0; 2624 for (Throwable t = this; t; t = t.nextInChain) 2625 { 2626 result = dg(t); 2627 if (result) 2628 break; 2629 } 2630 return result; 2631 } 2632 2633 /** 2634 * Append `e2` to chain of exceptions that starts with `e1`. 2635 * Params: 2636 * e1 = start of chain (can be null) 2637 * e2 = second part of chain (can be null) 2638 * Returns: 2639 * Throwable that is at the start of the chain; null if both `e1` and `e2` are null 2640 */ 2641 static @__future @system @nogc pure nothrow Throwable chainTogether(return scope Throwable e1, return scope Throwable e2) 2642 { 2643 if (!e1) 2644 return e2; 2645 if (!e2) 2646 return e1; 2647 if (e2.refcount()) 2648 ++e2.refcount(); 2649 2650 for (auto e = e1; 1; e = e.nextInChain) 2651 { 2652 if (!e.nextInChain) 2653 { 2654 e.nextInChain = e2; 2655 break; 2656 } 2657 } 2658 return e1; 2659 } 2660 2661 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null) 2662 { 2663 this.msg = msg; 2664 this.nextInChain = nextInChain; 2665 if (nextInChain && nextInChain._refcount) 2666 ++nextInChain._refcount; 2667 //this.info = _d_traceContext(); 2668 } 2669 2670 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null) 2671 { 2672 this(msg, nextInChain); 2673 this.file = file; 2674 this.line = line; 2675 //this.info = _d_traceContext(); 2676 } 2677 2678 @trusted nothrow ~this() 2679 { 2680 if (nextInChain && nextInChain._refcount) 2681 _d_delThrowable(nextInChain); 2682 // handle owned traceinfo 2683 if (infoDeallocator !is null) 2684 { 2685 infoDeallocator(info); 2686 info = null; // avoid any kind of dangling pointers if we can help 2687 // it. 2688 } 2689 } 2690 2691 /** 2692 * Overrides $(D Object.toString) and returns the error message. 2693 * Internally this forwards to the $(D toString) overload that 2694 * takes a $(D_PARAM sink) delegate. 2695 */ 2696 override string toString() 2697 { 2698 string s; 2699 toString((in buf) { s ~= buf; }); 2700 return s; 2701 } 2702 2703 /** 2704 * The Throwable hierarchy uses a toString overload that takes a 2705 * $(D_PARAM _sink) delegate to avoid GC allocations, which cannot be 2706 * performed in certain error situations. Override this $(D 2707 * toString) method to customize the error message. 2708 */ 2709 void toString(scope void delegate(in char[]) sink) @system const 2710 { 2711 import core.internal.string : unsignedToTempString; 2712 2713 char[20] tmpBuff = void; 2714 2715 sink(typeid(this).name); 2716 sink("@"); sink(file); 2717 sink("("); sink(unsignedToTempString(line, tmpBuff)); sink(")"); 2718 2719 if (msg.length) 2720 { 2721 sink(": "); sink(msg); 2722 } 2723 if (info) 2724 { 2725 try 2726 { 2727 sink("\n----------------"); 2728 foreach (t; info) 2729 { 2730 sink("\n"); sink(t); 2731 } 2732 } 2733 catch (Throwable) 2734 { 2735 // ignore more errors 2736 } 2737 } 2738 } 2739 2740 /** 2741 * Get the message describing the error. 2742 * 2743 * This getter is an alternative way to access the Exception's message, 2744 * with the added advantage of being override-able in subclasses. 2745 * Subclasses are hence free to do their own memory managements without 2746 * being tied to the requirement of providing a `string` in a field. 2747 * 2748 * The default behavior is to return the `Throwable.msg` field. 2749 * 2750 * Returns: 2751 * A message representing the cause of the `Throwable` 2752 */ 2753 @__future const(char)[] message() const @safe nothrow 2754 { 2755 return this.msg; 2756 } 2757 } 2758 2759 2760 /** 2761 * The base class of all errors that are safe to catch and handle. 2762 * 2763 * In principle, only thrown objects derived from this class are safe to catch 2764 * inside a $(D catch) block. Thrown objects not derived from Exception 2765 * represent runtime errors that should not be caught, as certain runtime 2766 * guarantees may not hold, making it unsafe to continue program execution. 2767 */ 2768 class Exception : Throwable 2769 { 2770 2771 /** 2772 * Creates a new instance of Exception. The nextInChain parameter is used 2773 * internally and should always be $(D null) when passed by user code. 2774 * This constructor does not automatically throw the newly-created 2775 * Exception; the $(D throw) expression should be used for that purpose. 2776 */ 2777 @nogc @safe pure nothrow this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable nextInChain = null) 2778 { 2779 super(msg, file, line, nextInChain); 2780 } 2781 2782 @nogc @safe pure nothrow this(string msg, Throwable nextInChain, string file = __FILE__, size_t line = __LINE__) 2783 { 2784 super(msg, file, line, nextInChain); 2785 } 2786 } 2787 2788 /// 2789 @safe unittest 2790 { 2791 bool gotCaught; 2792 try 2793 { 2794 throw new Exception("msg"); 2795 } 2796 catch (Exception e) 2797 { 2798 gotCaught = true; 2799 assert(e.msg == "msg"); 2800 } 2801 assert(gotCaught); 2802 } 2803 2804 @system unittest 2805 { 2806 { 2807 auto e = new Exception("msg"); 2808 assert(e.file == __FILE__); 2809 assert(e.line == __LINE__ - 2); 2810 assert(e.nextInChain is null); 2811 assert(e.msg == "msg"); 2812 } 2813 2814 { 2815 auto e = new Exception("msg", new Exception("It's an Exception!"), "hello", 42); 2816 assert(e.file == "hello"); 2817 assert(e.line == 42); 2818 assert(e.nextInChain !is null); 2819 assert(e.msg == "msg"); 2820 } 2821 2822 { 2823 auto e = new Exception("msg", "hello", 42, new Exception("It's an Exception!")); 2824 assert(e.file == "hello"); 2825 assert(e.line == 42); 2826 assert(e.nextInChain !is null); 2827 assert(e.msg == "msg"); 2828 } 2829 2830 { 2831 auto e = new Exception("message"); 2832 assert(e.message == "message"); 2833 } 2834 } 2835 2836 2837 /** 2838 * The base class of all unrecoverable runtime errors. 2839 * 2840 * This represents the category of $(D Throwable) objects that are $(B not) 2841 * safe to catch and handle. In principle, one should not catch Error 2842 * objects, as they represent unrecoverable runtime errors. 2843 * Certain runtime guarantees may fail to hold when these errors are 2844 * thrown, making it unsafe to continue execution after catching them. 2845 */ 2846 class Error : Throwable 2847 { 2848 /** 2849 * Creates a new instance of Error. The nextInChain parameter is used 2850 * internally and should always be $(D null) when passed by user code. 2851 * This constructor does not automatically throw the newly-created 2852 * Error; the $(D throw) statement should be used for that purpose. 2853 */ 2854 @nogc @safe pure nothrow this(string msg, Throwable nextInChain = null) 2855 { 2856 super(msg, nextInChain); 2857 bypassedException = null; 2858 } 2859 2860 @nogc @safe pure nothrow this(string msg, string file, size_t line, Throwable nextInChain = null) 2861 { 2862 super(msg, file, line, nextInChain); 2863 bypassedException = null; 2864 } 2865 2866 /** The first $(D Exception) which was bypassed when this Error was thrown, 2867 or $(D null) if no $(D Exception)s were pending. */ 2868 Throwable bypassedException; 2869 } 2870 2871 /// 2872 @system unittest 2873 { 2874 bool gotCaught; 2875 try 2876 { 2877 throw new Error("msg"); 2878 } 2879 catch (Error e) 2880 { 2881 gotCaught = true; 2882 assert(e.msg == "msg"); 2883 } 2884 assert(gotCaught); 2885 } 2886 2887 @safe unittest 2888 { 2889 { 2890 auto e = new Error("msg"); 2891 assert(e.file is null); 2892 assert(e.line == 0); 2893 assert(e.nextInChain is null); 2894 assert(e.msg == "msg"); 2895 assert(e.bypassedException is null); 2896 } 2897 2898 { 2899 auto e = new Error("msg", new Exception("It's an Exception!")); 2900 assert(e.file is null); 2901 assert(e.line == 0); 2902 assert(e.nextInChain !is null); 2903 assert(e.msg == "msg"); 2904 assert(e.bypassedException is null); 2905 } 2906 2907 { 2908 auto e = new Error("msg", "hello", 42, new Exception("It's an Exception!")); 2909 assert(e.file == "hello"); 2910 assert(e.line == 42); 2911 assert(e.nextInChain !is null); 2912 assert(e.msg == "msg"); 2913 assert(e.bypassedException is null); 2914 } 2915 } 2916 2917 extern (C) 2918 { 2919 // from druntime/src/rt/aaA.d 2920 2921 version (LDC) 2922 { 2923 /* The real type is (non-importable) `rt.aaA.Impl*`; 2924 * the compiler uses `void*` for its prototypes. 2925 */ 2926 private alias AA = void*; 2927 } 2928 else 2929 { 2930 private struct AA { void* impl; } 2931 } 2932 2933 // size_t _aaLen(in AA aa) pure nothrow @nogc; 2934 private void* _aaGetY(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey) pure nothrow; 2935 private void* _aaGetX(scope AA* paa, const TypeInfo_AssociativeArray ti, const size_t valsz, const scope void* pkey, out bool found) pure nothrow; 2936 // inout(void)* _aaGetRvalueX(inout AA aa, in TypeInfo keyti, in size_t valsz, in void* pkey); 2937 inout(void[]) _aaValues(inout AA aa, const size_t keysz, const size_t valsz, const TypeInfo tiValueArray) pure nothrow; 2938 inout(void[]) _aaKeys(inout AA aa, const size_t keysz, const TypeInfo tiKeyArray) pure nothrow; 2939 void* _aaRehash(AA* paa, const scope TypeInfo keyti) pure nothrow; 2940 void _aaClear(AA aa) pure nothrow; 2941 2942 // alias _dg_t = extern(D) int delegate(void*); 2943 // int _aaApply(AA aa, size_t keysize, _dg_t dg); 2944 2945 // alias _dg2_t = extern(D) int delegate(void*, void*); 2946 // int _aaApply2(AA aa, size_t keysize, _dg2_t dg); 2947 2948 private struct AARange { AA impl; size_t idx; } 2949 AARange _aaRange(AA aa) pure nothrow @nogc @safe; 2950 bool _aaRangeEmpty(AARange r) pure nothrow @nogc @safe; 2951 void* _aaRangeFrontKey(AARange r) pure nothrow @nogc @safe; 2952 void* _aaRangeFrontValue(AARange r) pure nothrow @nogc @safe; 2953 void _aaRangePopFront(ref AARange r) pure nothrow @nogc @safe; 2954 2955 int _aaEqual(scope const TypeInfo tiRaw, scope const AA aa1, scope const AA aa2); 2956 hash_t _aaGetHash(scope const AA* aa, scope const TypeInfo tiRaw) nothrow; 2957 2958 /* 2959 _d_assocarrayliteralTX marked as pure, because aaLiteral can be called from pure code. 2960 This is a typesystem hole, however this is existing hole. 2961 Early compiler didn't check purity of toHash or postblit functions, if key is a UDT thus 2962 copiler allowed to create AA literal with keys, which have impure unsafe toHash methods. 2963 */ 2964 void* _d_assocarrayliteralTX(const TypeInfo_AssociativeArray ti, void[] keys, void[] values) pure; 2965 } 2966 2967 void* aaLiteral(Key, Value)(Key[] keys, Value[] values) @trusted pure 2968 { 2969 return _d_assocarrayliteralTX(typeid(Value[Key]), *cast(void[]*)&keys, *cast(void[]*)&values); 2970 } 2971 2972 // Lower an Associative Array to a newaa struct for static initialization. 2973 auto _aaAsStruct(K, V)(V[K] aa) @safe 2974 { 2975 import core.internal.newaa : makeAA; 2976 assert(__ctfe); 2977 return makeAA!(K, V)(aa); 2978 } 2979 2980 alias AssociativeArray(Key, Value) = Value[Key]; 2981 2982 /*********************************** 2983 * Removes all remaining keys and values from an associative array. 2984 * Params: 2985 * aa = The associative array. 2986 */ 2987 void clear(Value, Key)(Value[Key] aa) @trusted 2988 { 2989 _aaClear(*cast(AA *) &aa); 2990 } 2991 2992 /** ditto */ 2993 void clear(Value, Key)(Value[Key]* aa) @trusted 2994 { 2995 _aaClear(*cast(AA *) aa); 2996 } 2997 2998 /// 2999 @safe unittest 3000 { 3001 auto aa = ["k1": 2]; 3002 aa.clear; 3003 assert("k1" !in aa); 3004 } 3005 3006 // Issue 20559 3007 @system unittest 3008 { 3009 static class Foo 3010 { 3011 int[string] aa; 3012 alias aa this; 3013 } 3014 3015 auto v = new Foo(); 3016 v["Hello World"] = 42; 3017 v.clear; 3018 assert("Hello World" !in v); 3019 3020 // Test for T* 3021 static assert(!__traits(compiles, (&v).clear)); 3022 static assert( __traits(compiles, (*(&v)).clear)); 3023 } 3024 3025 /*********************************** 3026 * Reorganizes the associative array in place so that lookups are more 3027 * efficient. 3028 * Params: 3029 * aa = The associative array. 3030 * Returns: 3031 * The rehashed associative array. 3032 */ 3033 T rehash(T : Value[Key], Value, Key)(T aa) 3034 { 3035 _aaRehash(cast(AA*)&aa, typeid(Value[Key])); 3036 return aa; 3037 } 3038 3039 /** ditto */ 3040 T rehash(T : Value[Key], Value, Key)(T* aa) 3041 { 3042 _aaRehash(cast(AA*)aa, typeid(Value[Key])); 3043 return *aa; 3044 } 3045 3046 /** ditto */ 3047 T rehash(T : shared Value[Key], Value, Key)(T aa) 3048 { 3049 _aaRehash(cast(AA*)&aa, typeid(Value[Key])); 3050 return aa; 3051 } 3052 3053 /** ditto */ 3054 T rehash(T : shared Value[Key], Value, Key)(T* aa) 3055 { 3056 _aaRehash(cast(AA*)aa, typeid(Value[Key])); 3057 return *aa; 3058 } 3059 3060 /*********************************** 3061 * Creates a new associative array of the same size and copies the contents of 3062 * the associative array into it. 3063 * Params: 3064 * aa = The associative array. 3065 */ 3066 V[K] dup(T : V[K], K, V)(T aa) 3067 { 3068 //pragma(msg, "K = ", K, ", V = ", V); 3069 3070 // Bug10720 - check whether V is copyable 3071 static assert(is(typeof({ V v = aa[K.init]; })), 3072 "cannot call " ~ T.stringof ~ ".dup because " ~ V.stringof ~ " is not copyable"); 3073 3074 V[K] result; 3075 3076 //foreach (k, ref v; aa) 3077 // result[k] = v; // Bug13701 - won't work if V is not mutable 3078 3079 ref V duplicateElem(ref K k, ref const V v) @trusted pure nothrow 3080 { 3081 import core.stdc.string : memcpy; 3082 3083 void* pv = _aaGetY(cast(AA*)&result, typeid(V[K]), V.sizeof, &k); 3084 memcpy(pv, &v, V.sizeof); 3085 return *cast(V*)pv; 3086 } 3087 3088 foreach (k, ref v; aa) 3089 { 3090 static if (!__traits(hasPostblit, V)) 3091 duplicateElem(k, v); 3092 else static if (__traits(isStaticArray, V)) 3093 _doPostblit(duplicateElem(k, v)[]); 3094 else static if (!is(typeof(v.__xpostblit())) && is(immutable V == immutable UV, UV)) 3095 (() @trusted => *cast(UV*) &duplicateElem(k, v))().__xpostblit(); 3096 else 3097 duplicateElem(k, v).__xpostblit(); 3098 } 3099 3100 return result; 3101 } 3102 3103 /** ditto */ 3104 V[K] dup(T : V[K], K, V)(T* aa) 3105 { 3106 return (*aa).dup; 3107 } 3108 3109 /// 3110 @safe unittest 3111 { 3112 auto aa = ["k1": 2]; 3113 auto a2 = aa.dup; 3114 aa["k2"] = 3; 3115 assert("k2" !in a2); 3116 } 3117 3118 // this should never be made public. 3119 private AARange _aaToRange(T: V[K], K, V)(ref T aa) pure nothrow @nogc @safe 3120 { 3121 // ensure we are dealing with a genuine AA. 3122 static if (is(const(V[K]) == const(T))) 3123 alias realAA = aa; 3124 else 3125 const(V[K]) realAA = aa; 3126 return _aaRange(() @trusted { return *cast(AA*)&realAA; } ()); 3127 } 3128 3129 /*********************************** 3130 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) 3131 * which will iterate over the keys of the associative array. The keys are 3132 * returned by reference. 3133 * 3134 * If structural changes are made to the array (removing or adding keys), all 3135 * ranges previously obtained through this function are invalidated. The 3136 * following example program will dereference a null pointer: 3137 * 3138 *--- 3139 * import std.stdio : writeln; 3140 * 3141 * auto dict = ["k1": 1, "k2": 2]; 3142 * auto keyRange = dict.byKey; 3143 * dict.clear; 3144 * writeln(keyRange.front); // Segmentation fault 3145 *--- 3146 * 3147 * Params: 3148 * aa = The associative array. 3149 * Returns: 3150 * A forward range referencing the keys of the associative array. 3151 */ 3152 auto byKey(T : V[K], K, V)(T aa) pure nothrow @nogc @safe 3153 { 3154 import core.internal.traits : substInout; 3155 3156 static struct Result 3157 { 3158 AARange r; 3159 3160 pure nothrow @nogc: 3161 @property bool empty() @safe { return _aaRangeEmpty(r); } 3162 @property ref front() @trusted 3163 { 3164 return *cast(substInout!K*) _aaRangeFrontKey(r); 3165 } 3166 void popFront() @safe { _aaRangePopFront(r); } 3167 @property Result save() { return this; } 3168 } 3169 3170 return Result(_aaToRange(aa)); 3171 } 3172 3173 /** ditto */ 3174 auto byKey(T : V[K], K, V)(T* aa) pure nothrow @nogc 3175 { 3176 return (*aa).byKey(); 3177 } 3178 3179 /// 3180 @safe unittest 3181 { 3182 auto dict = [1: "v1", 2: "v2"]; 3183 int sum; 3184 foreach (v; dict.byKey) 3185 sum += v; 3186 3187 assert(sum == 3); 3188 } 3189 3190 /*********************************** 3191 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) 3192 * which will iterate over the values of the associative array. The values are 3193 * returned by reference. 3194 * 3195 * If structural changes are made to the array (removing or adding keys), all 3196 * ranges previously obtained through this function are invalidated. The 3197 * following example program will dereference a null pointer: 3198 * 3199 *--- 3200 * import std.stdio : writeln; 3201 * 3202 * auto dict = ["k1": 1, "k2": 2]; 3203 * auto valueRange = dict.byValue; 3204 * dict.clear; 3205 * writeln(valueRange.front); // Segmentation fault 3206 *--- 3207 * 3208 * Params: 3209 * aa = The associative array. 3210 * Returns: 3211 * A forward range referencing the values of the associative array. 3212 */ 3213 auto byValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe 3214 { 3215 import core.internal.traits : substInout; 3216 3217 static struct Result 3218 { 3219 AARange r; 3220 3221 pure nothrow @nogc: 3222 @property bool empty() @safe { return _aaRangeEmpty(r); } 3223 @property ref front() @trusted 3224 { 3225 return *cast(substInout!V*) _aaRangeFrontValue(r); 3226 } 3227 void popFront() @safe { _aaRangePopFront(r); } 3228 @property Result save() { return this; } 3229 } 3230 3231 return Result(_aaToRange(aa)); 3232 } 3233 3234 /** ditto */ 3235 auto byValue(T : V[K], K, V)(T* aa) pure nothrow @nogc 3236 { 3237 return (*aa).byValue(); 3238 } 3239 3240 /// 3241 @safe unittest 3242 { 3243 auto dict = ["k1": 1, "k2": 2]; 3244 int sum; 3245 foreach (v; dict.byValue) 3246 sum += v; 3247 3248 assert(sum == 3); 3249 } 3250 3251 /*********************************** 3252 * Returns a $(REF_ALTTEXT forward range, isForwardRange, std,range,primitives) 3253 * which will iterate over the key-value pairs of the associative array. The 3254 * returned pairs are represented by an opaque type with `.key` and `.value` 3255 * properties for accessing references to the key and value of the pair, 3256 * respectively. 3257 * 3258 * If structural changes are made to the array (removing or adding keys), all 3259 * ranges previously obtained through this function are invalidated. The 3260 * following example program will dereference a null pointer: 3261 * 3262 *--- 3263 * import std.stdio : writeln; 3264 * 3265 * auto dict = ["k1": 1, "k2": 2]; 3266 * auto kvRange = dict.byKeyValue; 3267 * dict.clear; 3268 * writeln(kvRange.front.key, ": ", kvRange.front.value); // Segmentation fault 3269 *--- 3270 * 3271 * Note that this is a low-level interface to iterating over the associative 3272 * array and is not compatible withth the 3273 * $(LINK2 $(ROOT_DIR)phobos/std_typecons.html#.Tuple,`Tuple`) type in Phobos. 3274 * For compatibility with `Tuple`, use 3275 * $(LINK2 $(ROOT_DIR)phobos/std_array.html#.byPair,std.array.byPair) instead. 3276 * 3277 * Params: 3278 * aa = The associative array. 3279 * Returns: 3280 * A forward range referencing the pairs of the associative array. 3281 */ 3282 auto byKeyValue(T : V[K], K, V)(T aa) pure nothrow @nogc @safe 3283 { 3284 import core.internal.traits : substInout; 3285 3286 static struct Result 3287 { 3288 AARange r; 3289 3290 pure nothrow @nogc: 3291 @property bool empty() @safe { return _aaRangeEmpty(r); } 3292 @property auto front() 3293 { 3294 static struct Pair 3295 { 3296 // We save the pointers here so that the Pair we return 3297 // won't mutate when Result.popFront is called afterwards. 3298 private void* keyp; 3299 private void* valp; 3300 3301 @property ref key() inout @trusted 3302 { 3303 return *cast(substInout!K*) keyp; 3304 } 3305 @property ref value() inout @trusted 3306 { 3307 return *cast(substInout!V*) valp; 3308 } 3309 } 3310 return Pair(_aaRangeFrontKey(r), 3311 _aaRangeFrontValue(r)); 3312 } 3313 void popFront() @safe { return _aaRangePopFront(r); } 3314 @property Result save() { return this; } 3315 } 3316 3317 return Result(_aaToRange(aa)); 3318 } 3319 3320 /** ditto */ 3321 auto byKeyValue(T : V[K], K, V)(T* aa) pure nothrow @nogc 3322 { 3323 return (*aa).byKeyValue(); 3324 } 3325 3326 /// 3327 @safe unittest 3328 { 3329 auto dict = ["k1": 1, "k2": 2]; 3330 int sum; 3331 foreach (e; dict.byKeyValue) 3332 { 3333 assert(e.key[1] == e.value + '0'); 3334 sum += e.value; 3335 } 3336 3337 assert(sum == 3); 3338 } 3339 3340 /*********************************** 3341 * Returns a newly allocated dynamic array containing a copy of the keys from 3342 * the associative array. 3343 * Params: 3344 * aa = The associative array. 3345 * Returns: 3346 * A dynamic array containing a copy of the keys. 3347 */ 3348 Key[] keys(T : Value[Key], Value, Key)(T aa) @property 3349 { 3350 // ensure we are dealing with a genuine AA. 3351 static if (is(const(Value[Key]) == const(T))) 3352 alias realAA = aa; 3353 else 3354 const(Value[Key]) realAA = aa; 3355 auto res = () @trusted { 3356 auto a = cast(void[])_aaKeys(*cast(inout(AA)*)&realAA, Key.sizeof, typeid(Key[])); 3357 return *cast(Key[]*)&a; 3358 }(); 3359 static if (__traits(hasPostblit, Key)) 3360 _doPostblit(res); 3361 return res; 3362 } 3363 3364 /** ditto */ 3365 Key[] keys(T : Value[Key], Value, Key)(T *aa) @property 3366 { 3367 return (*aa).keys; 3368 } 3369 3370 /// 3371 @safe unittest 3372 { 3373 auto aa = [1: "v1", 2: "v2"]; 3374 int sum; 3375 foreach (k; aa.keys) 3376 sum += k; 3377 3378 assert(sum == 3); 3379 } 3380 3381 @safe unittest 3382 { 3383 static struct S 3384 { 3385 string str; 3386 void[][string] dict; 3387 alias dict this; 3388 } 3389 3390 auto s = S("a"); 3391 assert(s.keys.length == 0); 3392 } 3393 3394 @safe unittest 3395 { 3396 @safe static struct Key 3397 { 3398 string str; 3399 this(this) @safe {} 3400 } 3401 string[Key] aa; 3402 static assert(__traits(compiles, { 3403 void test() @safe { 3404 const _ = aa.keys; 3405 } 3406 })); 3407 } 3408 3409 @safe unittest 3410 { 3411 static struct Key 3412 { 3413 string str; 3414 this(this) @system {} 3415 } 3416 string[Key] aa; 3417 static assert(!__traits(compiles, { 3418 void test() @safe { 3419 const _ = aa.keys; 3420 } 3421 })); 3422 } 3423 3424 /*********************************** 3425 * Returns a newly allocated dynamic array containing a copy of the values from 3426 * the associative array. 3427 * Params: 3428 * aa = The associative array. 3429 * Returns: 3430 * A dynamic array containing a copy of the values. 3431 */ 3432 Value[] values(T : Value[Key], Value, Key)(T aa) @property 3433 { 3434 // ensure we are dealing with a genuine AA. 3435 static if (is(const(Value[Key]) == const(T))) 3436 alias realAA = aa; 3437 else 3438 const(Value[Key]) realAA = aa; 3439 auto res = () @trusted { 3440 auto a = cast(void[])_aaValues(*cast(inout(AA)*)&realAA, Key.sizeof, Value.sizeof, typeid(Value[])); 3441 return *cast(Value[]*)&a; 3442 }(); 3443 static if (__traits(hasPostblit, Value)) 3444 _doPostblit(res); 3445 return res; 3446 } 3447 3448 /** ditto */ 3449 Value[] values(T : Value[Key], Value, Key)(T *aa) @property 3450 { 3451 return (*aa).values; 3452 } 3453 3454 /// 3455 @safe unittest 3456 { 3457 auto aa = ["k1": 1, "k2": 2]; 3458 int sum; 3459 foreach (e; aa.values) 3460 sum += e; 3461 3462 assert(sum == 3); 3463 } 3464 3465 @safe unittest 3466 { 3467 static struct S 3468 { 3469 string str; 3470 void[][string] dict; 3471 alias dict this; 3472 } 3473 3474 auto s = S("a"); 3475 assert(s.values.length == 0); 3476 } 3477 3478 @safe unittest 3479 { 3480 @safe static struct Value 3481 { 3482 string str; 3483 this(this) @safe {} 3484 } 3485 Value[string] aa; 3486 static assert(__traits(compiles, { 3487 void test() @safe { 3488 const _ = aa.values; 3489 } 3490 })); 3491 } 3492 3493 @safe unittest 3494 { 3495 static struct Value 3496 { 3497 string str; 3498 this(this) @system {} 3499 } 3500 Value[string] aa; 3501 static assert(!__traits(compiles, { 3502 void test() @safe { 3503 const _ = aa.values; 3504 } 3505 })); 3506 } 3507 3508 /*********************************** 3509 * Looks up key; if it exists returns corresponding value else evaluates and 3510 * returns defaultValue. 3511 * Params: 3512 * aa = The associative array. 3513 * key = The key. 3514 * defaultValue = The default value. 3515 * Returns: 3516 * The value. 3517 */ 3518 inout(V) get(K, V)(inout(V[K]) aa, K key, lazy inout(V) defaultValue) 3519 { 3520 auto p = key in aa; 3521 return p ? *p : defaultValue; 3522 } 3523 3524 /** ditto */ 3525 inout(V) get(K, V)(inout(V[K])* aa, K key, lazy inout(V) defaultValue) 3526 { 3527 return (*aa).get(key, defaultValue); 3528 } 3529 3530 /// 3531 @safe unittest 3532 { 3533 auto aa = ["k1": 1]; 3534 assert(aa.get("k1", 0) == 1); 3535 assert(aa.get("k2", 0) == 0); 3536 } 3537 3538 /*********************************** 3539 * Looks up key; if it exists returns corresponding value else evaluates 3540 * value, adds it to the associative array and returns it. 3541 * Params: 3542 * aa = The associative array. 3543 * key = The key. 3544 * value = The required value. 3545 * Returns: 3546 * The value. 3547 */ 3548 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init) 3549 { 3550 bool found; 3551 // if key is @safe-ly copyable, `require` can infer @safe 3552 static if (isSafeCopyable!K) 3553 { 3554 auto p = () @trusted 3555 { 3556 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found); 3557 } (); 3558 } 3559 else 3560 { 3561 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found); 3562 } 3563 if (found) 3564 return *p; 3565 else 3566 { 3567 *p = value; // Not `return (*p = value)` since if `=` is overloaded 3568 return *p; // this might not return a ref to the left-hand side. 3569 } 3570 } 3571 3572 /// 3573 @safe unittest 3574 { 3575 auto aa = ["k1": 1]; 3576 assert(aa.require("k1", 0) == 1); 3577 assert(aa.require("k2", 0) == 0); 3578 assert(aa["k2"] == 0); 3579 } 3580 3581 // Tests whether T can be @safe-ly copied. Use a union to exclude destructor from the test. 3582 private enum bool isSafeCopyable(T) = is(typeof(() @safe { union U { T x; } T *x; auto u = U(*x); })); 3583 3584 /*********************************** 3585 * Calls `create` if `key` doesn't exist in the associative array, 3586 * otherwise calls `update`. 3587 * `create` returns a corresponding value for `key`. 3588 * `update` accepts a key parameter. If it returns a value, the value is 3589 * set for `key`. 3590 * Params: 3591 * aa = The associative array. 3592 * key = The key. 3593 * create = The callable to create a value for `key`. 3594 * Must return V. 3595 * update = The callable to call if `key` exists. 3596 * Takes a K argument, returns a V or void. 3597 */ 3598 void update(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update) 3599 if (is(typeof(create()) : V) && (is(typeof(update(aa[K.init])) : V) || is(typeof(update(aa[K.init])) == void))) 3600 { 3601 bool found; 3602 // if key is @safe-ly copyable, `update` may infer @safe 3603 static if (isSafeCopyable!K) 3604 { 3605 auto p = () @trusted 3606 { 3607 return cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found); 3608 } (); 3609 } 3610 else 3611 { 3612 auto p = cast(V*) _aaGetX(cast(AA*) &aa, typeid(V[K]), V.sizeof, &key, found); 3613 } 3614 if (!found) 3615 *p = create(); 3616 else 3617 { 3618 static if (is(typeof(update(*p)) == void)) 3619 update(*p); 3620 else 3621 *p = update(*p); 3622 } 3623 } 3624 3625 /// 3626 @safe unittest 3627 { 3628 int[string] aa; 3629 3630 // create 3631 aa.update("key", 3632 () => 1, 3633 (int) {} // not executed 3634 ); 3635 assert(aa["key"] == 1); 3636 3637 // update value by ref 3638 aa.update("key", 3639 () => 0, // not executed 3640 (ref int v) { 3641 v += 1; 3642 }); 3643 assert(aa["key"] == 2); 3644 3645 // update from return value 3646 aa.update("key", 3647 () => 0, // not executed 3648 (int v) => v * 2 3649 ); 3650 assert(aa["key"] == 4); 3651 3652 // 'update' without changing value 3653 aa.update("key", 3654 () => 0, // not executed 3655 (int) { 3656 // do something else 3657 }); 3658 assert(aa["key"] == 4); 3659 } 3660 3661 @safe unittest 3662 { 3663 static struct S 3664 { 3665 int x; 3666 @nogc nothrow pure: 3667 this(this) @system {} 3668 3669 @safe const: 3670 // stubs 3671 bool opEquals(S rhs) { assert(0); } 3672 size_t toHash() { assert(0); } 3673 } 3674 3675 int[string] aai; 3676 static assert(is(typeof(() @safe { aai.require("a", 1234); }))); 3677 static assert(is(typeof(() @safe { aai.update("a", { return 1234; }, (ref int x) { x++; return x; }); }))); 3678 3679 S[string] aas; 3680 static assert(is(typeof(() { aas.require("a", S(1234)); }))); 3681 static assert(is(typeof(() { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); }))); 3682 static assert(!is(typeof(() @safe { aas.update("a", { return S(1234); }, (ref S s) { s.x++; return s; }); }))); 3683 3684 int[S] aais; 3685 static assert(is(typeof(() { aais.require(S(1234), 1234); }))); 3686 static assert(is(typeof(() { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); }))); 3687 static assert(!is(typeof(() @safe { aais.require(S(1234), 1234); }))); 3688 static assert(!is(typeof(() @safe { aais.update(S(1234), { return 1234; }, (ref int x) { x++; return x; }); }))); 3689 } 3690 3691 @safe unittest 3692 { 3693 struct S0 3694 { 3695 int opCall(ref int v) 3696 { 3697 return v + 1; 3698 } 3699 } 3700 3701 struct S1 3702 { 3703 int opCall()() 3704 { 3705 return -2; 3706 } 3707 3708 T opCall(T)(ref T v) 3709 { 3710 return v + 1; 3711 } 3712 } 3713 3714 int[string] a = ["2" : 1]; 3715 a.update("2", () => -1, S0.init); 3716 assert(a["2"] == 2); 3717 a.update("0", () => -1, S0.init); 3718 assert(a["0"] == -1); 3719 a.update("2", S1.init, S1.init); 3720 assert(a["2"] == 3); 3721 a.update("1", S1.init, S1.init); 3722 assert(a["1"] == -2); 3723 } 3724 3725 @system unittest 3726 { 3727 int[string] aa; 3728 3729 foreach (n; 0 .. 2) 3730 aa.update("k1", { 3731 return 7; 3732 }, (ref int v) { 3733 return v + 3; 3734 }); 3735 assert(aa["k1"] == 10); 3736 } 3737 3738 version (CoreDdoc) 3739 { 3740 // This lets DDoc produce better documentation. 3741 3742 /** 3743 Calculates the hash value of `arg` with an optional `seed` initial value. 3744 The result might not be equal to `typeid(T).getHash(&arg)`. 3745 3746 Params: 3747 arg = argument to calculate the hash value of 3748 seed = optional `seed` value (may be used for hash chaining) 3749 3750 Return: calculated hash value of `arg` 3751 */ 3752 size_t hashOf(T)(auto ref T arg, size_t seed) 3753 { 3754 static import core.internal.hash; 3755 return core.internal.hash.hashOf(arg, seed); 3756 } 3757 /// ditto 3758 size_t hashOf(T)(auto ref T arg) 3759 { 3760 static import core.internal.hash; 3761 return core.internal.hash.hashOf(arg); 3762 } 3763 3764 @safe unittest 3765 { 3766 auto h1 = "my.string".hashOf; 3767 assert(h1 == "my.string".hashOf); 3768 } 3769 } 3770 else 3771 { 3772 public import core.internal.hash : hashOf; 3773 } 3774 3775 /// 3776 @system unittest 3777 { 3778 class MyObject 3779 { 3780 size_t myMegaHash() const @safe pure nothrow 3781 { 3782 return 42; 3783 } 3784 } 3785 struct Test 3786 { 3787 int a; 3788 string b; 3789 MyObject c; 3790 size_t toHash() const pure nothrow 3791 { 3792 size_t hash = a.hashOf(); 3793 hash = b.hashOf(hash); 3794 size_t h1 = c.myMegaHash(); 3795 hash = h1.hashOf(hash); //Mix two hash values 3796 return hash; 3797 } 3798 } 3799 } 3800 3801 bool _xopEquals(in void*, in void*) 3802 { 3803 throw new Error("TypeInfo.equals is not implemented"); 3804 } 3805 3806 bool _xopCmp(in void*, in void*) 3807 { 3808 throw new Error("TypeInfo.compare is not implemented"); 3809 } 3810 3811 /****************************************** 3812 * Create RTInfo for type T 3813 */ 3814 3815 template RTInfoImpl(size_t[] pointerBitmap) 3816 { 3817 immutable size_t[pointerBitmap.length] RTInfoImpl = pointerBitmap[]; 3818 } 3819 3820 template NoPointersBitmapPayload(size_t N) 3821 { 3822 enum size_t[N] NoPointersBitmapPayload = 0; 3823 } 3824 3825 template RTInfo(T) 3826 { 3827 enum pointerBitmap = __traits(getPointerBitmap, T); 3828 static if (pointerBitmap[1 .. $] == NoPointersBitmapPayload!(pointerBitmap.length - 1)) 3829 enum RTInfo = rtinfoNoPointers; 3830 else 3831 enum RTInfo = RTInfoImpl!(pointerBitmap).ptr; 3832 } 3833 3834 /** 3835 * shortcuts for the precise GC, also generated by the compiler 3836 * used instead of the actual pointer bitmap 3837 */ 3838 enum immutable(void)* rtinfoNoPointers = null; 3839 enum immutable(void)* rtinfoHasPointers = cast(void*)1; 3840 3841 // Helper functions 3842 3843 private inout(TypeInfo) getElement(return scope inout TypeInfo value) @trusted pure nothrow 3844 { 3845 TypeInfo element = cast() value; 3846 for (;;) 3847 { 3848 if (auto qualified = cast(TypeInfo_Const) element) 3849 element = qualified.base; 3850 else if (auto redefined = cast(TypeInfo_Enum) element) 3851 element = redefined.base; 3852 else if (auto staticArray = cast(TypeInfo_StaticArray) element) 3853 element = staticArray.value; 3854 else if (auto vector = cast(TypeInfo_Vector) element) 3855 element = vector.base; 3856 else 3857 break; 3858 } 3859 return cast(inout) element; 3860 } 3861 3862 private size_t getArrayHash(const scope TypeInfo element, const scope void* ptr, const size_t count) @trusted nothrow 3863 { 3864 if (!count) 3865 return 0; 3866 3867 const size_t elementSize = element.tsize; 3868 if (!elementSize) 3869 return 0; 3870 3871 static bool hasCustomToHash(const scope TypeInfo value) @trusted pure nothrow 3872 { 3873 const element = getElement(value); 3874 3875 if (const struct_ = cast(const TypeInfo_Struct) element) 3876 return !!struct_.xtoHash; 3877 3878 return cast(const TypeInfo_Array) element 3879 || cast(const TypeInfo_AssociativeArray) element 3880 || cast(const ClassInfo) element 3881 || cast(const TypeInfo_Interface) element; 3882 } 3883 3884 if (!hasCustomToHash(element)) 3885 return hashOf(ptr[0 .. elementSize * count]); 3886 3887 size_t hash = 0; 3888 foreach (size_t i; 0 .. count) 3889 hash = hashOf(element.getHash(ptr + i * elementSize), hash); 3890 return hash; 3891 } 3892 3893 /// Provide the .dup array property. 3894 @property auto dup(T)(T[] a) 3895 if (!is(const(T) : T)) 3896 { 3897 import core.internal.traits : Unconst; 3898 import core.internal.array.duplication : _dup; 3899 static assert(is(T : Unconst!T), "Cannot implicitly convert type "~T.stringof~ 3900 " to "~Unconst!T.stringof~" in dup."); 3901 3902 return _dup!(T, Unconst!T)(a); 3903 } 3904 3905 /// 3906 @safe unittest 3907 { 3908 auto arr = [1, 2]; 3909 auto arr2 = arr.dup; 3910 arr[0] = 0; 3911 assert(arr == [0, 2]); 3912 assert(arr2 == [1, 2]); 3913 } 3914 3915 /// ditto 3916 // const overload to support implicit conversion to immutable (unique result, see DIP29) 3917 @property T[] dup(T)(const(T)[] a) 3918 if (is(const(T) : T)) 3919 { 3920 import core.internal.array.duplication : _dup; 3921 return _dup!(const(T), T)(a); 3922 } 3923 3924 3925 /// Provide the .idup array property. 3926 @property immutable(T)[] idup(T)(T[] a) 3927 { 3928 import core.internal.array.duplication : _dup; 3929 static assert(is(T : immutable(T)), "Cannot implicitly convert type "~T.stringof~ 3930 " to immutable in idup."); 3931 return _dup!(T, immutable(T))(a); 3932 } 3933 3934 /// ditto 3935 @property immutable(T)[] idup(T:void)(const(T)[] a) 3936 { 3937 return a.dup; 3938 } 3939 3940 /// 3941 @safe unittest 3942 { 3943 char[] arr = ['a', 'b', 'c']; 3944 string s = arr.idup; 3945 arr[0] = '.'; 3946 assert(s == "abc"); 3947 } 3948 3949 // HACK: This is a lie. `_d_arraysetcapacity` is neither `nothrow` nor `pure`, but this lie is 3950 // necessary for now to prevent breaking code. 3951 private extern (C) size_t _d_arraysetcapacity(const TypeInfo ti, size_t newcapacity, void[]* arrptr) pure nothrow; 3952 3953 /** 3954 (Property) Gets the current _capacity of a slice. The _capacity is the size 3955 that the slice can grow to before the underlying array must be 3956 reallocated or extended. 3957 3958 If an append must reallocate a slice with no possibility of extension, then 3959 `0` is returned. This happens when the slice references a static array, or 3960 if another slice references elements past the end of the current slice. 3961 3962 Note: The _capacity of a slice may be impacted by operations on other slices. 3963 */ 3964 @property size_t capacity(T)(T[] arr) pure nothrow @trusted 3965 { 3966 return _d_arraysetcapacity(typeid(T[]), 0, cast(void[]*)&arr); 3967 } 3968 3969 /// 3970 @safe unittest 3971 { 3972 //Static array slice: no capacity 3973 int[4] sarray = [1, 2, 3, 4]; 3974 int[] slice = sarray[]; 3975 assert(sarray.capacity == 0); 3976 //Appending to slice will reallocate to a new array 3977 slice ~= 5; 3978 assert(slice.capacity >= 5); 3979 3980 //Dynamic array slices 3981 int[] a = [1, 2, 3, 4]; 3982 int[] b = a[1 .. $]; 3983 int[] c = a[1 .. $ - 1]; 3984 debug(SENTINEL) {} else // non-zero capacity very much depends on the array and GC implementation 3985 { 3986 assert(a.capacity != 0); 3987 assert(a.capacity == b.capacity + 1); //both a and b share the same tail 3988 } 3989 assert(c.capacity == 0); //an append to c must relocate c. 3990 } 3991 3992 /** 3993 Reserves capacity for a slice. The capacity is the size 3994 that the slice can grow to before the underlying array must be 3995 reallocated or extended. 3996 3997 Returns: The new capacity of the array (which may be larger than 3998 the requested capacity). 3999 */ 4000 size_t reserve(T)(ref T[] arr, size_t newcapacity) pure nothrow @trusted 4001 { 4002 if (__ctfe) 4003 return newcapacity; 4004 else 4005 return _d_arraysetcapacity(typeid(T[]), newcapacity, cast(void[]*)&arr); 4006 } 4007 4008 /// 4009 @safe unittest 4010 { 4011 //Static array slice: no capacity. Reserve relocates. 4012 int[4] sarray = [1, 2, 3, 4]; 4013 int[] slice = sarray[]; 4014 auto u = slice.reserve(8); 4015 assert(u >= 8); 4016 assert(&sarray[0] !is &slice[0]); 4017 assert(slice.capacity == u); 4018 4019 //Dynamic array slices 4020 int[] a = [1, 2, 3, 4]; 4021 a.reserve(8); //prepare a for appending 4 more items 4022 auto p = &a[0]; 4023 u = a.capacity; 4024 a ~= [5, 6, 7, 8]; 4025 assert(p == &a[0]); //a should not have been reallocated 4026 assert(u == a.capacity); //a should not have been extended 4027 } 4028 4029 // https://issues.dlang.org/show_bug.cgi?id=12330, reserve() at CTFE time 4030 @safe unittest 4031 { 4032 int[] foo() { 4033 int[] result; 4034 auto a = result.reserve = 5; 4035 assert(a == 5); 4036 return result; 4037 } 4038 enum r = foo(); 4039 } 4040 4041 // Issue 6646: should be possible to use array.reserve from SafeD. 4042 @safe unittest 4043 { 4044 int[] a; 4045 a.reserve(10); 4046 } 4047 4048 // HACK: This is a lie. `_d_arrayshrinkfit` is not `nothrow`, but this lie is necessary 4049 // for now to prevent breaking code. 4050 private extern (C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow; 4051 4052 /** 4053 Assume that it is safe to append to this array. Appends made to this array 4054 after calling this function may append in place, even if the array was a 4055 slice of a larger array to begin with. 4056 4057 Use this only when it is certain there are no elements in use beyond the 4058 array in the memory block. If there are, those elements will be 4059 overwritten by appending to this array. 4060 4061 Warning: Calling this function, and then using references to data located after the 4062 given array results in undefined behavior. 4063 4064 Returns: 4065 The input is returned. 4066 */ 4067 auto ref inout(T[]) assumeSafeAppend(T)(auto ref inout(T[]) arr) nothrow @system 4068 { 4069 _d_arrayshrinkfit(typeid(T[]), *(cast(void[]*)&arr)); 4070 return arr; 4071 } 4072 4073 /// 4074 @system unittest 4075 { 4076 int[] a = [1, 2, 3, 4]; 4077 4078 // Without assumeSafeAppend. Appending relocates. 4079 int[] b = a [0 .. 3]; 4080 b ~= 5; 4081 assert(a.ptr != b.ptr); 4082 4083 debug(SENTINEL) {} else 4084 { 4085 // With assumeSafeAppend. Appending overwrites. 4086 int[] c = a [0 .. 3]; 4087 c.assumeSafeAppend() ~= 5; 4088 assert(a.ptr == c.ptr); 4089 } 4090 } 4091 4092 @system unittest 4093 { 4094 int[] arr; 4095 auto newcap = arr.reserve(2000); 4096 assert(newcap >= 2000); 4097 assert(newcap == arr.capacity); 4098 auto ptr = arr.ptr; 4099 foreach (i; 0..2000) 4100 arr ~= i; 4101 assert(ptr == arr.ptr); 4102 arr = arr[0..1]; 4103 arr.assumeSafeAppend(); 4104 arr ~= 5; 4105 assert(ptr == arr.ptr); 4106 } 4107 4108 @system unittest 4109 { 4110 int[] arr = [1, 2, 3]; 4111 void foo(ref int[] i) 4112 { 4113 i ~= 5; 4114 } 4115 arr = arr[0 .. 2]; 4116 foo(assumeSafeAppend(arr)); //pass by ref 4117 assert(arr[]==[1, 2, 5]); 4118 arr = arr[0 .. 1].assumeSafeAppend(); //pass by value 4119 } 4120 4121 // https://issues.dlang.org/show_bug.cgi?id=10574 4122 @system unittest 4123 { 4124 int[] a; 4125 immutable(int[]) b; 4126 auto a2 = &assumeSafeAppend(a); 4127 auto b2 = &assumeSafeAppend(b); 4128 auto a3 = assumeSafeAppend(a[]); 4129 auto b3 = assumeSafeAppend(b[]); 4130 assert(is(typeof(*a2) == int[])); 4131 assert(is(typeof(*b2) == immutable(int[]))); 4132 assert(is(typeof(a3) == int[])); 4133 assert(is(typeof(b3) == immutable(int[]))); 4134 } 4135 4136 private void _doPostblit(T)(T[] arr) 4137 { 4138 // infer static postblit type, run postblit if any 4139 static if (__traits(hasPostblit, T)) 4140 { 4141 static if (__traits(isStaticArray, T) && is(T : E[], E)) 4142 _doPostblit(cast(E[]) arr); 4143 else static if (!is(typeof(arr[0].__xpostblit())) && is(immutable T == immutable U, U)) 4144 foreach (ref elem; (() @trusted => cast(U[]) arr)()) 4145 elem.__xpostblit(); 4146 else 4147 foreach (ref elem; arr) 4148 elem.__xpostblit(); 4149 } 4150 } 4151 4152 /** 4153 Destroys the given object and optionally resets to initial state. It's used to 4154 _destroy an object, calling its destructor or finalizer so it no longer 4155 references any other objects. It does $(I not) initiate a GC cycle or free 4156 any GC memory. 4157 If `initialize` is supplied `false`, the object is considered invalid after 4158 destruction, and should not be referenced. 4159 */ 4160 void destroy(bool initialize = true, T)(ref T obj) if (is(T == struct)) 4161 { 4162 import core.internal.destruction : destructRecurse; 4163 4164 destructRecurse(obj); 4165 4166 static if (initialize) 4167 { 4168 import core.internal.lifetime : emplaceInitializer; 4169 emplaceInitializer(obj); // emplace T.init 4170 } 4171 } 4172 4173 @safe unittest 4174 { 4175 struct A { string s = "A"; } 4176 A a = {s: "B"}; 4177 assert(a.s == "B"); 4178 a.destroy; 4179 assert(a.s == "A"); 4180 } 4181 4182 nothrow @safe @nogc unittest 4183 { 4184 { 4185 struct A { string s = "A"; } 4186 A a; 4187 a.s = "asd"; 4188 destroy!false(a); 4189 assert(a.s == "asd"); 4190 destroy(a); 4191 assert(a.s == "A"); 4192 } 4193 { 4194 static int destroyed = 0; 4195 struct C 4196 { 4197 string s = "C"; 4198 ~this() nothrow @safe @nogc 4199 { 4200 destroyed ++; 4201 } 4202 } 4203 4204 struct B 4205 { 4206 C c; 4207 string s = "B"; 4208 ~this() nothrow @safe @nogc 4209 { 4210 destroyed ++; 4211 } 4212 } 4213 B a; 4214 a.s = "asd"; 4215 a.c.s = "jkl"; 4216 destroy!false(a); 4217 assert(destroyed == 2); 4218 assert(a.s == "asd"); 4219 assert(a.c.s == "jkl" ); 4220 destroy(a); 4221 assert(destroyed == 4); 4222 assert(a.s == "B"); 4223 assert(a.c.s == "C" ); 4224 } 4225 } 4226 4227 private extern (C) void rt_finalize2(void* p, bool det = true, bool resetMemory = true) nothrow; 4228 4229 /// ditto 4230 void destroy(bool initialize = true, T)(T obj) if (is(T == class)) 4231 { 4232 static if (__traits(getLinkage, T) == "C++") 4233 { 4234 static if (__traits(hasMember, T, "__xdtor")) 4235 obj.__xdtor(); 4236 4237 static if (initialize) 4238 { 4239 const initializer = __traits(initSymbol, T); 4240 (cast(void*)obj)[0 .. initializer.length] = initializer[]; 4241 } 4242 } 4243 else 4244 { 4245 // Bypass overloaded opCast 4246 auto ptr = (() @trusted => *cast(void**) &obj)(); 4247 rt_finalize2(ptr, true, initialize); 4248 } 4249 } 4250 4251 /// ditto 4252 void destroy(bool initialize = true, T)(T obj) if (is(T == interface)) 4253 { 4254 static assert(__traits(getLinkage, T) == "D", "Invalid call to destroy() on extern(" ~ __traits(getLinkage, T) ~ ") interface"); 4255 4256 destroy!initialize(cast(Object)obj); 4257 } 4258 4259 /// Reference type demonstration 4260 @system unittest 4261 { 4262 class C 4263 { 4264 struct Agg 4265 { 4266 static int dtorCount; 4267 4268 int x = 10; 4269 ~this() { dtorCount++; } 4270 } 4271 4272 static int dtorCount; 4273 4274 string s = "S"; 4275 Agg a; 4276 ~this() { dtorCount++; } 4277 } 4278 4279 C c = new C(); 4280 assert(c.dtorCount == 0); // destructor not yet called 4281 assert(c.s == "S"); // initial state `c.s` is `"S"` 4282 assert(c.a.dtorCount == 0); // destructor not yet called 4283 assert(c.a.x == 10); // initial state `c.a.x` is `10` 4284 c.s = "T"; 4285 c.a.x = 30; 4286 assert(c.s == "T"); // `c.s` is `"T"` 4287 destroy(c); 4288 assert(c.dtorCount == 1); // `c`'s destructor was called 4289 assert(c.s == "S"); // `c.s` is back to its inital state, `"S"` 4290 assert(c.a.dtorCount == 1); // `c.a`'s destructor was called 4291 assert(c.a.x == 10); // `c.a.x` is back to its inital state, `10` 4292 } 4293 4294 /// C++ classes work too 4295 @system unittest 4296 { 4297 extern (C++) class CPP 4298 { 4299 struct Agg 4300 { 4301 __gshared int dtorCount; 4302 4303 int x = 10; 4304 ~this() { dtorCount++; } 4305 } 4306 4307 __gshared int dtorCount; 4308 4309 string s = "S"; 4310 Agg a; 4311 ~this() { dtorCount++; } 4312 } 4313 4314 CPP cpp = new CPP(); 4315 assert(cpp.dtorCount == 0); // destructor not yet called 4316 assert(cpp.s == "S"); // initial state `cpp.s` is `"S"` 4317 assert(cpp.a.dtorCount == 0); // destructor not yet called 4318 assert(cpp.a.x == 10); // initial state `cpp.a.x` is `10` 4319 cpp.s = "T"; 4320 cpp.a.x = 30; 4321 assert(cpp.s == "T"); // `cpp.s` is `"T"` 4322 destroy!false(cpp); // destroy without initialization 4323 assert(cpp.dtorCount == 1); // `cpp`'s destructor was called 4324 assert(cpp.s == "T"); // `cpp.s` is not initialized 4325 assert(cpp.a.dtorCount == 1); // `cpp.a`'s destructor was called 4326 assert(cpp.a.x == 30); // `cpp.a.x` is not initialized 4327 destroy(cpp); 4328 assert(cpp.dtorCount == 2); // `cpp`'s destructor was called again 4329 assert(cpp.s == "S"); // `cpp.s` is back to its inital state, `"S"` 4330 assert(cpp.a.dtorCount == 2); // `cpp.a`'s destructor was called again 4331 assert(cpp.a.x == 10); // `cpp.a.x` is back to its inital state, `10` 4332 } 4333 4334 /// Value type demonstration 4335 @safe unittest 4336 { 4337 int i; 4338 assert(i == 0); // `i`'s initial state is `0` 4339 i = 1; 4340 assert(i == 1); // `i` changed to `1` 4341 destroy!false(i); 4342 assert(i == 1); // `i` was not initialized 4343 destroy(i); 4344 assert(i == 0); // `i` is back to its initial state `0` 4345 } 4346 4347 /// Nested struct type 4348 @system unittest 4349 { 4350 int dtorCount; 4351 struct A 4352 { 4353 int i; 4354 ~this() 4355 { 4356 dtorCount++; // capture local variable 4357 } 4358 } 4359 A a = A(5); 4360 destroy!false(a); 4361 assert(dtorCount == 1); 4362 assert(a.i == 5); 4363 4364 destroy(a); 4365 assert(dtorCount == 2); 4366 assert(a.i == 0); 4367 4368 // the context pointer is now null 4369 // restore it so the dtor can run 4370 import core.lifetime : emplace; 4371 emplace(&a, A(0)); 4372 // dtor also called here 4373 } 4374 4375 @system unittest 4376 { 4377 extern(C++) 4378 static class C 4379 { 4380 void* ptr; 4381 this() {} 4382 } 4383 4384 destroy!false(new C()); 4385 destroy!true(new C()); 4386 } 4387 4388 @system unittest 4389 { 4390 // class with an `alias this` 4391 class A 4392 { 4393 static int dtorCount; 4394 ~this() 4395 { 4396 dtorCount++; 4397 } 4398 } 4399 4400 class B 4401 { 4402 A a; 4403 alias a this; 4404 this() 4405 { 4406 a = new A; 4407 } 4408 static int dtorCount; 4409 ~this() 4410 { 4411 dtorCount++; 4412 } 4413 } 4414 auto b = new B; 4415 assert(A.dtorCount == 0); 4416 assert(B.dtorCount == 0); 4417 destroy(b); 4418 assert(A.dtorCount == 0); 4419 assert(B.dtorCount == 1); 4420 4421 auto a = new A; 4422 destroy(a); 4423 assert(A.dtorCount == 1); 4424 } 4425 4426 @system unittest 4427 { 4428 interface I { } 4429 { 4430 class A: I { string s = "A"; this() {} } 4431 auto a = new A, b = new A; 4432 a.s = b.s = "asd"; 4433 destroy(a); 4434 assert(a.s == "A"); 4435 4436 I i = b; 4437 destroy(i); 4438 assert(b.s == "A"); 4439 } 4440 { 4441 static bool destroyed = false; 4442 class B: I 4443 { 4444 string s = "B"; 4445 this() {} 4446 ~this() 4447 { 4448 destroyed = true; 4449 } 4450 } 4451 auto a = new B, b = new B; 4452 a.s = b.s = "asd"; 4453 destroy(a); 4454 assert(destroyed); 4455 assert(a.s == "B"); 4456 4457 destroyed = false; 4458 I i = b; 4459 destroy(i); 4460 assert(destroyed); 4461 assert(b.s == "B"); 4462 } 4463 // this test is invalid now that the default ctor is not run after clearing 4464 version (none) 4465 { 4466 class C 4467 { 4468 string s; 4469 this() 4470 { 4471 s = "C"; 4472 } 4473 } 4474 auto a = new C; 4475 a.s = "asd"; 4476 destroy(a); 4477 assert(a.s == "C"); 4478 } 4479 } 4480 4481 nothrow @safe @nogc unittest 4482 { 4483 { 4484 struct A { string s = "A"; } 4485 A a; 4486 a.s = "asd"; 4487 destroy!false(a); 4488 assert(a.s == "asd"); 4489 destroy(a); 4490 assert(a.s == "A"); 4491 } 4492 { 4493 static int destroyed = 0; 4494 struct C 4495 { 4496 string s = "C"; 4497 ~this() nothrow @safe @nogc 4498 { 4499 destroyed ++; 4500 } 4501 } 4502 4503 struct B 4504 { 4505 C c; 4506 string s = "B"; 4507 ~this() nothrow @safe @nogc 4508 { 4509 destroyed ++; 4510 } 4511 } 4512 B a; 4513 a.s = "asd"; 4514 a.c.s = "jkl"; 4515 destroy!false(a); 4516 assert(destroyed == 2); 4517 assert(a.s == "asd"); 4518 assert(a.c.s == "jkl" ); 4519 destroy(a); 4520 assert(destroyed == 4); 4521 assert(a.s == "B"); 4522 assert(a.c.s == "C" ); 4523 } 4524 } 4525 4526 nothrow unittest 4527 { 4528 // Bugzilla 20049: Test to ensure proper behavior of `nothrow` destructors 4529 class C 4530 { 4531 static int dtorCount = 0; 4532 this() nothrow {} 4533 ~this() nothrow { dtorCount++; } 4534 } 4535 4536 auto c = new C; 4537 destroy(c); 4538 assert(C.dtorCount == 1); 4539 } 4540 4541 // https://issues.dlang.org/show_bug.cgi?id=22832 4542 nothrow unittest 4543 { 4544 static struct A {} 4545 static class B 4546 { 4547 A opCast(T : A)() { return A(); } 4548 } 4549 4550 destroy(B.init); 4551 } 4552 4553 // make sure destroy!false skips re-initialization 4554 unittest 4555 { 4556 static struct S { int x; } 4557 static class C { int x; } 4558 static extern(C++) class Cpp { int x; } 4559 4560 static void test(T)(T inst) 4561 { 4562 inst.x = 123; 4563 destroy!false(inst); 4564 assert(inst.x == 123, T.stringof); 4565 } 4566 4567 test(S()); 4568 test(new C()); 4569 test(new Cpp()); 4570 } 4571 4572 /// ditto 4573 void destroy(bool initialize = true, T)(ref T obj) 4574 if (__traits(isStaticArray, T)) 4575 { 4576 foreach_reverse (ref e; obj[]) 4577 destroy!initialize(e); 4578 } 4579 4580 @safe unittest 4581 { 4582 int[2] a; 4583 a[0] = 1; 4584 a[1] = 2; 4585 destroy!false(a); 4586 assert(a == [ 1, 2 ]); 4587 destroy(a); 4588 assert(a == [ 0, 0 ]); 4589 } 4590 4591 @safe unittest 4592 { 4593 static struct vec2f { 4594 float[2] values; 4595 alias values this; 4596 } 4597 4598 vec2f v; 4599 destroy!(true, vec2f)(v); 4600 } 4601 4602 @system unittest 4603 { 4604 // Bugzilla 15009 4605 static string op; 4606 static struct S 4607 { 4608 int x; 4609 this(int x) { op ~= "C" ~ cast(char)('0'+x); this.x = x; } 4610 this(this) { op ~= "P" ~ cast(char)('0'+x); } 4611 ~this() { op ~= "D" ~ cast(char)('0'+x); } 4612 } 4613 4614 { 4615 S[2] a1 = [S(1), S(2)]; 4616 op = ""; 4617 } 4618 assert(op == "D2D1"); // built-in scope destruction 4619 { 4620 S[2] a1 = [S(1), S(2)]; 4621 op = ""; 4622 destroy(a1); 4623 assert(op == "D2D1"); // consistent with built-in behavior 4624 } 4625 4626 { 4627 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]]; 4628 op = ""; 4629 } 4630 assert(op == "D4D3D2D1"); 4631 { 4632 S[2][2] a2 = [[S(1), S(2)], [S(3), S(4)]]; 4633 op = ""; 4634 destroy(a2); 4635 assert(op == "D4D3D2D1", op); 4636 } 4637 } 4638 4639 // https://issues.dlang.org/show_bug.cgi?id=19218 4640 @system unittest 4641 { 4642 static struct S 4643 { 4644 static dtorCount = 0; 4645 ~this() { ++dtorCount; } 4646 } 4647 4648 static interface I 4649 { 4650 ref S[3] getArray(); 4651 alias getArray this; 4652 } 4653 4654 static class C : I 4655 { 4656 static dtorCount = 0; 4657 ~this() { ++dtorCount; } 4658 4659 S[3] a; 4660 alias a this; 4661 4662 ref S[3] getArray() { return a; } 4663 } 4664 4665 C c = new C(); 4666 destroy(c); 4667 assert(S.dtorCount == 3); 4668 assert(C.dtorCount == 1); 4669 4670 I i = new C(); 4671 destroy(i); 4672 assert(S.dtorCount == 6); 4673 assert(C.dtorCount == 2); 4674 } 4675 4676 /// ditto 4677 void destroy(bool initialize = true, T)(ref T obj) 4678 if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T)) 4679 { 4680 static if (initialize) 4681 obj = T.init; 4682 } 4683 4684 @safe unittest 4685 { 4686 { 4687 int a = 42; 4688 destroy!false(a); 4689 assert(a == 42); 4690 destroy(a); 4691 assert(a == 0); 4692 } 4693 { 4694 float a = 42; 4695 destroy!false(a); 4696 assert(a == 42); 4697 destroy(a); 4698 assert(a != a); // isnan 4699 } 4700 } 4701 4702 @safe unittest 4703 { 4704 // Bugzilla 14746 4705 static struct HasDtor 4706 { 4707 ~this() { assert(0); } 4708 } 4709 static struct Owner 4710 { 4711 HasDtor* ptr; 4712 alias ptr this; 4713 } 4714 4715 Owner o; 4716 assert(o.ptr is null); 4717 destroy(o); // must not reach in HasDtor.__dtor() 4718 } 4719 4720 /* ************************************************************************ 4721 COMPILER SUPPORT 4722 The compiler lowers certain expressions to instantiations of the following 4723 templates. They must be implicitly imported, which is why they are here 4724 in this file. They must also be `public` as they must be visible from the 4725 scope in which they are instantiated. They are explicitly undocumented as 4726 they are only intended to be instantiated by the compiler, not the user. 4727 **************************************************************************/ 4728 4729 public import core.internal.entrypoint : _d_cmain; 4730 4731 public import core.internal.array.appending : _d_arrayappendT; 4732 version (D_ProfileGC) 4733 { 4734 public import core.internal.array.appending : _d_arrayappendTTrace; 4735 public import core.internal.array.appending : _d_arrayappendcTXTrace; 4736 public import core.internal.array.concatenation : _d_arraycatnTXTrace; 4737 public import core.lifetime : _d_newitemTTrace; 4738 public import core.internal.array.construction : _d_newarrayTTrace; 4739 public import core.internal.array.construction : _d_newarraymTXTrace; 4740 } 4741 public import core.internal.array.appending : _d_arrayappendcTX; 4742 public import core.internal.array.comparison : __cmp; 4743 public import core.internal.array.equality : __equals; 4744 public import core.internal.array.casting: __ArrayCast; 4745 public import core.internal.array.concatenation : _d_arraycatnTX; 4746 public import core.internal.array.construction : _d_arrayctor; 4747 public import core.internal.array.construction : _d_arraysetctor; 4748 public import core.internal.array.construction : _d_newarrayT; 4749 public import core.internal.array.construction : _d_newarraymTX; 4750 public import core.internal.array.arrayassign : _d_arrayassign_l; 4751 public import core.internal.array.arrayassign : _d_arrayassign_r; 4752 public import core.internal.array.arrayassign : _d_arraysetassign; 4753 public import core.internal.array.capacity: _d_arraysetlengthTImpl; 4754 4755 public import core.internal.dassert: _d_assert_fail; 4756 4757 public import core.internal.destruction: __ArrayDtor; 4758 4759 public import core.internal.moving: __move_post_blt; 4760 4761 public import core.internal.postblit: __ArrayPostblit; 4762 4763 public import core.internal.switch_: __switch; 4764 public import core.internal.switch_: __switch_error; 4765 4766 public import core.lifetime : _d_delstructImpl; 4767 public import core.lifetime : _d_newThrowable; 4768 public import core.lifetime : _d_newclassT; 4769 public import core.lifetime : _d_newclassTTrace; 4770 public import core.lifetime : _d_newitemT; 4771 4772 public @trusted @nogc nothrow pure extern (C) void _d_delThrowable(scope Throwable); 4773 4774 // Compare class and interface objects for ordering. 4775 int __cmp(C1, C2)(C1 lhs, C2 rhs) 4776 if ((is(C1 : const(Object)) || (is(C1 == interface) && (__traits(getLinkage, C1) == "D"))) && 4777 (is(C2 : const(Object)) || (is(C2 == interface) && (__traits(getLinkage, C2) == "D")))) 4778 { 4779 static if (is(C1 == typeof(null)) && is(C2 == typeof(null))) 4780 { 4781 return 0; 4782 } 4783 else static if (is(C1 == typeof(null))) 4784 { 4785 // Regard null references as always being "less than" 4786 return -1; 4787 } 4788 else static if (is(C2 == typeof(null))) 4789 { 4790 return 1; 4791 } 4792 else 4793 { 4794 if (lhs is rhs) 4795 return 0; 4796 if (lhs is null) 4797 return -1; 4798 if (rhs is null) 4799 return 1; 4800 return lhs.opCmp(rhs); 4801 } 4802 } 4803 4804 // objects 4805 @safe unittest 4806 { 4807 class C 4808 { 4809 int i; 4810 this(int i) { this.i = i; } 4811 4812 override int opCmp(Object c) const @safe 4813 { 4814 return i - (cast(C)c).i; 4815 } 4816 } 4817 4818 auto c1 = new C(1); 4819 auto c2 = new C(2); 4820 assert(__cmp(c1, null) > 0); 4821 assert(__cmp(null, c1) < 0); 4822 assert(__cmp(c1, c1) == 0); 4823 assert(__cmp(c1, c2) < 0); 4824 assert(__cmp(c2, c1) > 0); 4825 4826 assert(__cmp([c1, c1][], [c2, c2][]) < 0); 4827 assert(__cmp([c2, c2], [c1, c1]) > 0); 4828 } 4829 4830 // structs 4831 @safe unittest 4832 { 4833 struct C 4834 { 4835 ubyte i; 4836 this(ubyte i) { this.i = i; } 4837 } 4838 4839 auto c1 = C(1); 4840 auto c2 = C(2); 4841 4842 assert(__cmp([c1, c1][], [c2, c2][]) < 0); 4843 assert(__cmp([c2, c2], [c1, c1]) > 0); 4844 assert(__cmp([c2, c2], [c2, c1]) > 0); 4845 } 4846 4847 @safe unittest 4848 { 4849 auto a = "hello"c; 4850 4851 assert(a > "hel"); 4852 assert(a >= "hel"); 4853 assert(a < "helloo"); 4854 assert(a <= "helloo"); 4855 assert(a > "betty"); 4856 assert(a >= "betty"); 4857 assert(a == "hello"); 4858 assert(a <= "hello"); 4859 assert(a >= "hello"); 4860 assert(a < "я"); 4861 } 4862 4863 // Used in Exception Handling LSDA tables to 'wrap' C++ type info 4864 // so it can be distinguished from D TypeInfo 4865 class __cpp_type_info_ptr 4866 { 4867 void* ptr; // opaque pointer to C++ RTTI type info 4868 } 4869 4870 // Compiler hook into the runtime implementation of array (vector) operations. 4871 template _arrayOp(Args...) 4872 { 4873 import core.internal.array.operations; 4874 alias _arrayOp = arrayOp!Args; 4875 } 4876 4877 public import core.builtins : __ctfeWrite; 4878 4879 /** 4880 4881 Provides an "inline import", i.e. an `import` that is only available for a 4882 limited lookup. For example: 4883 4884 --- 4885 void fun(imported!"std.stdio".File input) 4886 { 4887 ... use File from std.stdio normally ... 4888 } 4889 --- 4890 4891 There is no need to import `std.stdio` at top level, so `fun` carries its own 4892 dependencies. The same approach can be used for template constraints: 4893 4894 --- 4895 void fun(T)(imported!"std.stdio".File input, T value) 4896 if (imported!"std.traits".isIntegral!T) 4897 { 4898 ... 4899 } 4900 --- 4901 4902 An inline import may be used in conjunction with the `with` statement as well. 4903 Inside the scope controlled by `with`, all symbols in the imported module are 4904 made available: 4905 4906 --- 4907 void fun() 4908 { 4909 with (imported!"std.datetime") 4910 with (imported!"std.stdio") 4911 { 4912 Clock.currTime.writeln; 4913 } 4914 } 4915 --- 4916 4917 The advantages of inline imports over top-level uses of the `import` declaration 4918 are the following: 4919 4920 $(UL 4921 $(LI The `imported` template specifies dependencies at declaration level, not at 4922 module level. This allows reasoning about the dependency cost of declarations in 4923 separation instead of aggregated at module level.) 4924 $(LI Declarations using `imported` are easier to move around because they don't 4925 require top-level context, making for simpler and quicker refactorings.) 4926 $(LI Declarations using `imported` scale better with templates. This is because 4927 templates that are not instantiated do not have their parameters and constraints 4928 instantiated, so additional modules are not imported without necessity. This 4929 makes the cost of unused templates negligible. Dependencies are pulled on a need 4930 basis depending on the declarations used by client code.) 4931 ) 4932 4933 The use of `imported` also has drawbacks: 4934 4935 $(UL 4936 $(LI If most declarations in a module need the same imports, then factoring them 4937 at top level, outside the declarations, is simpler than repeating them.) 4938 $(LI Traditional dependency-tracking tools such as make and other build systems 4939 assume file-level dependencies and need special tooling (such as rdmd) in order 4940 to work efficiently.) 4941 $(LI Dependencies at the top of a module are easier to inspect quickly than 4942 dependencies spread throughout the module.) 4943 ) 4944 4945 See_Also: The $(HTTP forum.dlang.org/post/tzqzmqhankrkbrfsrmbo@forum.dlang.org, 4946 forum discussion) that led to the creation of the `imported` facility. Credit is 4947 due to Daniel Nielsen and Dominikus Dittes Scherkl. 4948 4949 */ 4950 template imported(string moduleName) 4951 { 4952 mixin("import imported = " ~ moduleName ~ ";"); 4953 }