1
1
module core.lifetime ;
2
2
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
-
109
3
// emplace
110
4
/**
111
5
Given a pointer `chunk` to uninitialized memory (but already typed
@@ -116,6 +10,8 @@ as `chunk`).
116
10
*/
117
11
T* emplace (T)(T* chunk) @safe pure nothrow
118
12
{
13
+ import core.internal.lifetime : emplaceRef;
14
+
119
15
emplaceRef! T(* chunk);
120
16
return chunk;
121
17
}
@@ -160,6 +56,8 @@ as `chunk`).
160
56
T* emplace (T, Args... )(T* chunk, auto ref Args args)
161
57
if (is (T == struct ) || Args.length == 1 )
162
58
{
59
+ import core.internal.lifetime : emplaceRef;
60
+
163
61
emplaceRef! T(* chunk, args);
164
62
return chunk;
165
63
}
@@ -366,6 +264,8 @@ T* emplace(T, Args...)(void[] chunk, auto ref Args args)
366
264
if (! is (T == class ))
367
265
{
368
266
import core.internal.traits : Unqual;
267
+ import core.internal.lifetime : emplaceRef;
268
+
369
269
testEmplaceChunk(chunk, T.sizeof, T.alignof);
370
270
emplaceRef! (T, Unqual! T)(* cast (Unqual! T* ) chunk.ptr, args);
371
271
return cast (T* ) chunk.ptr;
@@ -1176,6 +1076,8 @@ version (unittest)
1176
1076
1177
1077
@system unittest // Constness
1178
1078
{
1079
+ import core.internal.lifetime : emplaceRef;
1080
+
1179
1081
int a = void ;
1180
1082
emplaceRef! (const int )(a, 5 );
1181
1083
@@ -1200,6 +1102,8 @@ version (unittest)
1200
1102
1201
1103
pure nothrow @safe @nogc unittest
1202
1104
{
1105
+ import core.internal.lifetime : emplaceRef;
1106
+
1203
1107
int i;
1204
1108
emplaceRef(i);
1205
1109
emplaceRef! int (i);
@@ -1210,6 +1114,8 @@ pure nothrow @safe @nogc unittest
1210
1114
// Test attribute propagation for UDTs
1211
1115
pure nothrow @safe /* @nogc */ unittest
1212
1116
{
1117
+ import core.internal.lifetime : emplaceRef;
1118
+
1213
1119
static struct Safe
1214
1120
{
1215
1121
this (this ) pure nothrow @safe @nogc {}
0 commit comments