Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit d10f515

Browse files
authored
Merge pull request #2498 from edi33416/move_emplace_ref
Move emplaceRef to core/internal
2 parents 54f20ba + 64a5d4e commit d10f515

File tree

5 files changed

+126
-106
lines changed

5 files changed

+126
-106
lines changed

mak/COPY

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ COPY=\
2727
$(IMPDIR)\core\internal\string.d \
2828
$(IMPDIR)\core\internal\traits.d \
2929
$(IMPDIR)\core\internal\utf.d \
30+
$(IMPDIR)\core\internal\lifetime.d \
3031
\
3132
$(IMPDIR)\core\stdc\assert_.d \
3233
$(IMPDIR)\core\stdc\complex.d \

mak/SRCS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ SRCS=\
2727
src\core\internal\string.d \
2828
src\core\internal\traits.d \
2929
src\core\internal\utf.d \
30+
src\core\internal\lifetime.d \
3031
\
3132
src\core\stdc\assert_.d \
3233
src\core\stdc\complex.d \

mak/WINDOWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ $(IMPDIR)\core\internal\traits.d : src\core\internal\traits.d
126126
$(IMPDIR)\core\internal\utf.d : src\core\internal\utf.d
127127
copy $** $@
128128

129+
$(IMPDIR)\core\internal\lifetime.d : src\core\internal\lifetime.d
130+
copy $** $@
131+
129132
$(IMPDIR)\core\stdc\assert_.d : src\core\stdc\assert_.d
130133
copy $** $@
131134

src/core/internal/lifetime.d

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
module core.internal.lifetime;
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+
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+
80+
// ditto
81+
static import core.internal.traits;
82+
void emplaceRef(UT, Args...)(ref UT chunk, auto ref Args args)
83+
if (is(UT == core.internal.traits.Unqual!UT))
84+
{
85+
emplaceRef!(UT, UT)(chunk, args);
86+
}
87+
88+
//emplace helper functions
89+
private nothrow pure @trusted
90+
void emplaceInitializer(T)(scope ref T chunk)
91+
{
92+
import core.internal.traits : hasElaborateAssign, isAssignable;
93+
static if (!hasElaborateAssign!T && isAssignable!T)
94+
chunk = T.init;
95+
else
96+
{
97+
static if (__traits(isZeroInit, T))
98+
{
99+
import core.stdc.string : memset;
100+
memset(&chunk, 0, T.sizeof);
101+
}
102+
else
103+
{
104+
import core.stdc.string : memcpy;
105+
static immutable T init = T.init;
106+
memcpy(&chunk, &init, T.sizeof);
107+
}
108+
}
109+
}

src/core/lifetime.d

Lines changed: 12 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -1,111 +1,5 @@
11
module 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
/**
1115
Given a pointer `chunk` to uninitialized memory (but already typed
@@ -116,6 +10,8 @@ as `chunk`).
11610
*/
11711
T* 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`).
16056
T* 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

12011103
pure 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
12111115
pure 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

Comments
 (0)