]> git.ipfire.org Git - thirdparty/gcc.git/blob - libphobos/libdruntime/core/lifetime.d
d: Merge upstream dmd 3982604c5, druntime bc58b1e9, phobos 12329adb6.
[thirdparty/gcc.git] / libphobos / libdruntime / core / lifetime.d
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 import core.internal.traits : maxAlignment;
204
205 enum classSize = __traits(classInstanceSize, T);
206 assert(chunk.length >= classSize, "chunk size too small.");
207
208 enum alignment = maxAlignment!(void*, typeof(T.tupleof));
209 assert((cast(size_t) chunk.ptr) % alignment == 0, "chunk is not aligned.");
210
211 return emplace!T(cast(T)(chunk.ptr), forward!args);
212 }
213
214 ///
215 @system unittest
216 {
217 static class C
218 {
219 int i;
220 this(int i){this.i = i;}
221 }
222 auto buf = new void[__traits(classInstanceSize, C)];
223 auto c = emplace!C(buf, 5);
224 assert(c.i == 5);
225 }
226
227 ///
228 @betterC
229 @nogc pure nothrow @system unittest
230 {
231 // works with -betterC too:
232
233 static extern (C++) class C
234 {
235 @nogc pure nothrow @safe:
236 int i = 3;
237 this(int i)
238 {
239 assert(this.i == 3);
240 this.i = i;
241 }
242 int virtualGetI() { return i; }
243 }
244
245 import core.internal.traits : classInstanceAlignment;
246
247 align(classInstanceAlignment!C) byte[__traits(classInstanceSize, C)] buffer;
248 C c = emplace!C(buffer[], 42);
249 assert(c.virtualGetI() == 42);
250 }
251
252 @system unittest
253 {
254 class Outer
255 {
256 int i = 3;
257 class Inner
258 {
259 auto getI() { return i; }
260 }
261 }
262 auto outerBuf = new void[__traits(classInstanceSize, Outer)];
263 auto innerBuf = new void[__traits(classInstanceSize, Outer.Inner)];
264 auto inner = innerBuf.emplace!(Outer.Inner)(outerBuf.emplace!Outer);
265 assert(inner.getI == 3);
266 }
267
268 @nogc pure nothrow @safe unittest
269 {
270 static class __conv_EmplaceTestClass
271 {
272 @nogc @safe pure nothrow:
273 int i = 3;
274 this(int i)
275 {
276 assert(this.i == 3);
277 this.i = 10 + i;
278 }
279 this(ref int i)
280 {
281 assert(this.i == 3);
282 this.i = 20 + i;
283 }
284 this(int i, ref int j)
285 {
286 assert(this.i == 3 && i == 5 && j == 6);
287 this.i = i;
288 ++j;
289 }
290 }
291
292 int var = 6;
293 align(__conv_EmplaceTestClass.alignof) 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 // bugzilla 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(A.alignof) 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 emplace(cast(Unqual!(T)*) &target); // blit T.init
1277 static if (__traits(isNested, T))
1278 {
1279 // copy context pointer
1280 *(cast(void**) &target.tupleof[$-1]) = cast(void*) source.tupleof[$-1];
1281 }
1282 target.__ctor(source); // invoke copy ctor
1283 }
1284 else
1285 {
1286 blit(); // no opAssign
1287 }
1288 }
1289 else static if (is(T == E[n], E, size_t n))
1290 {
1291 static if (hasElaborateCopyConstructor!E)
1292 {
1293 size_t i;
1294 try
1295 {
1296 for (i = 0; i < n; i++)
1297 copyEmplace(source[i], target[i]);
1298 }
1299 catch (Exception e)
1300 {
1301 // destroy, in reverse order, what we've constructed so far
1302 while (i--)
1303 destroy(*cast(Unconst!(E)*) &target[i]);
1304 throw e;
1305 }
1306 }
1307 else // trivial copy
1308 {
1309 blit(); // all elements at once
1310 }
1311 }
1312 else
1313 {
1314 *cast(Unconst!(T)*) &target = *cast(Unconst!(T)*) &source;
1315 }
1316 }
1317
1318 ///
1319 @betterC
1320 @system pure nothrow @nogc unittest
1321 {
1322 int source = 123;
1323 int target = void;
1324 copyEmplace(source, target);
1325 assert(target == 123);
1326 }
1327
1328 ///
1329 @betterC
1330 @system pure nothrow @nogc unittest
1331 {
1332 immutable int[1][1] source = [ [123] ];
1333 immutable int[1][1] target = void;
1334 copyEmplace(source, target);
1335 assert(target[0][0] == 123);
1336 }
1337
1338 ///
1339 @betterC
1340 @system pure nothrow @nogc unittest
1341 {
1342 struct S
1343 {
1344 int x;
1345 void opAssign(const scope ref S rhs) @safe pure nothrow @nogc
1346 {
1347 assert(0);
1348 }
1349 }
1350
1351 S source = S(42);
1352 S target = void;
1353 copyEmplace(source, target);
1354 assert(target.x == 42);
1355 }
1356
1357 // preserve shared-ness
1358 @system pure nothrow unittest
1359 {
1360 auto s = new Object();
1361 auto ss = new shared Object();
1362
1363 Object t;
1364 shared Object st;
1365
1366 copyEmplace(s, t);
1367 assert(t is s);
1368
1369 copyEmplace(ss, st);
1370 assert(st is ss);
1371
1372 static assert(!__traits(compiles, copyEmplace(s, st)));
1373 static assert(!__traits(compiles, copyEmplace(ss, t)));
1374 }
1375
1376 version (DigitalMars) version (X86) version (Posix) version = DMD_X86_Posix;
1377
1378 // don't violate immutability for reference types
1379 @system pure nothrow unittest
1380 {
1381 auto s = new Object();
1382 auto si = new immutable Object();
1383
1384 Object t;
1385 immutable Object ti;
1386
1387 copyEmplace(s, t);
1388 assert(t is s);
1389
1390 copyEmplace(si, ti);
1391 version (DMD_X86_Posix) { /* wrongly fails without -O */ } else
1392 assert(ti is si);
1393
1394 static assert(!__traits(compiles, copyEmplace(s, ti)));
1395 static assert(!__traits(compiles, copyEmplace(si, t)));
1396 }
1397
1398 version (CoreUnittest)
1399 {
1400 private void testCopyEmplace(S, T)(const scope T* expected = null)
1401 {
1402 S source;
1403 T target = void;
1404 copyEmplace(source, target);
1405 if (expected)
1406 assert(target == *expected);
1407 else
1408 {
1409 T expectedCopy = source;
1410 assert(target == expectedCopy);
1411 }
1412 }
1413 }
1414
1415 // postblit
1416 @system pure nothrow @nogc unittest
1417 {
1418 static struct S
1419 {
1420 @safe pure nothrow @nogc:
1421 int x = 42;
1422 this(this) { x += 10; }
1423 }
1424
1425 testCopyEmplace!(S, S)();
1426 testCopyEmplace!(immutable S, S)();
1427 testCopyEmplace!(S, immutable S)();
1428 testCopyEmplace!(immutable S, immutable S)();
1429
1430 testCopyEmplace!(S[1], S[1])();
1431 testCopyEmplace!(immutable S[1], S[1])();
1432
1433 // copying to an immutable static array works, but `T expected = source`
1434 // wrongly ignores the postblit: https://issues.dlang.org/show_bug.cgi?id=8950
1435 immutable S[1] expectedImmutable = [S(52)];
1436 testCopyEmplace!(S[1], immutable S[1])(&expectedImmutable);
1437 testCopyEmplace!(immutable S[1], immutable S[1])(&expectedImmutable);
1438 }
1439
1440 // copy constructors
1441 @system pure nothrow @nogc unittest
1442 {
1443 static struct S
1444 {
1445 @safe pure nothrow @nogc:
1446 int x = 42;
1447 this(int x) { this.x = x; }
1448 this(const scope ref S rhs) { x = rhs.x + 10; }
1449 this(const scope ref S rhs) immutable { x = rhs.x + 20; }
1450 }
1451
1452 testCopyEmplace!(S, S)();
1453 testCopyEmplace!(immutable S, S)();
1454 testCopyEmplace!(S, immutable S)();
1455 testCopyEmplace!(immutable S, immutable S)();
1456
1457 // static arrays work, but `T expected = source` wrongly ignores copy ctors
1458 // https://issues.dlang.org/show_bug.cgi?id=20365
1459 S[1] expectedMutable = [S(52)];
1460 immutable S[1] expectedImmutable = [immutable S(62)];
1461 testCopyEmplace!(S[1], S[1])(&expectedMutable);
1462 testCopyEmplace!(immutable S[1], S[1])(&expectedMutable);
1463 testCopyEmplace!(S[1], immutable S[1])(&expectedImmutable);
1464 testCopyEmplace!(immutable S[1], immutable S[1])(&expectedImmutable);
1465 }
1466
1467 // copy constructor in nested struct
1468 @system pure nothrow unittest
1469 {
1470 int copies;
1471 struct S
1472 {
1473 @safe pure nothrow @nogc:
1474 size_t x = 42;
1475 this(size_t x) { this.x = x; }
1476 this(const scope ref S rhs)
1477 {
1478 assert(x == 42); // T.init
1479 x = rhs.x;
1480 ++copies;
1481 }
1482 }
1483
1484 {
1485 copies = 0;
1486 S source = S(123);
1487 immutable S target = void;
1488 copyEmplace(source, target);
1489 assert(target is source);
1490 assert(copies == 1);
1491 }
1492
1493 {
1494 copies = 0;
1495 immutable S[1] source = [immutable S(456)];
1496 S[1] target = void;
1497 copyEmplace(source, target);
1498 assert(target[0] is source[0]);
1499 assert(copies == 1);
1500 }
1501 }
1502
1503 // destruction of partially copied static array
1504 @system unittest
1505 {
1506 static struct S
1507 {
1508 __gshared int[] deletions;
1509 int x;
1510 this(this) { if (x == 5) throw new Exception(""); }
1511 ~this() { deletions ~= x; }
1512 }
1513
1514 alias T = immutable S[3][2];
1515 T source = [ [S(1), S(2), S(3)], [S(4), S(5), S(6)] ];
1516 T target = void;
1517 try
1518 {
1519 copyEmplace(source, target);
1520 assert(0);
1521 }
1522 catch (Exception)
1523 {
1524 static immutable expectedDeletions = [ 4, 3, 2, 1 ];
1525 version (DigitalMars)
1526 {
1527 assert(S.deletions == expectedDeletions ||
1528 S.deletions == [ 4 ]); // FIXME: happens with -O
1529 }
1530 else
1531 assert(S.deletions == expectedDeletions);
1532 }
1533 }
1534
1535 /**
1536 Forwards function arguments while keeping `out`, `ref`, and `lazy` on
1537 the parameters.
1538
1539 Params:
1540 args = a parameter list or an $(REF AliasSeq,std,meta).
1541 Returns:
1542 An `AliasSeq` of `args` with `out`, `ref`, and `lazy` saved.
1543 */
1544 template forward(args...)
1545 {
1546 import core.internal.traits : AliasSeq;
1547
1548 static if (args.length)
1549 {
1550 alias arg = args[0];
1551 // by ref || lazy || const/immutable
1552 static if (__traits(isRef, arg) ||
1553 __traits(isOut, arg) ||
1554 __traits(isLazy, arg) ||
1555 !is(typeof(move(arg))))
1556 alias fwd = arg;
1557 // (r)value
1558 else
1559 @property auto fwd(){ return move(arg); }
1560
1561 static if (args.length == 1)
1562 alias forward = fwd;
1563 else
1564 alias forward = AliasSeq!(fwd, forward!(args[1..$]));
1565 }
1566 else
1567 alias forward = AliasSeq!();
1568 }
1569
1570 ///
1571 @safe unittest
1572 {
1573 class C
1574 {
1575 static int foo(int n) { return 1; }
1576 static int foo(ref int n) { return 2; }
1577 }
1578
1579 // with forward
1580 int bar()(auto ref int x) { return C.foo(forward!x); }
1581
1582 // without forward
1583 int baz()(auto ref int x) { return C.foo(x); }
1584
1585 int i;
1586 assert(bar(1) == 1);
1587 assert(bar(i) == 2);
1588
1589 assert(baz(1) == 2);
1590 assert(baz(i) == 2);
1591 }
1592
1593 ///
1594 @safe unittest
1595 {
1596 void foo(int n, ref string s) { s = null; foreach (i; 0 .. n) s ~= "Hello"; }
1597
1598 // forwards all arguments which are bound to parameter tuple
1599 void bar(Args...)(auto ref Args args) { return foo(forward!args); }
1600
1601 // forwards all arguments with swapping order
1602 void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); }
1603
1604 string s;
1605 bar(1, s);
1606 assert(s == "Hello");
1607 baz(s, 2);
1608 assert(s == "HelloHello");
1609 }
1610
1611 @safe unittest
1612 {
1613 auto foo(TL...)(auto ref TL args)
1614 {
1615 string result = "";
1616 foreach (i, _; args)
1617 {
1618 //pragma(msg, "[",i,"] ", __traits(isRef, args[i]) ? "L" : "R");
1619 result ~= __traits(isRef, args[i]) ? "L" : "R";
1620 }
1621 return result;
1622 }
1623
1624 string bar(TL...)(auto ref TL args)
1625 {
1626 return foo(forward!args);
1627 }
1628 string baz(TL...)(auto ref TL args)
1629 {
1630 int x;
1631 return foo(forward!args[3], forward!args[2], 1, forward!args[1], forward!args[0], x);
1632 }
1633
1634 struct S {}
1635 S makeS(){ return S(); }
1636 int n;
1637 string s;
1638 assert(bar(S(), makeS(), n, s) == "RRLL");
1639 assert(baz(S(), makeS(), n, s) == "LLRRRL");
1640 }
1641
1642 @betterC
1643 @safe unittest
1644 {
1645 ref int foo(return ref int a) { return a; }
1646 ref int bar(Args)(auto ref Args args)
1647 {
1648 return foo(forward!args);
1649 }
1650 static assert(!__traits(compiles, { auto x1 = bar(3); })); // case of NG
1651 int value = 3;
1652 auto x2 = bar(value); // case of OK
1653 }
1654
1655 ///
1656 @betterC
1657 @safe unittest
1658 {
1659 struct X {
1660 int i;
1661 this(this)
1662 {
1663 ++i;
1664 }
1665 }
1666
1667 struct Y
1668 {
1669 private X x_;
1670 this()(auto ref X x)
1671 {
1672 x_ = forward!x;
1673 }
1674 }
1675
1676 struct Z
1677 {
1678 private const X x_;
1679 this()(auto ref X x)
1680 {
1681 x_ = forward!x;
1682 }
1683 this()(auto const ref X x)
1684 {
1685 x_ = forward!x;
1686 }
1687 }
1688
1689 X x;
1690 const X cx;
1691 auto constX = (){ const X x; return x; };
1692 static assert(__traits(compiles, { Y y = x; }));
1693 static assert(__traits(compiles, { Y y = X(); }));
1694 static assert(!__traits(compiles, { Y y = cx; }));
1695 static assert(!__traits(compiles, { Y y = constX(); }));
1696 static assert(__traits(compiles, { Z z = x; }));
1697 static assert(__traits(compiles, { Z z = X(); }));
1698 static assert(__traits(compiles, { Z z = cx; }));
1699 static assert(__traits(compiles, { Z z = constX(); }));
1700
1701
1702 Y y1 = x;
1703 // ref lvalue, copy
1704 assert(y1.x_.i == 1);
1705 Y y2 = X();
1706 // rvalue, move
1707 assert(y2.x_.i == 0);
1708
1709 Z z1 = x;
1710 // ref lvalue, copy
1711 assert(z1.x_.i == 1);
1712 Z z2 = X();
1713 // rvalue, move
1714 assert(z2.x_.i == 0);
1715 Z z3 = cx;
1716 // ref const lvalue, copy
1717 assert(z3.x_.i == 1);
1718 Z z4 = constX();
1719 // const rvalue, copy
1720 assert(z4.x_.i == 1);
1721 }
1722
1723 // lazy -> lazy
1724 @betterC
1725 @safe unittest
1726 {
1727 int foo1(lazy int i) { return i; }
1728 int foo2(A)(auto ref A i) { return foo1(forward!i); }
1729 int foo3(lazy int i) { return foo2(i); }
1730
1731 int numCalls = 0;
1732 assert(foo3({ ++numCalls; return 42; }()) == 42);
1733 assert(numCalls == 1);
1734 }
1735
1736 // lazy -> non-lazy
1737 @betterC
1738 @safe unittest
1739 {
1740 int foo1(int a, int b) { return a + b; }
1741 int foo2(A...)(auto ref A args) { return foo1(forward!args); }
1742 int foo3(int a, lazy int b) { return foo2(a, b); }
1743
1744 int numCalls;
1745 assert(foo3(11, { ++numCalls; return 31; }()) == 42);
1746 assert(numCalls == 1);
1747 }
1748
1749 // non-lazy -> lazy
1750 @betterC
1751 @safe unittest
1752 {
1753 int foo1(int a, lazy int b) { return a + b; }
1754 int foo2(A...)(auto ref A args) { return foo1(forward!args); }
1755 int foo3(int a, int b) { return foo2(a, b); }
1756
1757 assert(foo3(11, 31) == 42);
1758 }
1759
1760 // out
1761 @betterC
1762 @safe unittest
1763 {
1764 void foo1(int a, out int b) { b = a; }
1765 void foo2(A...)(auto ref A args) { foo1(forward!args); }
1766 void foo3(int a, out int b) { foo2(a, b); }
1767
1768 int b;
1769 foo3(42, b);
1770 assert(b == 42);
1771 }
1772
1773 // move
1774 /**
1775 Moves `source` into `target`, via a destructive copy when necessary.
1776
1777 If `T` is a struct with a destructor or postblit defined, source is reset
1778 to its `.init` value after it is moved into target, otherwise it is
1779 left unchanged.
1780
1781 Preconditions:
1782 If source has internal pointers that point to itself and doesn't define
1783 opPostMove, it cannot be moved, and will trigger an assertion failure.
1784
1785 Params:
1786 source = Data to copy.
1787 target = Where to copy into. The destructor, if any, is invoked before the
1788 copy is performed.
1789 */
1790 void move(T)(ref T source, ref T target)
1791 {
1792 moveImpl(target, source);
1793 }
1794
1795 /// For non-struct types, `move` just performs `target = source`:
1796 @safe unittest
1797 {
1798 Object obj1 = new Object;
1799 Object obj2 = obj1;
1800 Object obj3;
1801
1802 move(obj2, obj3);
1803 assert(obj3 is obj1);
1804 // obj2 unchanged
1805 assert(obj2 is obj1);
1806 }
1807
1808 ///
1809 pure nothrow @safe @nogc unittest
1810 {
1811 // Structs without destructors are simply copied
1812 struct S1
1813 {
1814 int a = 1;
1815 int b = 2;
1816 }
1817 S1 s11 = { 10, 11 };
1818 S1 s12;
1819
1820 move(s11, s12);
1821
1822 assert(s12 == S1(10, 11));
1823 assert(s11 == s12);
1824
1825 // But structs with destructors or postblits are reset to their .init value
1826 // after copying to the target.
1827 struct S2
1828 {
1829 int a = 1;
1830 int b = 2;
1831
1832 ~this() pure nothrow @safe @nogc { }
1833 }
1834 S2 s21 = { 3, 4 };
1835 S2 s22;
1836
1837 move(s21, s22);
1838
1839 assert(s21 == S2(1, 2));
1840 assert(s22 == S2(3, 4));
1841 }
1842
1843 @safe unittest
1844 {
1845 import core.internal.traits;
1846
1847 assertCTFEable!((){
1848 Object obj1 = new Object;
1849 Object obj2 = obj1;
1850 Object obj3;
1851 move(obj2, obj3);
1852 assert(obj3 is obj1);
1853
1854 static struct S1 { int a = 1, b = 2; }
1855 S1 s11 = { 10, 11 };
1856 S1 s12;
1857 move(s11, s12);
1858 assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1859
1860 static struct S2 { int a = 1; int * b; }
1861 S2 s21 = { 10, null };
1862 s21.b = new int;
1863 S2 s22;
1864 move(s21, s22);
1865 assert(s21 == s22);
1866 });
1867 // Issue 5661 test(1)
1868 static struct S3
1869 {
1870 static struct X { int n = 0; ~this(){n = 0;} }
1871 X x;
1872 }
1873 static assert(hasElaborateDestructor!S3);
1874 S3 s31, s32;
1875 s31.x.n = 1;
1876 move(s31, s32);
1877 assert(s31.x.n == 0);
1878 assert(s32.x.n == 1);
1879
1880 // Issue 5661 test(2)
1881 static struct S4
1882 {
1883 static struct X { int n = 0; this(this){n = 0;} }
1884 X x;
1885 }
1886 static assert(hasElaborateCopyConstructor!S4);
1887 S4 s41, s42;
1888 s41.x.n = 1;
1889 move(s41, s42);
1890 assert(s41.x.n == 0);
1891 assert(s42.x.n == 1);
1892
1893 // Issue 13990 test
1894 class S5;
1895
1896 S5 s51;
1897 S5 s52 = s51;
1898 S5 s53;
1899 move(s52, s53);
1900 assert(s53 is s51);
1901 }
1902
1903 /// Ditto
1904 T move(T)(return scope ref T source)
1905 {
1906 return moveImpl(source);
1907 }
1908
1909 /// Non-copyable structs can still be moved:
1910 pure nothrow @safe @nogc unittest
1911 {
1912 struct S
1913 {
1914 int a = 1;
1915 @disable this(this);
1916 ~this() pure nothrow @safe @nogc {}
1917 }
1918 S s1;
1919 s1.a = 2;
1920 S s2 = move(s1);
1921 assert(s1.a == 1);
1922 assert(s2.a == 2);
1923 }
1924
1925 // https://issues.dlang.org/show_bug.cgi?id=20869
1926 // `move` should propagate the attributes of `opPostMove`
1927 @system unittest
1928 {
1929 static struct S
1930 {
1931 void opPostMove(const ref S old) nothrow @system
1932 {
1933 __gshared int i;
1934 new int(i++); // Force @gc impure @system
1935 }
1936 }
1937
1938 alias T = void function() @system nothrow;
1939 static assert(is(typeof({ S s; move(s); }) == T));
1940 static assert(is(typeof({ S s; move(s, s); }) == T));
1941 }
1942
1943 private void moveImpl(T)(scope ref T target, return scope ref T source)
1944 {
1945 import core.internal.traits : hasElaborateDestructor;
1946
1947 static if (is(T == struct))
1948 {
1949 // Unsafe when compiling without -preview=dip1000
1950 if ((() @trusted => &source == &target)()) return;
1951 // Destroy target before overwriting it
1952 static if (hasElaborateDestructor!T) target.__xdtor();
1953 }
1954 // move and emplace source into target
1955 moveEmplaceImpl(target, source);
1956 }
1957
1958 private T moveImpl(T)(return scope ref T source)
1959 {
1960 // Properly infer safety from moveEmplaceImpl as the implementation below
1961 // might void-initialize pointers in result and hence needs to be @trusted
1962 if (false) moveEmplaceImpl(source, source);
1963
1964 return trustedMoveImpl(source);
1965 }
1966
1967 private T trustedMoveImpl(T)(return scope ref T source) @trusted
1968 {
1969 T result = void;
1970 moveEmplaceImpl(result, source);
1971 return result;
1972 }
1973
1974 @safe unittest
1975 {
1976 import core.internal.traits;
1977
1978 assertCTFEable!((){
1979 Object obj1 = new Object;
1980 Object obj2 = obj1;
1981 Object obj3 = move(obj2);
1982 assert(obj3 is obj1);
1983
1984 static struct S1 { int a = 1, b = 2; }
1985 S1 s11 = { 10, 11 };
1986 S1 s12 = move(s11);
1987 assert(s11.a == 10 && s11.b == 11 && s12.a == 10 && s12.b == 11);
1988
1989 static struct S2 { int a = 1; int * b; }
1990 S2 s21 = { 10, null };
1991 s21.b = new int;
1992 S2 s22 = move(s21);
1993 assert(s21 == s22);
1994 });
1995
1996 // Issue 5661 test(1)
1997 static struct S3
1998 {
1999 static struct X { int n = 0; ~this(){n = 0;} }
2000 X x;
2001 }
2002 static assert(hasElaborateDestructor!S3);
2003 S3 s31;
2004 s31.x.n = 1;
2005 S3 s32 = move(s31);
2006 assert(s31.x.n == 0);
2007 assert(s32.x.n == 1);
2008
2009 // Issue 5661 test(2)
2010 static struct S4
2011 {
2012 static struct X { int n = 0; this(this){n = 0;} }
2013 X x;
2014 }
2015 static assert(hasElaborateCopyConstructor!S4);
2016 S4 s41;
2017 s41.x.n = 1;
2018 S4 s42 = move(s41);
2019 assert(s41.x.n == 0);
2020 assert(s42.x.n == 1);
2021
2022 // Issue 13990 test
2023 class S5;
2024
2025 S5 s51;
2026 S5 s52 = s51;
2027 S5 s53;
2028 s53 = move(s52);
2029 assert(s53 is s51);
2030 }
2031
2032 @betterC
2033 @system unittest
2034 {
2035 static struct S { int n = 0; ~this() @system { n = 0; } }
2036 S a, b;
2037 static assert(!__traits(compiles, () @safe { move(a, b); }));
2038 static assert(!__traits(compiles, () @safe { move(a); }));
2039 a.n = 1;
2040 () @trusted { move(a, b); }();
2041 assert(a.n == 0);
2042 a.n = 1;
2043 () @trusted { move(a); }();
2044 assert(a.n == 0);
2045 }
2046 /+ this can't be tested in druntime, tests are still run in phobos
2047 @safe unittest//Issue 6217
2048 {
2049 import std.algorithm.iteration : map;
2050 auto x = map!"a"([1,2,3]);
2051 x = move(x);
2052 }
2053 +/
2054 @betterC
2055 @safe unittest// Issue 8055
2056 {
2057 static struct S
2058 {
2059 int x;
2060 ~this()
2061 {
2062 assert(x == 0);
2063 }
2064 }
2065 S foo(S s)
2066 {
2067 return move(s);
2068 }
2069 S a;
2070 a.x = 0;
2071 auto b = foo(a);
2072 assert(b.x == 0);
2073 }
2074
2075 @system unittest// Issue 8057
2076 {
2077 int n = 10;
2078 struct S
2079 {
2080 int x;
2081 ~this()
2082 {
2083 // Access to enclosing scope
2084 assert(n == 10);
2085 }
2086 }
2087 S foo(S s)
2088 {
2089 // Move nested struct
2090 return move(s);
2091 }
2092 S a;
2093 a.x = 1;
2094 auto b = foo(a);
2095 assert(b.x == 1);
2096
2097 // Regression 8171
2098 static struct Array(T)
2099 {
2100 // nested struct has no member
2101 struct Payload
2102 {
2103 ~this() {}
2104 }
2105 }
2106 Array!int.Payload x = void;
2107 move(x);
2108 move(x, x);
2109 }
2110
2111 // target must be first-parameter, because in void-functions DMD + dip1000 allows it to take the place of a return-scope
2112 private void moveEmplaceImpl(T)(scope ref T target, return scope ref T source)
2113 {
2114 import core.stdc.string : memcpy, memset;
2115 import core.internal.traits;
2116
2117 // TODO: this assert pulls in half of phobos. we need to work out an alternative assert strategy.
2118 // static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
2119 // {
2120 // import std.exception : doesPointTo;
2121 // assert(!doesPointTo(source, source) && !hasElaborateMove!T),
2122 // "Cannot move object with internal pointer unless `opPostMove` is defined.");
2123 // }
2124
2125 static if (is(T == struct))
2126 {
2127 // Unsafe when compiling without -preview=dip1000
2128 assert((() @trusted => &source !is &target)(), "source and target must not be identical");
2129
2130 static if (hasElaborateAssign!T || !isAssignable!T)
2131 () @trusted { memcpy(&target, &source, T.sizeof); }();
2132 else
2133 target = source;
2134
2135 static if (hasElaborateMove!T)
2136 __move_post_blt(target, source);
2137
2138 // If the source defines a destructor or a postblit hook, we must obliterate the
2139 // object in order to avoid double freeing and undue aliasing
2140 static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)
2141 {
2142 // If T is nested struct, keep original context pointer
2143 static if (__traits(isNested, T))
2144 enum sz = T.sizeof - (void*).sizeof;
2145 else
2146 enum sz = T.sizeof;
2147
2148 static if (__traits(isZeroInit, T))
2149 () @trusted { memset(&source, 0, sz); }();
2150 else
2151 () @trusted { memcpy(&source, __traits(initSymbol, T).ptr, sz); }();
2152 }
2153 }
2154 else static if (__traits(isStaticArray, T))
2155 {
2156 for (size_t i = 0; i < source.length; ++i)
2157 move(source[i], target[i]);
2158 }
2159 else
2160 {
2161 // Primitive data (including pointers and arrays) or class -
2162 // assignment works great
2163 target = source;
2164 }
2165 }
2166
2167 /**
2168 * Similar to $(LREF move) but assumes `target` is uninitialized. This
2169 * is more efficient because `source` can be blitted over `target`
2170 * without destroying or initializing it first.
2171 *
2172 * Params:
2173 * source = value to be moved into target
2174 * target = uninitialized value to be filled by source
2175 */
2176 void moveEmplace(T)(ref T source, ref T target) @system
2177 {
2178 moveEmplaceImpl(target, source);
2179 }
2180
2181 ///
2182 @betterC
2183 pure nothrow @nogc @system unittest
2184 {
2185 static struct Foo
2186 {
2187 pure nothrow @nogc:
2188 this(int* ptr) { _ptr = ptr; }
2189 ~this() { if (_ptr) ++*_ptr; }
2190 int* _ptr;
2191 }
2192
2193 int val;
2194 Foo foo1 = void; // uninitialized
2195 auto foo2 = Foo(&val); // initialized
2196 assert(foo2._ptr is &val);
2197
2198 // Using `move(foo2, foo1)` would have an undefined effect because it would destroy
2199 // the uninitialized foo1.
2200 // moveEmplace directly overwrites foo1 without destroying or initializing it first.
2201 moveEmplace(foo2, foo1);
2202 assert(foo1._ptr is &val);
2203 assert(foo2._ptr is null);
2204 assert(val == 0);
2205 }
2206
2207 // issue 18913
2208 @safe unittest
2209 {
2210 static struct NoCopy
2211 {
2212 int payload;
2213 ~this() { }
2214 @disable this(this);
2215 }
2216
2217 static void f(NoCopy[2]) { }
2218
2219 NoCopy[2] ncarray = [ NoCopy(1), NoCopy(2) ];
2220
2221 static assert(!__traits(compiles, f(ncarray)));
2222 f(move(ncarray));
2223 }
2224
2225 /**
2226 * This is called for a delete statement where the value
2227 * being deleted is a pointer to a struct with a destructor
2228 * but doesn't have an overloaded delete operator.
2229 *
2230 * Params:
2231 * p = pointer to the value to be deleted
2232 */
2233 void _d_delstruct(T)(ref T *p)
2234 {
2235 if (p)
2236 {
2237 debug(PRINTF) printf("_d_delstruct(%p)\n", p);
2238
2239 import core.memory : GC;
2240
2241 destroy(*p);
2242 GC.free(p);
2243 p = null;
2244 }
2245 }
2246
2247 @system unittest
2248 {
2249 int dtors = 0;
2250 struct S { ~this() { ++dtors; } }
2251
2252 S *s = new S();
2253 _d_delstruct(s);
2254
2255 assert(s == null);
2256 assert(dtors == 1);
2257 }
2258
2259 @system unittest
2260 {
2261 int innerDtors = 0;
2262 int outerDtors = 0;
2263
2264 struct Inner { ~this() { ++innerDtors; } }
2265 struct Outer
2266 {
2267 Inner *i1;
2268 Inner *i2;
2269
2270 this(int x)
2271 {
2272 i1 = new Inner();
2273 i2 = new Inner();
2274 }
2275
2276 ~this()
2277 {
2278 ++outerDtors;
2279
2280 _d_delstruct(i1);
2281 assert(i1 == null);
2282
2283 _d_delstruct(i2);
2284 assert(i2 == null);
2285 }
2286 }
2287
2288 Outer *o = new Outer(0);
2289 _d_delstruct(o);
2290
2291 assert(o == null);
2292 assert(innerDtors == 2);
2293 assert(outerDtors == 1);
2294 }