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