11module core.lifetime ;
22
3- /+
4- emplaceRef is a package function for druntime internal use. It works like
5- emplace, but takes its argument by ref (as opposed to "by pointer").
6- This makes it easier to use, easier to be safe, and faster in a non-inline
7- build.
8- Furthermore, emplaceRef optionally takes a type parameter, which specifies
9- the type we want to build. This helps to build qualified objects on mutable
10- buffer, without breaking the type system with unsafe casts.
11- +/
12- private void emplaceRef (T, UT , Args... )(ref UT chunk, auto ref Args args)
13- {
14- static if (args.length == 0 )
15- {
16- static assert (is (typeof ({static T i;})),
17- " Cannot emplace a " ~ T.stringof ~ " because " ~ T.stringof ~
18- " .this() is annotated with @disable." );
19- static if (is (T == class )) static assert (! __traits(isAbstractClass, T),
20- T.stringof ~ " is abstract and it can't be emplaced" );
21- emplaceInitializer(chunk);
22- }
23- else static if (
24- ! is (T == struct ) && Args.length == 1 /* primitives, enums, arrays */
25- ||
26- Args.length == 1 && is (typeof ({T t = args[0 ];})) /* conversions */
27- ||
28- is (typeof (T(args))) /* general constructors */ )
29- {
30- static struct S
31- {
32- T payload;
33- this (ref Args x)
34- {
35- static if (Args.length == 1 )
36- static if (is (typeof (payload = x[0 ])))
37- payload = x[0 ];
38- else
39- payload = T(x[0 ]);
40- else
41- payload = T(x);
42- }
43- }
44- if (__ctfe)
45- {
46- static if (is (typeof (chunk = T(args))))
47- chunk = T(args);
48- else static if (args.length == 1 && is (typeof (chunk = args[0 ])))
49- chunk = args[0 ];
50- else assert (0 , " CTFE emplace doesn't support "
51- ~ T.stringof ~ " from " ~ Args.stringof);
52- }
53- else
54- {
55- S* p = () @trusted { return cast (S* ) &chunk; }();
56- static if (UT .sizeof > 0 )
57- emplaceInitializer(* p);
58- p.__ctor(args);
59- }
60- }
61- else static if (is (typeof (chunk.__ctor(args))))
62- {
63- // This catches the rare case of local types that keep a frame pointer
64- emplaceInitializer(chunk);
65- chunk.__ctor(args);
66- }
67- else
68- {
69- // We can't emplace. Try to diagnose a disabled postblit.
70- static assert (! (Args.length == 1 && is (Args[0 ] : T)),
71- " Cannot emplace a " ~ T.stringof ~ " because " ~ T.stringof ~
72- " .this(this) is annotated with @disable." );
73-
74- // We can't emplace.
75- static assert (false ,
76- T.stringof ~ " cannot be emplaced from " ~ Args[].stringof ~ " ." );
77- }
78- }
79- // ditto
80- static import core.internal.traits ;
81- private void emplaceRef (UT , Args... )(ref UT chunk, auto ref Args args)
82- if (is (UT == core.internal.traits.Unqual ! UT ))
83- {
84- emplaceRef! (UT , UT )(chunk, args);
85- }
86-
87- // emplace helper functions
88- private void emplaceInitializer (T)(scope ref T chunk) @trusted pure nothrow
89- {
90- import core.internal.traits : hasElaborateAssign, isAssignable;
91- static if (! hasElaborateAssign! T && isAssignable! T)
92- chunk = T.init;
93- else
94- {
95- static if (__traits(isZeroInit, T))
96- {
97- import core.stdc.string : memset;
98- memset(&chunk, 0 , T.sizeof);
99- }
100- else
101- {
102- import core.stdc.string : memcpy;
103- static immutable T init = T.init;
104- memcpy(&chunk, &init, T.sizeof);
105- }
106- }
107- }
108-
1093// emplace
1104/**
1115Given a pointer `chunk` to uninitialized memory (but already typed
@@ -116,6 +10,8 @@ as `chunk`).
11610 */
11711T* emplace (T)(T* chunk) @safe pure nothrow
11812{
13+ import core.internal.lifetime : emplaceRef;
14+
11915 emplaceRef! T(* chunk);
12016 return chunk;
12117}
@@ -160,6 +56,8 @@ as `chunk`).
16056T* emplace (T, Args... )(T* chunk, auto ref Args args)
16157 if (is (T == struct ) || Args.length == 1 )
16258{
59+ import core.internal.lifetime : emplaceRef;
60+
16361 emplaceRef! T(* chunk, args);
16462 return chunk;
16563}
@@ -366,6 +264,8 @@ T* emplace(T, Args...)(void[] chunk, auto ref Args args)
366264 if (! is (T == class ))
367265{
368266 import core.internal.traits : Unqual;
267+ import core.internal.lifetime : emplaceRef;
268+
369269 testEmplaceChunk(chunk, T.sizeof, T.alignof);
370270 emplaceRef! (T, Unqual! T)(* cast (Unqual! T* ) chunk.ptr, args);
371271 return cast (T* ) chunk.ptr;
@@ -1176,6 +1076,8 @@ version (unittest)
11761076
11771077@system unittest // Constness
11781078{
1079+ import core.internal.lifetime : emplaceRef;
1080+
11791081 int a = void ;
11801082 emplaceRef! (const int )(a, 5 );
11811083
@@ -1200,6 +1102,8 @@ version (unittest)
12001102
12011103pure nothrow @safe @nogc unittest
12021104{
1105+ import core.internal.lifetime : emplaceRef;
1106+
12031107 int i;
12041108 emplaceRef(i);
12051109 emplaceRef! int (i);
@@ -1210,6 +1114,8 @@ pure nothrow @safe @nogc unittest
12101114// Test attribute propagation for UDTs
12111115pure nothrow @safe /* @nogc */ unittest
12121116{
1117+ import core.internal.lifetime : emplaceRef;
1118+
12131119 static struct Safe
12141120 {
12151121 this (this ) pure nothrow @safe @nogc {}
0 commit comments