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