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