1 module core.lifetime; 2 3 import core.internal.attributes : betterC; 4 5 // version (CRuntime_LIBWASM) {} // Removed the GC from here 6 7 private extern (C) void* _d_allocmemory(size_t sz) pure nothrow; 8 // emplace 9 /** 10 Given a pointer `chunk` to uninitialized memory (but already typed 11 as `T`), constructs an object of non-`class` type `T` at that 12 address. If `T` is a class, initializes the class reference to null. 13 Returns: A pointer to the newly constructed object (which is the same 14 as `chunk`). 15 */ 16 T* emplace(T)(T* chunk) @safe pure nothrow 17 { 18 import core.internal.lifetime : emplaceRef; 19 20 emplaceRef!T(*chunk); 21 return chunk; 22 } 23 24 /// 25 @betterC 26 @system unittest 27 { 28 static struct S 29 { 30 int i = 42; 31 } 32 S[2] s2 = void; 33 emplace(&s2); 34 assert(s2[0].i == 42 && s2[1].i == 42); 35 } 36 37 /// 38 @system unittest 39 { 40 interface I {} 41 class K : I {} 42 43 K k = void; 44 emplace(&k); 45 assert(k is null); 46 47 I i = void; 48 emplace(&i); 49 assert(i is null); 50 } 51 52 /** 53 Given a pointer `chunk` to uninitialized memory (but already typed 54 as a non-class type `T`), constructs an object of type `T` at 55 that address from arguments `args`. If `T` is a class, initializes 56 the class reference to `args[0]`. 57 This function can be `@trusted` if the corresponding constructor of 58 `T` is `@safe`. 59 Returns: A pointer to the newly constructed object (which is the same 60 as `chunk`). 61 */ 62 T* emplace(T, Args...)(T* chunk, auto ref Args args) 63 if (is(T == struct) || Args.length == 1) 64 { 65 import core.internal.lifetime : emplaceRef; 66 67 emplaceRef!T(*chunk, forward!args); 68 return chunk; 69 } 70 71 /// 72 @betterC 73 @system unittest 74 { 75 int a; 76 int b = 42; 77 assert(*emplace!int(&a, b) == 42); 78 } 79 80 @betterC 81 @system unittest 82 { 83 shared int i; 84 emplace(&i, 42); 85 assert(i == 42); 86 } 87 88 /** 89 Given a raw memory area `chunk` (but already typed as a class type `T`), 90 constructs an object of `class` type `T` at that address. The constructor 91 is passed the arguments `Args`. 92 If `T` is an inner class whose `outer` field can be used to access an instance 93 of the enclosing class, then `Args` must not be empty, and the first member of it 94 must be a valid initializer for that `outer` field. Correct initialization of 95 this field is essential to access members of the outer class inside `T` methods. 96 Note: 97 This function is `@safe` if the corresponding constructor of `T` is `@safe`. 98 Returns: The newly constructed object. 99 */ 100 T emplace(T, Args...)(T chunk, auto ref Args args) 101 if (is(T == class)) 102 { 103 import core.internal.traits : isInnerClass; 104 105 static assert(!__traits(isAbstractClass, T), T.stringof ~ 106 " is abstract and it can't be emplaced"); 107 108 // Initialize the object in its pre-ctor state 109 const initializer = __traits(initSymbol, T); 110 (() @trusted { (cast(void*) chunk)[0 .. initializer.length] = initializer[]; })(); 111 112 static if (isInnerClass!T) 113 { 114 static assert(Args.length > 0, 115 "Initializing an inner class requires a pointer to the outer class"); 116 static assert(is(Args[0] : typeof(T.outer)), 117 "The first argument must be a pointer to the outer class"); 118 119 chunk.outer = args[0]; 120 alias args1 = args[1..$]; 121 } 122 else alias args1 = args; 123 124 // Call the ctor if any 125 static if (is(typeof(chunk.__ctor(forward!args1)))) 126 { 127 // T defines a genuine constructor accepting args 128 // Go the classic route: write .init first, then call ctor 129 chunk.__ctor(forward!args1); 130 } 131 else 132 { 133 static assert(args1.length == 0 && !is(typeof(&T.__ctor)), 134 "Don't know how to initialize an object of type " 135 ~ T.stringof ~ " with arguments " ~ typeof(args1).stringof); 136 } 137 return chunk; 138 } 139 140 /// 141 @safe unittest 142 { 143 () @safe { 144 class SafeClass 145 { 146 int x; 147 @safe this(int x) { this.x = x; } 148 } 149 150 auto buf = new void[__traits(classInstanceSize, SafeClass)]; 151 auto support = (() @trusted => cast(SafeClass)(buf.ptr))(); 152 auto safeClass = emplace!SafeClass(support, 5); 153 assert(safeClass.x == 5); 154 155 class UnsafeClass 156 { 157 int x; 158 @system this(int x) { this.x = x; } 159 } 160 161 auto buf2 = new void[__traits(classInstanceSize, UnsafeClass)]; 162 auto support2 = (() @trusted => cast(UnsafeClass)(buf2.ptr))(); 163 static assert(!__traits(compiles, emplace!UnsafeClass(support2, 5))); 164 static assert(!__traits(compiles, emplace!UnsafeClass(buf2, 5))); 165 }(); 166 } 167 168 @safe unittest 169 { 170 class Outer 171 { 172 int i = 3; 173 class Inner 174 { 175 @safe auto getI() { return i; } 176 } 177 } 178 auto outerBuf = new void[__traits(classInstanceSize, Outer)]; 179 auto outerSupport = (() @trusted => cast(Outer)(outerBuf.ptr))(); 180 181 auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)]; 182 auto innerSupport = (() @trusted => cast(Outer.Inner)(innerBuf.ptr))(); 183 184 auto inner = innerSupport.emplace!(Outer.Inner)(outerSupport.emplace!Outer); 185 assert(inner.getI == 3); 186 } 187 188 /** 189 Given a raw memory area `chunk`, constructs an object of `class` type `T` at 190 that address. The constructor is passed the arguments `Args`. 191 If `T` is an inner class whose `outer` field can be used to access an instance 192 of the enclosing class, then `Args` must not be empty, and the first member of it 193 must be a valid initializer for that `outer` field. Correct initialization of 194 this field is essential to access members of the outer class inside `T` methods. 195 Preconditions: 196 `chunk` must be at least as large as `T` needs and should have an alignment 197 multiple of `T`'s alignment. (The size of a `class` instance is obtained by using 198 $(D __traits(classInstanceSize, T))). 199 Note: 200 This function can be `@trusted` if the corresponding constructor of `T` is `@safe`. 201 Returns: The newly constructed object. 202 */ 203 T emplace(T, Args...)(void[] chunk, auto ref Args args) 204 if (is(T == class)) 205 { 206 enum classSize = __traits(classInstanceSize, T); 207 assert(chunk.length >= classSize, "chunk size too small."); 208 209 enum alignment = __traits(classInstanceAlignment, T); 210 assert((cast(size_t) chunk.ptr) % alignment == 0, "chunk is not aligned."); 211 212 return emplace!T(cast(T)(chunk.ptr), forward!args); 213 } 214 215 /// 216 @system unittest 217 { 218 static class C 219 { 220 int i; 221 this(int i){this.i = i;} 222 } 223 auto buf = new void[__traits(classInstanceSize, C)]; 224 auto c = emplace!C(buf, 5); 225 assert(c.i == 5); 226 } 227 228 /// 229 @betterC 230 @nogc pure nothrow @system unittest 231 { 232 // works with -betterC too: 233 234 static extern (C++) class C 235 { 236 @nogc pure nothrow @safe: 237 int i = 3; 238 this(int i) 239 { 240 assert(this.i == 3); 241 this.i = i; 242 } 243 int virtualGetI() { return i; } 244 } 245 246 align(__traits(classInstanceAlignment, C)) byte[__traits(classInstanceSize, C)] buffer; 247 C c = emplace!C(buffer[], 42); 248 assert(c.virtualGetI() == 42); 249 } 250 251 @system unittest 252 { 253 class Outer 254 { 255 int i = 3; 256 class Inner 257 { 258 auto getI() { return i; } 259 } 260 } 261 auto outerBuf = new void[__traits(classInstanceSize, Outer)]; 262 auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)]; 263 auto inner = innerBuf.emplace!(Outer.Inner)(outerBuf.emplace!Outer); 264 assert(inner.getI == 3); 265 } 266 267 @nogc pure nothrow @safe unittest 268 { 269 static class __conv_EmplaceTestClass 270 { 271 @nogc @safe pure nothrow: 272 int i = 3; 273 this(int i) 274 { 275 assert(this.i == 3); 276 this.i = 10 + i; 277 } 278 this(ref int i) 279 { 280 assert(this.i == 3); 281 this.i = 20 + i; 282 } 283 this(int i, ref int j) 284 { 285 assert(this.i == 3 && i == 5 && j == 6); 286 this.i = i; 287 ++j; 288 } 289 } 290 291 int var = 6; 292 align(__traits(classInstanceAlignment, __conv_EmplaceTestClass)) 293 ubyte[__traits(classInstanceSize, __conv_EmplaceTestClass)] buf; 294 auto support = (() @trusted => cast(__conv_EmplaceTestClass)(buf.ptr))(); 295 296 auto fromRval = emplace!__conv_EmplaceTestClass(support, 1); 297 assert(fromRval.i == 11); 298 299 auto fromLval = emplace!__conv_EmplaceTestClass(support, var); 300 assert(fromLval.i == 26); 301 302 auto k = emplace!__conv_EmplaceTestClass(support, 5, var); 303 assert(k.i == 5); 304 assert(var == 7); 305 } 306 307 /** 308 Given a raw memory area `chunk`, constructs an object of non-$(D 309 class) type `T` at that address. The constructor is passed the 310 arguments `args`, if any. 311 Preconditions: 312 `chunk` must be at least as large 313 as `T` needs and should have an alignment multiple of `T`'s 314 alignment. 315 Note: 316 This function can be `@trusted` if the corresponding constructor of 317 `T` is `@safe`. 318 Returns: A pointer to the newly constructed object. 319 */ 320 T* emplace(T, Args...)(void[] chunk, auto ref Args args) 321 if (!is(T == class)) 322 { 323 import core.internal.traits : Unqual; 324 import core.internal.lifetime : emplaceRef; 325 326 assert(chunk.length >= T.sizeof, "chunk size too small."); 327 assert((cast(size_t) chunk.ptr) % T.alignof == 0, "emplace: Chunk is not aligned."); 328 329 emplaceRef!(T, Unqual!T)(*cast(Unqual!T*) chunk.ptr, forward!args); 330 return cast(T*) chunk.ptr; 331 } 332 333 /// 334 @betterC 335 @system unittest 336 { 337 struct S 338 { 339 int a, b; 340 } 341 void[S.sizeof] buf = void; 342 S s; 343 s.a = 42; 344 s.b = 43; 345 auto s1 = emplace!S(buf, s); 346 assert(s1.a == 42 && s1.b == 43); 347 } 348 349 // Bulk of emplace unittests starts here 350 351 @betterC 352 @system unittest /* unions */ 353 { 354 static union U 355 { 356 string a; 357 int b; 358 struct 359 { 360 long c; 361 int[] d; 362 } 363 } 364 U u1 = void; 365 U u2 = { "hello" }; 366 emplace(&u1, u2); 367 assert(u1.a == "hello"); 368 } 369 370 @system unittest // https://issues.dlang.org/show_bug.cgi?id=15772 371 { 372 abstract class Foo {} 373 class Bar: Foo {} 374 void[] memory; 375 // test in emplaceInitializer 376 static assert(!is(typeof(emplace!Foo(cast(Foo*) memory.ptr)))); 377 static assert( is(typeof(emplace!Bar(cast(Bar*) memory.ptr)))); 378 // test in the emplace overload that takes void[] 379 static assert(!is(typeof(emplace!Foo(memory)))); 380 static assert( is(typeof(emplace!Bar(memory)))); 381 } 382 383 @betterC 384 @system unittest 385 { 386 struct S { @disable this(); } 387 S s = void; 388 static assert(!__traits(compiles, emplace(&s))); 389 emplace(&s, S.init); 390 } 391 392 @betterC 393 @system unittest 394 { 395 struct S1 396 {} 397 398 struct S2 399 { 400 void opAssign(S2); 401 } 402 403 S1 s1 = void; 404 S2 s2 = void; 405 S1[2] as1 = void; 406 S2[2] as2 = void; 407 emplace(&s1); 408 emplace(&s2); 409 emplace(&as1); 410 emplace(&as2); 411 } 412 413 @system unittest 414 { 415 static struct S1 416 { 417 this(this) @disable; 418 } 419 static struct S2 420 { 421 this() @disable; 422 } 423 S1[2] ss1 = void; 424 S2[2] ss2 = void; 425 emplace(&ss1); 426 static assert(!__traits(compiles, emplace(&ss2))); 427 S1 s1 = S1.init; 428 S2 s2 = S2.init; 429 static assert(!__traits(compiles, emplace(&ss1, s1))); 430 emplace(&ss2, s2); 431 } 432 433 @system unittest 434 { 435 struct S 436 { 437 immutable int i; 438 } 439 S s = void; 440 S[2] ss1 = void; 441 S[2] ss2 = void; 442 emplace(&s, 5); 443 assert(s.i == 5); 444 emplace(&ss1, s); 445 assert(ss1[0].i == 5 && ss1[1].i == 5); 446 emplace(&ss2, ss1); 447 assert(ss2 == ss1); 448 } 449 450 //Start testing emplace-args here 451 452 @system unittest 453 { 454 interface I {} 455 class K : I {} 456 457 K k = null, k2 = new K; 458 assert(k !is k2); 459 emplace!K(&k, k2); 460 assert(k is k2); 461 462 I i = null; 463 assert(i !is k); 464 emplace!I(&i, k); 465 assert(i is k); 466 } 467 468 @system unittest 469 { 470 static struct S 471 { 472 int i = 5; 473 void opAssign(S){assert(0);} 474 } 475 S[2] sa = void; 476 S[2] sb; 477 emplace(&sa, sb); 478 assert(sa[0].i == 5 && sa[1].i == 5); 479 } 480 481 //Start testing emplace-struct here 482 483 // Test constructor branch 484 @betterC 485 @system unittest 486 { 487 struct S 488 { 489 double x = 5, y = 6; 490 this(int a, int b) 491 { 492 assert(x == 5 && y == 6); 493 x = a; 494 y = b; 495 } 496 } 497 498 void[S.sizeof] s1 = void; 499 auto s2 = S(42, 43); 500 assert(*emplace!S(cast(S*) s1.ptr, s2) == s2); 501 assert(*emplace!S(cast(S*) s1, 44, 45) == S(44, 45)); 502 } 503 504 @system unittest 505 { 506 static struct __conv_EmplaceTest 507 { 508 int i = 3; 509 this(int i) 510 { 511 assert(this.i == 3 && i == 5); 512 this.i = i; 513 } 514 this(int i, ref int j) 515 { 516 assert(i == 5 && j == 6); 517 this.i = i; 518 ++j; 519 } 520 521 @disable: 522 this(); 523 this(this); 524 void opAssign(); 525 } 526 527 __conv_EmplaceTest k = void; 528 emplace(&k, 5); 529 assert(k.i == 5); 530 531 int var = 6; 532 __conv_EmplaceTest x = void; 533 emplace(&x, 5, var); 534 assert(x.i == 5); 535 assert(var == 7); 536 537 var = 6; 538 auto z = emplace!__conv_EmplaceTest(new void[__conv_EmplaceTest.sizeof], 5, var); 539 assert(z.i == 5); 540 assert(var == 7); 541 } 542 543 // Test matching fields branch 544 @betterC 545 @system unittest 546 { 547 struct S { uint n; } 548 S s; 549 emplace!S(&s, 2U); 550 assert(s.n == 2); 551 } 552 553 @betterC 554 @safe unittest 555 { 556 struct S { int a, b; this(int){} } 557 S s; 558 static assert(!__traits(compiles, emplace!S(&s, 2, 3))); 559 } 560 561 @betterC 562 @system unittest 563 { 564 struct S { int a, b = 7; } 565 S s1 = void, s2 = void; 566 567 emplace!S(&s1, 2); 568 assert(s1.a == 2 && s1.b == 7); 569 570 emplace!S(&s2, 2, 3); 571 assert(s2.a == 2 && s2.b == 3); 572 } 573 574 //opAssign 575 @betterC 576 @system unittest 577 { 578 static struct S 579 { 580 int i = 5; 581 void opAssign(int){assert(0);} 582 void opAssign(S){assert(0);} 583 } 584 S sa1 = void; 585 S sa2 = void; 586 S sb1 = S(1); 587 emplace(&sa1, sb1); 588 emplace(&sa2, 2); 589 assert(sa1.i == 1); 590 assert(sa2.i == 2); 591 } 592 593 //postblit precedence 594 @betterC 595 @system unittest 596 { 597 //Works, but breaks in "-w -O" because of @@@9332@@@. 598 //Uncomment test when 9332 is fixed. 599 static struct S 600 { 601 int i; 602 603 this(S other){assert(false);} 604 this(int i){this.i = i;} 605 this(this){} 606 } 607 S a = void; 608 assert(is(typeof({S b = a;}))); //Postblit 609 assert(is(typeof({S b = S(a);}))); //Constructor 610 auto b = S(5); 611 emplace(&a, b); 612 assert(a.i == 5); 613 614 static struct S2 615 { 616 int* p; 617 this(const S2){} 618 } 619 static assert(!is(immutable S2 : S2)); 620 S2 s2 = void; 621 immutable is2 = (immutable S2).init; 622 emplace(&s2, is2); 623 } 624 625 //nested structs and postblit 626 @system unittest 627 { 628 static struct S 629 { 630 int* p; 631 this(int i){p = [i].ptr;} 632 this(this) 633 { 634 if (p) 635 p = [*p].ptr; 636 } 637 } 638 static struct SS 639 { 640 S s; 641 void opAssign(const SS) 642 { 643 assert(0); 644 } 645 } 646 SS ssa = void; 647 SS ssb = SS(S(5)); 648 emplace(&ssa, ssb); 649 assert(*ssa.s.p == 5); 650 assert(ssa.s.p != ssb.s.p); 651 } 652 653 //disabled postblit 654 @betterC 655 @system unittest 656 { 657 static struct S1 658 { 659 int i; 660 @disable this(this); 661 } 662 S1 s1 = void; 663 emplace(&s1, 1); 664 assert(s1.i == 1); 665 static assert(!__traits(compiles, emplace(&s1, s1))); // copy disabled 666 static assert(__traits(compiles, emplace(&s1, move(s1)))); // move not affected 667 668 static struct S2 669 { 670 int i; 671 @disable this(this); 672 this(ref S2){} 673 } 674 S2 s2 = void; 675 //static assert(!__traits(compiles, emplace(&s2, 1))); 676 emplace(&s2, S2.init); 677 678 static struct SS1 679 { 680 S1 s; 681 } 682 SS1 ss1 = void; 683 emplace(&ss1); 684 static assert(!__traits(compiles, emplace(&ss1, ss1))); // copying disabled 685 static assert(__traits(compiles, emplace(&ss1, move(ss1)))); // move unaffected 686 687 static struct SS2 688 { 689 S2 s; 690 } 691 SS2 ss2 = void; 692 emplace(&ss2); 693 static assert(!__traits(compiles, emplace(&ss2, ss2))); // copying disabled 694 static assert(__traits(compiles, emplace(&ss2, SS2.init))); // move is OK 695 696 697 // SS1 sss1 = s1; //This doesn't compile 698 // SS1 sss1 = SS1(s1); //This doesn't compile 699 // So emplace shouldn't compile either 700 static assert(!__traits(compiles, emplace(&sss1, s1))); 701 static assert(!__traits(compiles, emplace(&sss2, s2))); 702 } 703 704 //Imutability 705 @betterC 706 @system unittest 707 { 708 //Castable immutability 709 { 710 static struct S1 711 { 712 int i; 713 } 714 static assert(is( immutable(S1) : S1)); 715 S1 sa = void; 716 auto sb = immutable(S1)(5); 717 emplace(&sa, sb); 718 assert(sa.i == 5); 719 } 720 //Un-castable immutability 721 { 722 static struct S2 723 { 724 int* p; 725 } 726 static assert(!is(immutable(S2) : S2)); 727 S2 sa = void; 728 auto sb = immutable(S2)(null); 729 assert(!__traits(compiles, emplace(&sa, sb))); 730 } 731 } 732 733 @betterC 734 @system unittest 735 { 736 static struct S 737 { 738 immutable int i; 739 immutable(int)* j; 740 } 741 S s = void; 742 emplace(&s, 1, null); 743 emplace(&s, 2, &s.i); 744 assert(s is S(2, &s.i)); 745 } 746 747 //Context pointer 748 @system unittest 749 { 750 int i = 0; 751 { 752 struct S1 753 { 754 void foo(){++i;} 755 } 756 S1 sa = void; 757 S1 sb; 758 emplace(&sa, sb); 759 sa.foo(); 760 assert(i == 1); 761 } 762 { 763 struct S2 764 { 765 void foo(){++i;} 766 this(this){} 767 } 768 S2 sa = void; 769 S2 sb; 770 emplace(&sa, sb); 771 sa.foo(); 772 assert(i == 2); 773 } 774 } 775 776 //Alias this 777 @betterC 778 @system unittest 779 { 780 static struct S 781 { 782 int i; 783 } 784 //By Ref 785 { 786 static struct SS1 787 { 788 int j; 789 S s; 790 alias s this; 791 } 792 S s = void; 793 SS1 ss = SS1(1, S(2)); 794 emplace(&s, ss); 795 assert(s.i == 2); 796 } 797 //By Value 798 { 799 static struct SS2 800 { 801 int j; 802 S s; 803 S foo() @property{return s;} 804 alias foo this; 805 } 806 S s = void; 807 SS2 ss = SS2(1, S(2)); 808 emplace(&s, ss); 809 assert(s.i == 2); 810 } 811 } 812 813 version (CoreUnittest) 814 { 815 //Ambiguity 816 private struct __std_conv_S 817 { 818 int i; 819 this(__std_conv_SS ss) {assert(0);} 820 static opCall(__std_conv_SS ss) 821 { 822 __std_conv_S s; s.i = ss.j; 823 return s; 824 } 825 } 826 private struct __std_conv_SS 827 { 828 int j; 829 __std_conv_S s; 830 ref __std_conv_S foo() return @property {s.i = j; return s;} 831 alias foo this; 832 } 833 } 834 835 @system unittest 836 { 837 static assert(is(__std_conv_SS : __std_conv_S)); 838 __std_conv_S s = void; 839 __std_conv_SS ss = __std_conv_SS(1); 840 841 __std_conv_S sTest1 = ss; //this calls "SS alias this" (and not "S.this(SS)") 842 emplace(&s, ss); //"alias this" should take precedence in emplace over "opCall" 843 assert(s.i == 1); 844 } 845 846 //Nested classes 847 @system unittest 848 { 849 class A{} 850 static struct S 851 { 852 A a; 853 } 854 S s1 = void; 855 S s2 = S(new A); 856 emplace(&s1, s2); 857 assert(s1.a is s2.a); 858 } 859 860 //safety & nothrow & CTFE 861 @betterC 862 @system unittest 863 { 864 //emplace should be safe for anything with no elaborate opassign 865 static struct S1 866 { 867 int i; 868 } 869 static struct S2 870 { 871 int i; 872 this(int j)@safe nothrow{i = j;} 873 } 874 875 int i; 876 S1 s1 = void; 877 S2 s2 = void; 878 879 auto pi = &i; 880 auto ps1 = &s1; 881 auto ps2 = &s2; 882 883 void foo() @safe nothrow 884 { 885 emplace(pi); 886 emplace(pi, 5); 887 emplace(ps1); 888 emplace(ps1, 5); 889 emplace(ps1, S1.init); 890 emplace(ps2); 891 emplace(ps2, 5); 892 emplace(ps2, S2.init); 893 } 894 foo(); 895 896 T bar(T)() @property 897 { 898 T t/+ = void+/; //CTFE void illegal 899 emplace(&t, 5); 900 return t; 901 } 902 // CTFE 903 enum a = bar!int; 904 static assert(a == 5); 905 enum b = bar!S1; 906 static assert(b.i == 5); 907 enum c = bar!S2; 908 static assert(c.i == 5); 909 // runtime 910 auto aa = bar!int; 911 assert(aa == 5); 912 auto bb = bar!S1; 913 assert(bb.i == 5); 914 auto cc = bar!S2; 915 assert(cc.i == 5); 916 } 917 918 @betterC 919 @system unittest 920 { 921 struct S 922 { 923 int[2] get(){return [1, 2];} 924 alias get this; 925 } 926 struct SS 927 { 928 int[2] ii; 929 } 930 struct ISS 931 { 932 int[2] ii; 933 } 934 S s; 935 SS ss = void; 936 ISS iss = void; 937 emplace(&ss, s); 938 emplace(&iss, s); 939 assert(ss.ii == [1, 2]); 940 assert(iss.ii == [1, 2]); 941 } 942 943 //disable opAssign 944 @betterC 945 @system unittest 946 { 947 static struct S 948 { 949 @disable void opAssign(S); 950 } 951 S s; 952 emplace(&s, S.init); 953 } 954 955 //opCall 956 @betterC 957 @system unittest 958 { 959 int i; 960 //Without constructor 961 { 962 static struct S1 963 { 964 int i; 965 static S1 opCall(int*){assert(0);} 966 } 967 S1 s = void; 968 static assert(!__traits(compiles, emplace(&s, 1))); 969 } 970 //With constructor 971 { 972 static struct S2 973 { 974 int i = 0; 975 static S2 opCall(int*){assert(0);} 976 static S2 opCall(int){assert(0);} 977 this(int i){this.i = i;} 978 } 979 S2 s = void; 980 emplace(&s, 1); 981 assert(s.i == 1); 982 } 983 //With postblit ambiguity 984 { 985 static struct S3 986 { 987 int i = 0; 988 static S3 opCall(ref S3){assert(0);} 989 } 990 S3 s = void; 991 emplace(&s, S3.init); 992 } 993 } 994 995 //static arrays 996 @system unittest 997 { 998 static struct S 999 { 1000 int[2] ii; 1001 } 1002 static struct IS 1003 { 1004 immutable int[2] ii; 1005 } 1006 int[2] ii; 1007 S s = void; 1008 IS ims = void; 1009 ubyte ub = 2; 1010 emplace(&s, ub); 1011 emplace(&s, ii); 1012 emplace(&ims, ub); 1013 emplace(&ims, ii); 1014 uint[2] uu; 1015 static assert(!__traits(compiles, {S ss = S(uu);})); 1016 static assert(!__traits(compiles, emplace(&s, uu))); 1017 } 1018 1019 @system unittest 1020 { 1021 int[2] sii; 1022 int[2] sii2; 1023 uint[2] uii; 1024 uint[2] uii2; 1025 emplace(&sii, 1); 1026 emplace(&sii, 1U); 1027 emplace(&uii, 1); 1028 emplace(&uii, 1U); 1029 emplace(&sii, sii2); 1030 //emplace(&sii, uii2); //Sorry, this implementation doesn't know how to... 1031 //emplace(&uii, sii2); //Sorry, this implementation doesn't know how to... 1032 emplace(&uii, uii2); 1033 emplace(&sii, sii2[]); 1034 //emplace(&sii, uii2[]); //Sorry, this implementation doesn't know how to... 1035 //emplace(&uii, sii2[]); //Sorry, this implementation doesn't know how to... 1036 emplace(&uii, uii2[]); 1037 } 1038 1039 @system unittest 1040 { 1041 bool allowDestruction = false; 1042 struct S 1043 { 1044 int i; 1045 this(this){} 1046 ~this(){assert(allowDestruction);} 1047 } 1048 S s = S(1); 1049 S[2] ss1 = void; 1050 S[2] ss2 = void; 1051 S[2] ss3 = void; 1052 emplace(&ss1, s); 1053 emplace(&ss2, ss1); 1054 emplace(&ss3, ss2[]); 1055 assert(ss1[1] == s); 1056 assert(ss2[1] == s); 1057 assert(ss3[1] == s); 1058 allowDestruction = true; 1059 } 1060 1061 @system unittest 1062 { 1063 //Checks postblit, construction, and context pointer 1064 int count = 0; 1065 struct S 1066 { 1067 this(this) 1068 { 1069 ++count; 1070 } 1071 ~this() 1072 { 1073 --count; 1074 } 1075 } 1076 1077 S s; 1078 { 1079 S[4] ss = void; 1080 emplace(&ss, s); 1081 assert(count == 4); 1082 } 1083 assert(count == 0); 1084 } 1085 1086 @system unittest 1087 { 1088 struct S 1089 { 1090 int i; 1091 } 1092 S s; 1093 S[2][2][2] sss = void; 1094 emplace(&sss, s); 1095 } 1096 1097 @system unittest //Constness 1098 { 1099 import core.internal.lifetime : emplaceRef; 1100 1101 int a = void; 1102 emplaceRef!(const int)(a, 5); 1103 1104 immutable i = 5; 1105 const(int)* p = void; 1106 emplaceRef!(const int*)(p, &i); 1107 1108 struct S 1109 { 1110 int* p; 1111 } 1112 alias IS = immutable(S); 1113 S s = void; 1114 emplaceRef!IS(s, IS()); 1115 S[2] ss = void; 1116 emplaceRef!(IS[2])(ss, IS()); 1117 1118 IS[2] iss = IS.init; 1119 emplaceRef!(IS[2])(ss, iss); 1120 emplaceRef!(IS[2])(ss, iss[]); 1121 } 1122 1123 @betterC 1124 pure nothrow @safe @nogc unittest 1125 { 1126 import core.internal.lifetime : emplaceRef; 1127 1128 int i; 1129 emplaceRef(i); 1130 emplaceRef!int(i); 1131 emplaceRef(i, 5); 1132 emplaceRef!int(i, 5); 1133 } 1134 1135 // Test attribute propagation for UDTs 1136 pure nothrow @safe /* @nogc */ unittest 1137 { 1138 import core.internal.lifetime : emplaceRef; 1139 1140 static struct Safe 1141 { 1142 this(this) pure nothrow @safe @nogc {} 1143 } 1144 1145 Safe safe = void; 1146 emplaceRef(safe, Safe()); 1147 1148 Safe[1] safeArr = [Safe()]; 1149 Safe[1] uninitializedSafeArr = void; 1150 emplaceRef(uninitializedSafeArr, safe); 1151 emplaceRef(uninitializedSafeArr, safeArr); 1152 1153 static struct Unsafe 1154 { 1155 this(this) @system {} 1156 } 1157 1158 Unsafe unsafe = void; 1159 static assert(!__traits(compiles, emplaceRef(unsafe, unsafe))); 1160 1161 Unsafe[1] unsafeArr = [Unsafe()]; 1162 Unsafe[1] uninitializedUnsafeArr = void; 1163 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafe))); 1164 static assert(!__traits(compiles, emplaceRef(uninitializedUnsafeArr, unsafeArr))); 1165 } 1166 1167 @betterC 1168 @system unittest 1169 { 1170 // Issue 15313 1171 static struct Node 1172 { 1173 int payload; 1174 Node* next; 1175 uint refs; 1176 } 1177 1178 import core.stdc.stdlib : malloc; 1179 void[] buf = malloc(Node.sizeof)[0 .. Node.sizeof]; 1180 1181 const Node* n = emplace!(const Node)(buf, 42, null, 10); 1182 assert(n.payload == 42); 1183 assert(n.next == null); 1184 assert(n.refs == 10); 1185 } 1186 1187 @system unittest 1188 { 1189 class A 1190 { 1191 int x = 5; 1192 int y = 42; 1193 this(int z) 1194 { 1195 assert(x == 5 && y == 42); 1196 x = y = z; 1197 } 1198 } 1199 void[] buf; 1200 1201 static align(__traits(classInstanceAlignment, A)) byte[__traits(classInstanceSize, A)] sbuf; 1202 buf = sbuf[]; 1203 auto a = emplace!A(buf, 55); 1204 assert(a.x == 55 && a.y == 55); 1205 1206 // emplace in bigger buffer 1207 buf = new byte[](__traits(classInstanceSize, A) + 10); 1208 a = emplace!A(buf, 55); 1209 assert(a.x == 55 && a.y == 55); 1210 1211 // need ctor args 1212 static assert(!is(typeof(emplace!A(buf)))); 1213 } 1214 1215 //constructor arguments forwarding 1216 @betterC 1217 @system unittest 1218 { 1219 static struct S 1220 { 1221 this()(auto ref long arg) 1222 { 1223 // assert that arg is an lvalue 1224 static assert(__traits(isRef, arg)); 1225 } 1226 this()(auto ref double arg) 1227 // assert that arg is an rvalue 1228 { 1229 static assert(!__traits(isRef, arg)); 1230 } 1231 } 1232 S obj = void; 1233 long i; 1234 emplace(&obj, i); // lvalue 1235 emplace(&obj, 0.0); // rvalue 1236 } 1237 // Bulk of emplace unittests ends here 1238 1239 /** 1240 * Emplaces a copy of the specified source value into uninitialized memory, 1241 * i.e., simulates `T target = source` copy-construction for cases where the 1242 * target memory is already allocated and to be initialized with a copy. 1243 * 1244 * Params: 1245 * source = value to be copied into target 1246 * target = uninitialized value to be initialized with a copy of source 1247 */ 1248 void copyEmplace(S, T)(ref S source, ref T target) @system 1249 if (is(immutable S == immutable T)) 1250 { 1251 import core.internal.traits : BaseElemOf, hasElaborateCopyConstructor, Unconst, Unqual; 1252 1253 // cannot have the following as simple template constraint due to nested-struct special case... 1254 static if (!__traits(compiles, (ref S src) { T tgt = src; })) 1255 { 1256 alias B = BaseElemOf!T; 1257 enum isNestedStruct = is(B == struct) && __traits(isNested, B); 1258 static assert(isNestedStruct, "cannot copy-construct " ~ T.stringof ~ " from " ~ S.stringof); 1259 } 1260 1261 void blit() 1262 { 1263 import core.stdc.string : memcpy; 1264 memcpy(cast(Unqual!(T)*) &target, cast(Unqual!(T)*) &source, T.sizeof); 1265 } 1266 1267 static if (is(T == struct)) 1268 { 1269 static if (__traits(hasPostblit, T)) 1270 { 1271 blit(); 1272 (cast() target).__xpostblit(); 1273 } 1274 else static if (__traits(hasCopyConstructor, T)) 1275 { 1276 // https://issues.dlang.org/show_bug.cgi?id=22766 1277 import core.internal.lifetime : emplaceInitializer; 1278 emplaceInitializer(*(cast(Unqual!T*)&target)); 1279 static if (__traits(isNested, T)) 1280 { 1281 // copy context pointer 1282 *(cast(void**) &target.tupleof[$-1]) = cast(void*) source.tupleof[$-1]; 1283 } 1284 target.__ctor(source); // invoke copy ctor 1285 } 1286 else 1287 { 1288 blit(); // no opAssign 1289 } 1290 } 1291 else static if (is(T == E[n], E, size_t n)) 1292 { 1293 static if (hasElaborateCopyConstructor!E) 1294 { 1295 size_t i; 1296 try 1297 { 1298 for (i = 0; i < n; i++) 1299 copyEmplace(source[i], target[i]); 1300 } 1301 catch (Exception e) 1302 { 1303 // destroy, in reverse order, what we've constructed so far 1304 while (i--) 1305 destroy(*cast(Unconst!(E)*) &target[i]); 1306 throw e; 1307 } 1308 } 1309 else // trivial copy 1310 { 1311 blit(); // all elements at once 1312 } 1313 } 1314 else 1315 { 1316 *cast(Unconst!(T)*) &target = *cast(Unconst!(T)*) &source; 1317 } 1318 } 1319 1320 /// 1321 @betterC 1322 @system pure nothrow @nogc unittest 1323 { 1324 int source = 123; 1325 int target = void; 1326 copyEmplace(source, target); 1327 assert(target == 123); 1328 } 1329 1330 /// 1331 @betterC 1332 @system pure nothrow @nogc unittest 1333 { 1334 immutable int[1][1] source = [ [123] ]; 1335 immutable int[1][1] target = void; 1336 copyEmplace(source, target); 1337 assert(target[0][0] == 123); 1338 } 1339 1340 /// 1341 @betterC 1342 @system pure nothrow @nogc unittest 1343 { 1344 struct S 1345 { 1346 int x; 1347 void opAssign(const scope ref S rhs) @safe pure nothrow @nogc 1348 { 1349 assert(0); 1350 } 1351 } 1352 1353 S source = S(42); 1354 S target = void; 1355 copyEmplace(source, target); 1356 assert(target.x == 42); 1357 } 1358 1359 // preserve shared-ness 1360 @system pure nothrow unittest 1361 { 1362 auto s = new Object(); 1363 auto ss = new shared Object(); 1364 1365 Object t; 1366 shared Object st; 1367 1368 copyEmplace(s, t); 1369 assert(t is s); 1370 1371 copyEmplace(ss, st); 1372 assert(st is ss); 1373 1374 static assert(!__traits(compiles, copyEmplace(s, st))); 1375 static assert(!__traits(compiles, copyEmplace(ss, t))); 1376 } 1377 1378 // https://issues.dlang.org/show_bug.cgi?id=22766 1379 @system pure nothrow @nogc unittest 1380 { 1381 static struct S 1382 { 1383 @disable this(); 1384 this(int) @safe pure nothrow @nogc{} 1385 this(ref const(S) other) @safe pure nothrow @nogc {} 1386 } 1387 1388 S s1 = S(1); 1389 S s2 = void; 1390 copyEmplace(s1, s2); 1391 assert(s2 == S(1)); 1392 } 1393 1394 version (DigitalMars) version (X86) version (Posix) version = DMD_X86_Posix; 1395 1396 // don't violate immutability for reference types 1397 @system pure nothrow unittest 1398 { 1399 auto s = new Object(); 1400 auto si = new immutable Object(); 1401 1402 Object t; 1403 immutable Object ti; 1404 1405 copyEmplace(s, t); 1406 assert(t is s); 1407 1408 copyEmplace(si, ti); 1409 version (DMD_X86_Posix) { /* wrongly fails without -O */ } else 1410 assert(ti is si); 1411 1412 static assert(!__traits(compiles, copyEmplace(s, ti))); 1413 static assert(!__traits(compiles, copyEmplace(si, t))); 1414 } 1415 1416 version (CoreUnittest) 1417 { 1418 private void testCopyEmplace(S, T)(const scope T* expected = null) 1419 { 1420 S source; 1421 T target = void; 1422 copyEmplace(source, target); 1423 if (expected) 1424 assert(target == *expected); 1425 else 1426 { 1427 T expectedCopy = source; 1428 assert(target == expectedCopy); 1429 } 1430 } 1431 } 1432 1433 // postblit 1434 @system pure nothrow @nogc unittest 1435 { 1436 static struct S 1437 { 1438 @safe pure nothrow @nogc: 1439 int x = 42; 1440 this(this) { x += 10; } 1441 } 1442 1443 testCopyEmplace!(S, S)(); 1444 testCopyEmplace!(immutable S, S)(); 1445 testCopyEmplace!(S, immutable S)(); 1446 testCopyEmplace!(immutable S, immutable S)(); 1447 1448 testCopyEmplace!(S[1], S[1])(); 1449 testCopyEmplace!(immutable S[1], S[1])(); 1450 1451 // copying to an immutable static array works, but `T expected = source` 1452 // wrongly ignores the postblit: https://issues.dlang.org/show_bug.cgi?id=8950 1453 immutable S[1] expectedImmutable = [S(52)]; 1454 testCopyEmplace!(S[1], immutable S[1])(&expectedImmutable); 1455 testCopyEmplace!(immutable S[1], immutable S[1])(&expectedImmutable); 1456 } 1457 1458 // copy constructors 1459 @system pure nothrow @nogc unittest 1460 { 1461 static struct S 1462 { 1463 @safe pure nothrow @nogc: 1464 int x = 42; 1465 this(int x) { this.x = x; } 1466 this(const scope ref S rhs) { x = rhs.x + 10; } 1467 this(const scope ref S rhs) immutable { x = rhs.x + 20; } 1468 } 1469 1470 testCopyEmplace!(S, S)(); 1471 testCopyEmplace!(immutable S, S)(); 1472 testCopyEmplace!(S, immutable S)(); 1473 testCopyEmplace!(immutable S, immutable S)(); 1474 1475 // static arrays work, but `T expected = source` wrongly ignores copy ctors 1476 // https://issues.dlang.org/show_bug.cgi?id=20365 1477 S[1] expectedMutable = [S(52)]; 1478 immutable S[1] expectedImmutable = [immutable S(62)]; 1479 testCopyEmplace!(S[1], S[1])(&expectedMutable); 1480 testCopyEmplace!(immutable S[1], S[1])(&expectedMutable); 1481 testCopyEmplace!(S[1], immutable S[1])(&expectedImmutable); 1482 testCopyEmplace!(immutable S[1], immutable S[1])(&expectedImmutable); 1483 } 1484 1485 // copy constructor in nested struct 1486 @system pure nothrow unittest 1487 { 1488 int copies; 1489 struct S 1490 { 1491 @safe pure nothrow @nogc: 1492 size_t x = 42; 1493 this(size_t x) { this.x = x; } 1494 this(const scope ref S rhs) 1495 { 1496 assert(x == 42); // T.init 1497 x = rhs.x; 1498 ++copies; 1499 } 1500 } 1501 1502 { 1503 copies = 0; 1504 S source = S(123); 1505 immutable S target = void; 1506 copyEmplace(source, target); 1507 assert(target is source); 1508 assert(copies == 1); 1509 } 1510 1511 { 1512 copies = 0; 1513 immutable S[1] source = [immutable S(456)]; 1514 S[1] target = void; 1515 copyEmplace(source, target); 1516 assert(target[0] is source[0]); 1517 assert(copies == 1); 1518 } 1519 } 1520 1521 // destruction of partially copied static array 1522 @system unittest 1523 { 1524 static struct S 1525 { 1526 __gshared int[] deletions; 1527 int x; 1528 this(this) { if (x == 5) throw new Exception(""); } 1529 ~this() { deletions ~= x; } 1530 } 1531 1532 alias T = immutable S[3][2]; 1533 T source = [ [S(1), S(2), S(3)], [S(4), S(5), S(6)] ]; 1534 T target = void; 1535 try 1536 { 1537 copyEmplace(source, target); 1538 assert(0); 1539 } 1540 catch (Exception) 1541 { 1542 static immutable expectedDeletions = [ 4, 3, 2, 1 ]; 1543 version (DigitalMars) 1544 { 1545 assert(S.deletions == expectedDeletions || 1546 S.deletions == [ 4 ]); // FIXME: happens with -O 1547 } 1548 else 1549 assert(S.deletions == expectedDeletions); 1550 } 1551 } 1552 1553 /** 1554 Forwards function arguments while keeping `out`, `ref`, and `lazy` on 1555 the parameters. 1556 1557 Params: 1558 args = a parameter list or an $(REF AliasSeq,std,meta). 1559 Returns: 1560 An `AliasSeq` of `args` with `out`, `ref`, and `lazy` saved. 1561 */ 1562 template forward(args...) 1563 { 1564 import core.internal.traits : AliasSeq; 1565 1566 template fwd(alias arg) 1567 { 1568 // by ref || lazy || const/immutable 1569 static if (__traits(isRef, arg) || 1570 __traits(isOut, arg) || 1571 __traits(isLazy, arg) || 1572 !is(typeof(move(arg)))) 1573 alias fwd = arg; 1574 // (r)value 1575 else 1576 @property auto fwd() 1577 { 1578 version (DigitalMars) { /* @@BUG 23890@@ */ } else pragma(inline, true); 1579 return move(arg); 1580 } 1581 } 1582 1583 alias Result = AliasSeq!(); 1584 static foreach (arg; args) 1585 Result = AliasSeq!(Result, fwd!arg); 1586 static if (Result.length == 1) 1587 alias forward = Result[0]; 1588 else 1589 alias forward = Result; 1590 } 1591 1592 /// 1593 @safe unittest 1594 { 1595 class C 1596 { 1597 static int foo(int n) { return 1; } 1598 static int foo(ref int n) { return 2; } 1599 } 1600 1601 // with forward 1602 int bar()(auto ref int x) { return C.foo(forward!x); } 1603 1604 // without forward 1605 int baz()(auto ref int x) { return C.foo(x); } 1606 1607 int i; 1608 assert(bar(1) == 1); 1609 assert(bar(i) == 2); 1610 1611 assert(baz(1) == 2); 1612 assert(baz(i) == 2); 1613 } 1614 1615 /// 1616 @safe unittest 1617 { 1618 void foo(int n, ref string s) { s = null; foreach (i; 0 .. n) s ~= "Hello"; } 1619 1620 // forwards all arguments which are bound to parameter tuple 1621 void bar(Args...)(auto ref Args args) { return foo(forward!args); } 1622 1623 // forwards all arguments with swapping order 1624 void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); } 1625 1626 string s; 1627 bar(1, s); 1628 assert(s == "Hello"); 1629 baz(s, 2); 1630 assert(s == "HelloHello"); 1631 } 1632 1633 @safe unittest 1634 { 1635 auto foo(TL...)(auto ref TL args) 1636 { 1637 string result = ""; 1638 foreach (i, _; args) 1639 { 1640 //pragma(msg, "[",i,"] ", __traits(isRef, args[i]) ? "L" : "R"); 1641 result ~= __traits(isRef, args[i]) ? "L" : "R"; 1642 } 1643 return result; 1644 } 1645 1646 string bar(TL...)(auto ref TL args) 1647 { 1648 return foo(forward!args); 1649 } 1650 string baz(TL...)(auto ref TL args) 1651 { 1652 int x; 1653 return foo(forward!args[3], forward!args[2], 1, forward!args[1], forward!args[0], x); 1654 } 1655 1656 struct S {} 1657 S makeS(){ return S(); } 1658 int n; 1659 string s; 1660 assert(bar(S(), makeS(), n, s) == "RRLL"); 1661 assert(baz(S(), makeS(), n, s) == "LLRRRL"); 1662 } 1663 1664 @betterC 1665 @safe unittest 1666 { 1667 ref int foo(return ref int a) { return a; } 1668 ref int bar(Args)(auto ref Args args) 1669 { 1670 return foo(forward!args); 1671 } 1672 static assert(!__traits(compiles, { auto x1 = bar(3); })); // case of NG 1673 int value = 3; 1674 auto x2 = bar(value); // case of OK 1675 } 1676 1677 /// 1678 @betterC 1679 @safe unittest 1680 { 1681 struct X { 1682 int i; 1683 this(this) 1684 { 1685 ++i; 1686 } 1687 } 1688 1689 struct Y 1690 { 1691 private X x_; 1692 this()(auto ref X x) 1693 { 1694 x_ = forward!x; 1695 } 1696 } 1697 1698 struct Z 1699 { 1700 private const X x_; 1701 this()(auto ref X x) 1702 { 1703 x_ = forward!x; 1704 } 1705 this()(auto const ref X x) 1706 { 1707 x_ = forward!x; 1708 } 1709 } 1710 1711 X x; 1712 const X cx; 1713 auto constX = (){ const X x; return x; }; 1714 static assert(__traits(compiles, { Y y = x; })); 1715 static assert(__traits(compiles, { Y y = X(); })); 1716 static assert(!__traits(compiles, { Y y = cx; })); 1717 static assert(!__traits(compiles, { Y y = constX(); })); 1718 static assert(__traits(compiles, { Z z = x; })); 1719 static assert(__traits(compiles, { Z z = X(); })); 1720 static assert(__traits(compiles, { Z z = cx; })); 1721 static assert(__traits(compiles, { Z z = constX(); })); 1722 1723 1724 Y y1 = x; 1725 // ref lvalue, copy 1726 assert(y1.x_.i == 1); 1727 Y y2 = X(); 1728 // rvalue, move 1729 assert(y2.x_.i == 0); 1730 1731 Z z1 = x; 1732 // ref lvalue, copy 1733 assert(z1.x_.i == 1); 1734 Z z2 = X(); 1735 // rvalue, move 1736 assert(z2.x_.i == 0); 1737 Z z3 = cx; 1738 // ref const lvalue, copy 1739 assert(z3.x_.i == 1); 1740 Z z4 = constX(); 1741 // const rvalue, copy 1742 assert(z4.x_.i == 1); 1743 } 1744 1745 // lazy -> lazy 1746 @betterC 1747 @safe unittest 1748 { 1749 int foo1(lazy int i) { return i; } 1750 int foo2(A)(auto ref A i) { return foo1(forward!i); } 1751 int foo3(lazy int i) { return foo2(i); } 1752 1753 int numCalls = 0; 1754 assert(foo3({ ++numCalls; return 42; }()) == 42); 1755 assert(numCalls == 1); 1756 } 1757 1758 // lazy -> non-lazy 1759 @betterC 1760 @safe unittest 1761 { 1762 int foo1(int a, int b) { return a + b; } 1763 int foo2(A...)(auto ref A args) { return foo1(forward!args); } 1764 int foo3(int a, lazy int b) { return foo2(a, b); } 1765 1766 int numCalls; 1767 assert(foo3(11, { ++numCalls; return 31; }()) == 42); 1768 assert(numCalls == 1); 1769 } 1770 1771 // non-lazy -> lazy 1772 @betterC 1773 @safe unittest 1774 { 1775 int foo1(int a, lazy int b) { return a + b; } 1776 int foo2(A...)(auto ref A args) { return foo1(forward!args); } 1777 int foo3(int a, int b) { return foo2(a, b); } 1778 1779 assert(foo3(11, 31) == 42); 1780 } 1781 1782 // out 1783 @betterC 1784 @safe unittest 1785 { 1786 void foo1(int a, out int b) { b = a; } 1787 void foo2(A...)(auto ref A args) { foo1(forward!args); } 1788 void foo3(int a, out int b) { foo2(a, b); } 1789 1790 int b; 1791 foo3(42, b); 1792 assert(b == 42); 1793 } 1794 1795 // move 1796 /** 1797 Moves `source` into `target`, via a destructive copy when necessary. 1798 1799 If `T` is a struct with a destructor or postblit defined, source is reset 1800 to its `.init` value after it is moved into target, otherwise it is 1801 left unchanged. 1802 1803 Preconditions: 1804 If source has internal pointers that point to itself and doesn't define 1805 opPostMove, it cannot be moved, and will trigger an assertion failure. 1806 1807 Params: 1808 source = Data to copy. 1809 target = Where to copy into. The destructor, if any, is invoked before the 1810 copy is performed. 1811 */ 1812 void move(T)(ref T source, ref T target) 1813 { 1814 moveImpl(target, source); 1815 } 1816 1817 /// For non-struct types, `move` just performs `target = source`: 1818 @safe unittest 1819 { 1820 Object obj1 = new Object; 1821 Object obj2 = obj1; 1822 Object obj3; 1823 1824 move(obj2, obj3); 1825 assert(obj3 is obj1); 1826 // obj2 unchanged 1827 assert(obj2 is obj1); 1828 } 1829 1830 /// 1831 pure nothrow @safe @nogc unittest 1832 { 1833 // Structs without destructors are simply copied 1834 struct S1 1835 { 1836 int a = 1; 1837 int b = 2; 1838 } 1839 S1 s11 = { 10, 11 }; 1840 S1 s12; 1841 1842 move(s11, s12); 1843 1844 assert(s12 == S1(10, 11)); 1845 assert(s11 == s12); 1846 1847 // But structs with destructors or postblits are reset to their .init value 1848 // after copying to the target. 1849 struct S2 1850 { 1851 int a = 1; 1852 int b = 2; 1853 1854 ~this() pure nothrow @safe @nogc { } 1855 } 1856 S2 s21 = { 3, 4 }; 1857 S2 s22; 1858 1859 move(s21, s22); 1860 1861 assert(s21 == S2(1, 2)); 1862 assert(s22 == S2(3, 4)); 1863 } 1864 1865 @safe unittest 1866 { 1867 import core.internal.traits; 1868 1869 assertCTFEable!((){ 1870 Object obj1 = new Object; 1871 Object obj2 = obj1; 1872 Object obj3; 1873 move(obj2, obj3); 1874 assert(obj3 is obj1); 1875 1876 static struct S1 { int a = 1, b = 2; } 1877 S1 s11 = { 10, 11 }; 1878 S1 s12; 1879 move(s11, s12); 1880 assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11); 1881 1882 static struct S2 { int a = 1; int * b; } 1883 S2 s21 = { 10, null }; 1884 s21.b = new int; 1885 S2 s22; 1886 move(s21, s22); 1887 assert(s21 == s22); 1888 }); 1889 // Issue 5661 test(1) 1890 static struct S3 1891 { 1892 static struct X { int n = 0; ~this(){n = 0;} } 1893 X x; 1894 } 1895 static assert(hasElaborateDestructor!S3); 1896 S3 s31, s32; 1897 s31.x.n = 1; 1898 move(s31, s32); 1899 assert(s31.x.n == 0); 1900 assert(s32.x.n == 1); 1901 1902 // Issue 5661 test(2) 1903 static struct S4 1904 { 1905 static struct X { int n = 0; this(this){n = 0;} } 1906 X x; 1907 } 1908 static assert(hasElaborateCopyConstructor!S4); 1909 S4 s41, s42; 1910 s41.x.n = 1; 1911 move(s41, s42); 1912 assert(s41.x.n == 0); 1913 assert(s42.x.n == 1); 1914 1915 // Issue 13990 test 1916 class S5; 1917 1918 S5 s51; 1919 S5 s52 = s51; 1920 S5 s53; 1921 move(s52, s53); 1922 assert(s53 is s51); 1923 } 1924 1925 /// Ditto 1926 T move(T)(return scope ref T source) 1927 { 1928 return moveImpl(source); 1929 } 1930 1931 /// Non-copyable structs can still be moved: 1932 pure nothrow @safe @nogc unittest 1933 { 1934 struct S 1935 { 1936 int a = 1; 1937 @disable this(this); 1938 ~this() pure nothrow @safe @nogc {} 1939 } 1940 S s1; 1941 s1.a = 2; 1942 S s2 = move(s1); 1943 assert(s1.a == 1); 1944 assert(s2.a == 2); 1945 } 1946 1947 // https://issues.dlang.org/show_bug.cgi?id=20869 1948 // `move` should propagate the attributes of `opPostMove` 1949 @system unittest 1950 { 1951 static struct S 1952 { 1953 void opPostMove(const ref S old) nothrow @system 1954 { 1955 __gshared int i; 1956 new int(i++); // Force @gc impure @system 1957 } 1958 } 1959 1960 alias T = void function() @system nothrow; 1961 static assert(is(typeof({ S s; move(s); }) == T)); 1962 static assert(is(typeof({ S s; move(s, s); }) == T)); 1963 } 1964 1965 private void moveImpl(T)(scope ref T target, return scope ref T source) 1966 { 1967 import core.internal.traits : hasElaborateDestructor; 1968 1969 static if (is(T == struct)) 1970 { 1971 // Unsafe when compiling without -preview=dip1000 1972 if ((() @trusted => &source == &target)()) return; 1973 // Destroy target before overwriting it 1974 static if (hasElaborateDestructor!T) target.__xdtor(); 1975 } 1976 // move and emplace source into target 1977 moveEmplaceImpl(target, source); 1978 } 1979 1980 private T moveImpl(T)(return scope ref T source) 1981 { 1982 // Properly infer safety from moveEmplaceImpl as the implementation below 1983 // might void-initialize pointers in result and hence needs to be @trusted 1984 if (false) moveEmplaceImpl(source, source); 1985 1986 return trustedMoveImpl(source); 1987 } 1988 1989 private T trustedMoveImpl(T)(return scope ref T source) @trusted 1990 { 1991 T result = void; 1992 moveEmplaceImpl(result, source); 1993 return result; 1994 } 1995 1996 @safe unittest 1997 { 1998 import core.internal.traits; 1999 2000 assertCTFEable!((){ 2001 Object obj1 = new Object; 2002 Object obj2 = obj1; 2003 Object obj3 = move(obj2); 2004 assert(obj3 is obj1); 2005 2006 static struct S1 { int a = 1, b = 2; } 2007 S1 s11 = { 10, 11 }; 2008 S1 s12 = move(s11); 2009 assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11); 2010 2011 static struct S2 { int a = 1; int * b; } 2012 S2 s21 = { 10, null }; 2013 s21.b = new int; 2014 S2 s22 = move(s21); 2015 assert(s21 == s22); 2016 }); 2017 2018 // Issue 5661 test(1) 2019 static struct S3 2020 { 2021 static struct X { int n = 0; ~this(){n = 0;} } 2022 X x; 2023 } 2024 static assert(hasElaborateDestructor!S3); 2025 S3 s31; 2026 s31.x.n = 1; 2027 S3 s32 = move(s31); 2028 assert(s31.x.n == 0); 2029 assert(s32.x.n == 1); 2030 2031 // Issue 5661 test(2) 2032 static struct S4 2033 { 2034 static struct X { int n = 0; this(this){n = 0;} } 2035 X x; 2036 } 2037 static assert(hasElaborateCopyConstructor!S4); 2038 S4 s41; 2039 s41.x.n = 1; 2040 S4 s42 = move(s41); 2041 assert(s41.x.n == 0); 2042 assert(s42.x.n == 1); 2043 2044 // Issue 13990 test 2045 class S5; 2046 2047 S5 s51; 2048 S5 s52 = s51; 2049 S5 s53; 2050 s53 = move(s52); 2051 assert(s53 is s51); 2052 } 2053 2054 @betterC 2055 @system unittest 2056 { 2057 static struct S { int n = 0; ~this() @system { n = 0; } } 2058 S a, b; 2059 static assert(!__traits(compiles, () @safe { move(a, b); })); 2060 static assert(!__traits(compiles, () @safe { move(a); })); 2061 a.n = 1; 2062 () @trusted { move(a, b); }(); 2063 assert(a.n == 0); 2064 a.n = 1; 2065 () @trusted { move(a); }(); 2066 assert(a.n == 0); 2067 } 2068 /+ this can't be tested in druntime, tests are still run in phobos 2069 @safe unittest//Issue 6217 2070 { 2071 import std.algorithm.iteration : map; 2072 auto x = map!"a"([1,2,3]); 2073 x = move(x); 2074 } 2075 +/ 2076 @betterC 2077 @safe unittest// Issue 8055 2078 { 2079 static struct S 2080 { 2081 int x; 2082 ~this() 2083 { 2084 assert(x == 0); 2085 } 2086 } 2087 S foo(S s) 2088 { 2089 return move(s); 2090 } 2091 S a; 2092 a.x = 0; 2093 auto b = foo(a); 2094 assert(b.x == 0); 2095 } 2096 2097 @system unittest// Issue 8057 2098 { 2099 int n = 10; 2100 struct S 2101 { 2102 int x; 2103 ~this() 2104 { 2105 // Access to enclosing scope 2106 assert(n == 10); 2107 } 2108 } 2109 S foo(S s) 2110 { 2111 // Move nested struct 2112 return move(s); 2113 } 2114 S a; 2115 a.x = 1; 2116 auto b = foo(a); 2117 assert(b.x == 1); 2118 2119 // Regression 8171 2120 static struct Array(T) 2121 { 2122 // nested struct has no member 2123 struct Payload 2124 { 2125 ~this() {} 2126 } 2127 } 2128 Array!int.Payload x = void; 2129 move(x); 2130 move(x, x); 2131 } 2132 2133 private enum bool hasContextPointers(T) = { 2134 static if (__traits(isStaticArray, T)) 2135 { 2136 return hasContextPointers!(typeof(T.init[0])); 2137 } 2138 else static if (is(T == struct)) 2139 { 2140 import core.internal.traits : anySatisfy; 2141 return __traits(isNested, T) || anySatisfy!(hasContextPointers, typeof(T.tupleof)); 2142 } 2143 else return false; 2144 } (); 2145 2146 @safe @nogc nothrow pure unittest 2147 { 2148 static assert(!hasContextPointers!int); 2149 static assert(!hasContextPointers!(void*)); 2150 2151 static struct S {} 2152 static assert(!hasContextPointers!S); 2153 static assert(!hasContextPointers!(S[1])); 2154 2155 struct Nested 2156 { 2157 void foo() {} 2158 } 2159 2160 static assert(hasContextPointers!Nested); 2161 static assert(hasContextPointers!(Nested[1])); 2162 2163 static struct OneLevel 2164 { 2165 int before; 2166 Nested n; 2167 int after; 2168 } 2169 2170 static assert(hasContextPointers!OneLevel); 2171 static assert(hasContextPointers!(OneLevel[1])); 2172 2173 static struct TwoLevels 2174 { 2175 int before; 2176 OneLevel o; 2177 int after; 2178 } 2179 2180 static assert(hasContextPointers!TwoLevels); 2181 static assert(hasContextPointers!(TwoLevels[1])); 2182 2183 union U 2184 { 2185 Nested n; 2186 } 2187 2188 // unions can have false positives, so this query ignores them 2189 static assert(!hasContextPointers!U); 2190 } 2191 2192 // target must be first-parameter, because in void-functions DMD + dip1000 allows it to take the place of a return-scope 2193 private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source) 2194 { 2195 // TODO: this assert pulls in half of phobos. we need to work out an alternative assert strategy. 2196 // static if (!is(T == class) && hasAliasing!T) if (!__ctfe) 2197 // { 2198 // import std.exception : doesPointTo; 2199 // assert(!doesPointTo(source, source) && !hasElaborateMove!T), 2200 // "Cannot move object with internal pointer unless `opPostMove` is defined."); 2201 // } 2202 2203 import core.internal.traits : hasElaborateAssign, isAssignable, hasElaborateMove, 2204 hasElaborateDestructor, hasElaborateCopyConstructor; 2205 static if (is(T == struct)) 2206 { 2207 2208 // Unsafe when compiling without -preview=dip1000 2209 assert((() @trusted => &source !is &target)(), "source and target must not be identical"); 2210 2211 static if (hasElaborateAssign!T || !isAssignable!T) 2212 { 2213 import core.stdc.string : memcpy; 2214 () @trusted { memcpy(&target, &source, T.sizeof); }(); 2215 } 2216 else 2217 target = source; 2218 2219 static if (hasElaborateMove!T) 2220 __move_post_blt(target, source); 2221 2222 // If the source defines a destructor or a postblit hook, we must obliterate the 2223 // object in order to avoid double freeing and undue aliasing 2224 static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T) 2225 { 2226 // If there are members that are nested structs, we must take care 2227 // not to erase any context pointers, so we might have to recurse 2228 static if (__traits(isZeroInit, T)) 2229 wipe(source); 2230 else 2231 wipe(source, ref () @trusted { return *cast(immutable(T)*) __traits(initSymbol, T).ptr; } ()); 2232 } 2233 } 2234 else static if (__traits(isStaticArray, T)) 2235 { 2236 static if (T.length) 2237 { 2238 static if (!hasElaborateMove!T && 2239 !hasElaborateDestructor!T && 2240 !hasElaborateCopyConstructor!T) 2241 { 2242 // Single blit if no special per-instance handling is required 2243 () @trusted 2244 { 2245 assert(source.ptr !is target.ptr, "source and target must not be identical"); 2246 *cast(ubyte[T.sizeof]*) &target = *cast(ubyte[T.sizeof]*) &source; 2247 } (); 2248 } 2249 else 2250 { 2251 for (size_t i = 0; i < source.length; ++i) 2252 moveEmplaceImpl(target[i], source[i]); 2253 } 2254 } 2255 } 2256 else 2257 { 2258 // Primitive data (including pointers and arrays) or class - 2259 // assignment works great 2260 target = source; 2261 } 2262 } 2263 2264 /** 2265 * Similar to $(LREF move) but assumes `target` is uninitialized. This 2266 * is more efficient because `source` can be blitted over `target` 2267 * without destroying or initializing it first. 2268 * 2269 * Params: 2270 * source = value to be moved into target 2271 * target = uninitialized value to be filled by source 2272 */ 2273 void moveEmplace(T)(ref T source, ref T target) @system 2274 { 2275 moveEmplaceImpl(target, source); 2276 } 2277 2278 /// 2279 @betterC 2280 pure nothrow @nogc @system unittest 2281 { 2282 static struct Foo 2283 { 2284 pure nothrow @nogc: 2285 this(int* ptr) { _ptr = ptr; } 2286 ~this() { if (_ptr) ++*_ptr; } 2287 int* _ptr; 2288 } 2289 2290 int val; 2291 Foo foo1 = void; // uninitialized 2292 auto foo2 = Foo(&val); // initialized 2293 assert(foo2._ptr is &val); 2294 2295 // Using `move(foo2, foo1)` would have an undefined effect because it would destroy 2296 // the uninitialized foo1. 2297 // moveEmplace directly overwrites foo1 without destroying or initializing it first. 2298 moveEmplace(foo2, foo1); 2299 assert(foo1._ptr is &val); 2300 assert(foo2._ptr is null); 2301 assert(val == 0); 2302 } 2303 2304 @betterC 2305 pure nothrow @nogc @system unittest 2306 { 2307 static struct Foo 2308 { 2309 pure nothrow @nogc: 2310 this(int* ptr) { _ptr = ptr; } 2311 ~this() { if (_ptr) ++*_ptr; } 2312 int* _ptr; 2313 } 2314 2315 int val; 2316 { 2317 Foo[1] foo1 = void; // uninitialized 2318 Foo[1] foo2 = [Foo(&val)];// initialized 2319 assert(foo2[0]._ptr is &val); 2320 2321 // Using `move(foo2, foo1)` would have an undefined effect because it would destroy 2322 // the uninitialized foo1. 2323 // moveEmplace directly overwrites foo1 without destroying or initializing it first. 2324 moveEmplace(foo2, foo1); 2325 assert(foo1[0]._ptr is &val); 2326 assert(foo2[0]._ptr is null); 2327 assert(val == 0); 2328 } 2329 assert(val == 1); 2330 } 2331 2332 // https://issues.dlang.org/show_bug.cgi?id=18913 2333 @safe unittest 2334 { 2335 static struct NoCopy 2336 { 2337 int payload; 2338 ~this() { } 2339 @disable this(this); 2340 } 2341 2342 static void f(NoCopy[2]) { } 2343 2344 NoCopy[2] ncarray = [ NoCopy(1), NoCopy(2) ]; 2345 2346 static assert(!__traits(compiles, f(ncarray))); 2347 f(move(ncarray)); 2348 } 2349 2350 //debug = PRINTF; 2351 2352 debug(PRINTF) 2353 { 2354 import core.stdc.stdio; 2355 } 2356 2357 /// Implementation of `_d_delstruct` and `_d_delstructTrace` 2358 template _d_delstructImpl(T) 2359 { 2360 private void _d_delstructImpure(ref T p) 2361 { 2362 debug(PRINTF) printf("_d_delstruct(%p)\n", p); 2363 2364 destroy(*p); 2365 p = null; 2366 } 2367 2368 /** 2369 * This is called for a delete statement where the value being deleted is a 2370 * pointer to a struct with a destructor but doesn't have an overloaded 2371 * `delete` operator. 2372 * 2373 * Params: 2374 * p = pointer to the value to be deleted 2375 * 2376 * Bugs: 2377 * This function template was ported from a much older runtime hook that 2378 * bypassed safety, purity, and throwabilty checks. To prevent breaking 2379 * existing code, this function template is temporarily declared 2380 * `@trusted` until the implementation can be brought up to modern D 2381 * expectations. 2382 */ 2383 void _d_delstruct(ref T p) @trusted @nogc pure nothrow 2384 { 2385 if (p) 2386 { 2387 alias Type = void function(ref T P) @nogc pure nothrow; 2388 (cast(Type) &_d_delstructImpure)(p); 2389 } 2390 } 2391 2392 version (D_ProfileGC) 2393 { 2394 import core.internal.array.utils : _d_HookTraceImpl; 2395 2396 private enum errorMessage = "Cannot delete struct if compiling without support for runtime type information!"; 2397 2398 /** 2399 * TraceGC wrapper around $(REF _d_delstruct, core,lifetime,_d_delstructImpl). 2400 * 2401 * Bugs: 2402 * This function template was ported from a much older runtime hook that 2403 * bypassed safety, purity, and throwabilty checks. To prevent breaking 2404 * existing code, this function template is temporarily declared 2405 * `@trusted` until the implementation can be brought up to modern D 2406 * expectations. 2407 */ 2408 alias _d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage); 2409 } 2410 } 2411 2412 @system pure nothrow unittest 2413 { 2414 int dtors = 0; 2415 struct S { ~this() nothrow { ++dtors; } } 2416 2417 S *s = new S(); 2418 _d_delstructImpl!(typeof(s))._d_delstruct(s); 2419 2420 assert(s == null); 2421 assert(dtors == 1); 2422 } 2423 2424 @system pure unittest 2425 { 2426 int innerDtors = 0; 2427 int outerDtors = 0; 2428 2429 struct Inner { ~this() { ++innerDtors; } } 2430 struct Outer 2431 { 2432 Inner *i1; 2433 Inner *i2; 2434 2435 this(int x) 2436 { 2437 i1 = new Inner(); 2438 i2 = new Inner(); 2439 } 2440 2441 ~this() 2442 { 2443 ++outerDtors; 2444 2445 _d_delstructImpl!(typeof(i1))._d_delstruct(i1); 2446 assert(i1 == null); 2447 2448 _d_delstructImpl!(typeof(i2))._d_delstruct(i2); 2449 assert(i2 == null); 2450 } 2451 } 2452 2453 Outer *o = new Outer(0); 2454 _d_delstructImpl!(typeof(o))._d_delstruct(o); 2455 2456 assert(o == null); 2457 assert(innerDtors == 2); 2458 assert(outerDtors == 1); 2459 } 2460 2461 // https://issues.dlang.org/show_bug.cgi?id=25552 2462 pure nothrow @system unittest 2463 { 2464 int i; 2465 struct Nested 2466 { 2467 pure nothrow @nogc: 2468 char[1] arr; // char.init is not 0 2469 ~this() { ++i; } 2470 } 2471 2472 { 2473 Nested[1] dst = void; 2474 Nested[1] src = [Nested(['a'])]; 2475 2476 moveEmplace(src, dst); 2477 assert(i == 0); 2478 assert(dst[0].arr == ['a']); 2479 assert(src[0].arr == [char.init]); 2480 assert(dst[0].tupleof[$-1] is src[0].tupleof[$-1]); 2481 } 2482 assert(i == 2); 2483 } 2484 2485 // https://issues.dlang.org/show_bug.cgi?id=25552 2486 @safe unittest 2487 { 2488 int i; 2489 struct Nested 2490 { 2491 ~this() { ++i; } 2492 } 2493 2494 static struct NotNested 2495 { 2496 Nested n; 2497 } 2498 2499 static struct Deep 2500 { 2501 NotNested nn; 2502 } 2503 2504 static struct Deeper 2505 { 2506 NotNested[1] nn; 2507 } 2508 2509 static assert(__traits(isZeroInit, Nested)); 2510 static assert(__traits(isZeroInit, NotNested)); 2511 static assert(__traits(isZeroInit, Deep)); 2512 static assert(__traits(isZeroInit, Deeper)); 2513 2514 { 2515 auto a = NotNested(Nested()); 2516 assert(a.n.tupleof[$-1]); 2517 auto b = move(a); 2518 assert(b.n.tupleof[$-1]); 2519 assert(a.n.tupleof[$-1] is b.n.tupleof[$-1]); 2520 2521 auto c = Deep(NotNested(Nested())); 2522 auto d = move(c); 2523 assert(d.nn.n.tupleof[$-1]); 2524 assert(c.nn.n.tupleof[$-1] is d.nn.n.tupleof[$-1]); 2525 2526 auto e = Deeper([NotNested(Nested())]); 2527 auto f = move(e); 2528 assert(f.nn[0].n.tupleof[$-1]); 2529 assert(e.nn[0].n.tupleof[$-1] is f.nn[0].n.tupleof[$-1]); 2530 } 2531 assert(i == 6); 2532 } 2533 2534 // https://issues.dlang.org/show_bug.cgi?id=25552 2535 @safe unittest 2536 { 2537 int i; 2538 struct Nested 2539 { 2540 align(32) // better still find context pointer correctly! 2541 int[3] stuff = [0, 1, 2]; 2542 ~this() { ++i; } 2543 } 2544 2545 static struct NoAssign 2546 { 2547 int value; 2548 @disable void opAssign(typeof(this)); 2549 } 2550 2551 static struct NotNested 2552 { 2553 int before = 42; 2554 align(Nested.alignof * 4) // better still find context pointer correctly! 2555 Nested n; 2556 auto after = NoAssign(43); 2557 } 2558 2559 static struct Deep 2560 { 2561 NotNested nn; 2562 } 2563 2564 static struct Deeper 2565 { 2566 NotNested[1] nn; 2567 } 2568 2569 static assert(!__traits(isZeroInit, Nested)); 2570 static assert(!__traits(isZeroInit, NotNested)); 2571 static assert(!__traits(isZeroInit, Deep)); 2572 static assert(!__traits(isZeroInit, Deeper)); 2573 2574 { 2575 auto a = NotNested(1, Nested([3, 4, 5]), NoAssign(2)); 2576 auto b = move(a); 2577 assert(b.n.tupleof[$-1]); 2578 assert(a.n.tupleof[$-1] is b.n.tupleof[$-1]); 2579 assert(a.n.stuff == [0, 1, 2]); 2580 assert(a.before == 42); 2581 assert(a.after == NoAssign(43)); 2582 2583 auto c = Deep(NotNested(1, Nested([3, 4, 5]), NoAssign(2))); 2584 auto d = move(c); 2585 assert(d.nn.n.tupleof[$-1]); 2586 assert(c.nn.n.tupleof[$-1] is d.nn.n.tupleof[$-1]); 2587 assert(c.nn.n.stuff == [0, 1, 2]); 2588 assert(c.nn.before == 42); 2589 assert(c.nn.after == NoAssign(43)); 2590 2591 auto e = Deeper([NotNested(1, Nested([3, 4, 5]), NoAssign(2))]); 2592 auto f = move(e); 2593 assert(f.nn[0].n.tupleof[$-1]); 2594 assert(e.nn[0].n.tupleof[$-1] is f.nn[0].n.tupleof[$-1]); 2595 assert(e.nn[0].n.stuff == [0, 1, 2]); 2596 assert(e.nn[0].before == 42); 2597 assert(e.nn[0].after == NoAssign(43)); 2598 } 2599 assert(i == 6); 2600 } 2601 2602 // wipes source after moving 2603 pragma(inline, true) 2604 private void wipe(T, Init...)(return scope ref T source, ref const scope Init initializer) @trusted 2605 if (!Init.length || 2606 ((Init.length == 1) && (is(immutable T == immutable Init[0])))) 2607 { 2608 static if (__traits(isStaticArray, T) && hasContextPointers!T) 2609 { 2610 for (auto i = 0; i < T.length; i++) 2611 static if (Init.length) 2612 wipe(source[i], initializer[0][i]); 2613 else 2614 wipe(source[i]); 2615 } 2616 else static if (is(T == struct) && hasContextPointers!T) 2617 { 2618 import core.internal.traits : anySatisfy; 2619 static if (anySatisfy!(hasContextPointers, typeof(T.tupleof))) 2620 { 2621 static foreach (i; 0 .. T.tupleof.length - __traits(isNested, T)) 2622 static if (Init.length) 2623 wipe(source.tupleof[i], initializer[0].tupleof[i]); 2624 else 2625 wipe(source.tupleof[i]); 2626 } 2627 else 2628 { 2629 static if (__traits(isNested, T)) 2630 enum sz = T.tupleof[$-1].offsetof; 2631 else 2632 enum sz = T.sizeof; 2633 2634 static if (Init.length) 2635 *cast(ubyte[sz]*) &source = *cast(ubyte[sz]*) &initializer[0]; 2636 else 2637 *cast(ubyte[sz]*) &source = 0; 2638 } 2639 } 2640 else 2641 { 2642 import core.internal.traits : hasElaborateAssign, isAssignable; 2643 static if (Init.length) 2644 { 2645 static if (hasElaborateAssign!T || !isAssignable!T) 2646 *cast(ubyte[T.sizeof]*) &source = *cast(ubyte[T.sizeof]*) &initializer[0]; 2647 else 2648 source = *cast(T*) &initializer[0]; 2649 } 2650 else 2651 { 2652 *cast(ubyte[T.sizeof]*) &source = 0; 2653 } 2654 } 2655 } 2656 2657 /** 2658 * Allocate an exception of type `T` from the exception pool. 2659 * `T` must be `Throwable` or derived from it and cannot be a COM or C++ class. 2660 * 2661 * Note: 2662 * This function does not call the constructor of `T` because that would require 2663 * `forward!args`, which causes errors with -dip1008. This inconvenience will be 2664 * removed once -dip1008 works as intended. 2665 * 2666 * Returns: 2667 * allocated instance of type `T` 2668 */ 2669 T _d_newThrowable(T)() @trusted 2670 if (is(T : Throwable) && __traits(getLinkage, T) == "D") 2671 { 2672 debug(PRINTF) printf("_d_newThrowable(%s)\n", cast(char*) T.stringof); 2673 2674 auto init = __traits(initSymbol, T); 2675 void* p = _d_allocmemory(init.length); 2676 if (!p) 2677 { 2678 import core.exception : onOutOfMemoryError; 2679 onOutOfMemoryError(); 2680 } 2681 2682 debug(PRINTF) printf(" p = %p\n", p); 2683 2684 // initialize it 2685 p[0 .. init.length] = init[]; 2686 2687 2688 debug(PRINTF) printf("initialization done\n"); 2689 2690 (cast(Throwable) p).refcount() = 1; 2691 2692 return cast(T) p; 2693 } 2694 2695 @system unittest 2696 { 2697 class E : Exception 2698 { 2699 this(string msg = "", Throwable nextInChain = null) 2700 { 2701 super(msg, nextInChain); 2702 } 2703 } 2704 2705 Throwable exc = _d_newThrowable!Exception(); 2706 Throwable e = _d_newThrowable!E(); 2707 2708 assert(exc.refcount() == 1); 2709 assert(e.refcount() == 1); 2710 } 2711 2712 /** 2713 * Create a new class instance. 2714 * Allocates memory and sets fields to their initial value, but does not call a 2715 * constructor. 2716 * --- 2717 * new C() // _d_newclass!(C)() 2718 * --- 2719 * Returns: newly created object 2720 */ 2721 T _d_newclassT(T)() @trusted 2722 if (is(T == class)) 2723 { 2724 import core.internal.traits : hasIndirections; 2725 import core.exception : onOutOfMemoryError; 2726 2727 alias BlkAttr = GC.BlkAttr; 2728 2729 auto init = __traits(initSymbol, T); 2730 void* p = _d_allocmemory(init.length); 2731 2732 debug(PRINTF) 2733 { 2734 printf("p = %p\n", p); 2735 printf("init.ptr = %p, len = %llu\n", init.ptr, cast(ulong)init.length); 2736 printf("vptr = %p\n", *cast(void**) init); 2737 printf("vtbl[0] = %p\n", (*cast(void***) init)[0]); 2738 printf("vtbl[1] = %p\n", (*cast(void***) init)[1]); 2739 printf("init[0] = %x\n", (cast(uint*) init)[0]); 2740 printf("init[1] = %x\n", (cast(uint*) init)[1]); 2741 printf("init[2] = %x\n", (cast(uint*) init)[2]); 2742 printf("init[3] = %x\n", (cast(uint*) init)[3]); 2743 printf("init[4] = %x\n", (cast(uint*) init)[4]); 2744 } 2745 2746 // initialize it 2747 p[0 .. init.length] = init[]; 2748 2749 debug(PRINTF) printf("initialization done\n"); 2750 return cast(T) p; 2751 } 2752 2753 /** 2754 * TraceGC wrapper around $(REF _d_newclassT, core,lifetime). 2755 */ 2756 T _d_newclassTTrace(T)(string file, int line, string funcname) @trusted 2757 { 2758 version (D_TypeInfo) 2759 { 2760 import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure; 2761 mixin(TraceHook!(T.stringof, "_d_newclassT")); 2762 2763 return _d_newclassT!T(); 2764 } 2765 else 2766 assert(0, "Cannot create new class if compiling without support for runtime type information!"); 2767 } 2768 2769 /** 2770 * Allocate an initialized non-array item. 2771 * 2772 * This is an optimization to avoid things needed for arrays like the __arrayPad(size). 2773 * Used to allocate struct instances on the heap. 2774 * 2775 * --- 2776 * struct Sz {int x = 0;} 2777 * struct Si {int x = 3;} 2778 * 2779 * void main() 2780 * { 2781 * new Sz(); // uses zero-initialization 2782 * new Si(); // uses Si.init 2783 * } 2784 * --- 2785 * 2786 * Returns: 2787 * newly allocated item 2788 */ 2789 T* _d_newitemT(T)() @trusted 2790 { 2791 import core.internal.lifetime : emplaceInitializer; 2792 import core.internal.traits : hasIndirections; 2793 2794 immutable tiSize = TypeInfoSize!T; 2795 immutable itemSize = T.sizeof; 2796 immutable totalSize = itemSize + tiSize; 2797 2798 auto p = _d_allocmemory(totalSize); 2799 2800 emplaceInitializer(*(cast(T*) p)); 2801 2802 return cast(T*) p; 2803 } 2804 2805 // Test allocation 2806 @safe unittest 2807 { 2808 class C { } 2809 C c = _d_newclassT!C(); 2810 2811 assert(c !is null); 2812 } 2813 2814 // Test initializers 2815 @safe unittest 2816 { 2817 { 2818 class C { int x, y; } 2819 C c = _d_newclassT!C(); 2820 2821 assert(c.x == 0); 2822 assert(c.y == 0); 2823 } 2824 { 2825 class C { int x = 2, y = 3; } 2826 C c = _d_newclassT!C(); 2827 2828 assert(c.x == 2); 2829 assert(c.y == 3); 2830 } 2831 } 2832 2833 // Test allocation 2834 @safe unittest 2835 { 2836 struct S { } 2837 S* s = _d_newitemT!S(); 2838 2839 assert(s !is null); 2840 } 2841 2842 // Test initializers 2843 @safe unittest 2844 { 2845 { 2846 // zero-initialization 2847 struct S { int x, y; } 2848 S* s = _d_newitemT!S(); 2849 2850 assert(s.x == 0); 2851 assert(s.y == 0); 2852 } 2853 { 2854 // S.init 2855 struct S { int x = 2, y = 3; } 2856 S* s = _d_newitemT!S(); 2857 2858 assert(s.x == 2); 2859 assert(s.y == 3); 2860 } 2861 } 2862 2863 // Test GC attributes 2864 version (CoreUnittest) 2865 { 2866 struct S1 2867 { 2868 int x = 5; 2869 } 2870 struct S2 2871 { 2872 int x; 2873 this(int x) { this.x = x; } 2874 } 2875 struct S3 2876 { 2877 int[4] x; 2878 this(int x) { this.x[] = x; } 2879 } 2880 struct S4 2881 { 2882 int *x; 2883 } 2884 2885 } 2886 @system unittest 2887 { 2888 import core.memory : GC; 2889 2890 auto s1 = new S1; 2891 assert(s1.x == 5); 2892 assert(GC.getAttr(s1) == GC.BlkAttr.NO_SCAN); 2893 2894 auto s2 = new S2(3); 2895 assert(s2.x == 3); 2896 assert(GC.getAttr(s2) == GC.BlkAttr.NO_SCAN); 2897 2898 auto s3 = new S3(1); 2899 assert(s3.x == [1, 1, 1, 1]); 2900 assert(GC.getAttr(s3) == GC.BlkAttr.NO_SCAN); 2901 debug(SENTINEL) {} else 2902 assert(GC.sizeOf(s3) == 16); 2903 2904 auto s4 = new S4; 2905 assert(s4.x == null); 2906 assert(GC.getAttr(s4) == 0); 2907 } 2908 2909 // Test struct finalizers exception handling 2910 debug(SENTINEL) {} else 2911 @system unittest 2912 { 2913 import core.memory : GC; 2914 2915 bool test(E)() 2916 { 2917 import core.exception; 2918 static struct S1 2919 { 2920 E exc; 2921 ~this() { throw exc; } 2922 } 2923 2924 bool caught = false; 2925 S1* s = new S1(new E("test onFinalizeError")); 2926 try 2927 { 2928 GC.runFinalizers((cast(char*)(typeid(S1).xdtor))[0 .. 1]); 2929 } 2930 catch (FinalizeError err) 2931 { 2932 caught = true; 2933 } 2934 catch (E) 2935 { 2936 } 2937 GC.free(s); 2938 return caught; 2939 } 2940 2941 assert(test!Exception); 2942 import core.exception : InvalidMemoryOperationError; 2943 assert(!test!InvalidMemoryOperationError); 2944 } 2945 2946 version (D_ProfileGC) 2947 { 2948 /** 2949 * TraceGC wrapper around $(REF _d_newitemT, core,lifetime). 2950 */ 2951 T* _d_newitemTTrace(T)(string file, int line, string funcname) @trusted 2952 { 2953 version (D_TypeInfo) 2954 { 2955 import core.internal.array.utils : TraceHook, gcStatsPure, accumulatePure; 2956 mixin(TraceHook!(T.stringof, "_d_newitemT")); 2957 2958 return _d_newitemT!T(); 2959 } 2960 else 2961 assert(0, "Cannot create new `struct` if compiling without support for runtime type information!"); 2962 } 2963 } 2964 2965 template TypeInfoSize(T) 2966 { 2967 import core.internal.traits : hasElaborateDestructor; 2968 enum TypeInfoSize = hasElaborateDestructor!T ? size_t.sizeof : 0; 2969 }