Skip to content

Commit f71919b

Browse files
committed
fix variant and scoped buffer
1 parent dddaed5 commit f71919b

File tree

2 files changed

+26
-14
lines changed

2 files changed

+26
-14
lines changed

source/mir/appender.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ struct ScopedBuffer(T, size_t bytes = 4096)
149149

150150
///
151151
void put(Iterable)(Iterable range) scope
152-
if (isIterable!Iterable && !isArray!Iterable)
152+
if (isIterable!Iterable && (!isArray!Iterable || hasElaborateAssign!T))
153153
{
154154
static if (hasLength!Iterable)
155155
{

source/mir/variant.d

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ module mir.variant;
55

66
private static immutable variantExceptionMsg = "mir.variant: the variant stores other type then requested.";
77
private static immutable variantNulllExceptionMsg = "mir.variant: the variant is empty and doesn't store any value.";
8-
private static immutable variantMemberExceptionMsg = "mir.variant: the variant is stores the type that isn't compatible with the user proveded visitor and arguments.";
8+
private static immutable variantMemberExceptionMsg = "mir.variant: the variant is stores the type that isn't compatible with the user provided visitor and arguments.";
99

1010
version (D_Exceptions)
1111
{
@@ -14,6 +14,8 @@ version (D_Exceptions)
1414
private static immutable variantMemberException = new Exception(variantMemberExceptionMsg);
1515
}
1616

17+
private enum int alignOf(T) = T.alignof;
18+
1719
/++
1820
Variant Type (aka Algebraic Type) with clever member access.
1921
@@ -22,14 +24,15 @@ Compatible with BetterC mode.
2224
struct Variant(Types...)
2325
if (Types.length)
2426
{
25-
import mir.utility: swap;
27+
import mir.utility: max, swap;
2628
import mir.conv: emplaceRef;
27-
import std.meta: anySatisfy;
28-
import std.traits: Largest, hasElaborateDestructor, hasElaborateAssign;
29+
import std.meta: anySatisfy, staticMap;
30+
import std.traits: Largest, hasElaborateDestructor, hasElaborateAssign, hasElaborateCopyConstructor;
2931

3032
private alias _Types = Types;
3133

32-
private void[Largest!Types.sizeof] payload = void;
34+
align(max(4, staticMap!(alignOf, Types)))
35+
private ubyte[Largest!Types.sizeof] payload;
3336
private uint type; // 0 for unininit value, index = type - 1
3437
private enum hasDestructor = anySatisfy!(hasElaborateDestructor, Types);
3538

@@ -46,18 +49,17 @@ struct Variant(Types...)
4649
}
4750
default: break;
4851
}
49-
type = 0;
5052
}
5153

52-
static if (anySatisfy!(hasElaborateAssign, Types))
54+
static if (anySatisfy!(hasElaborateCopyConstructor, Types))
5355
this(this)
5456
{
5557
S: switch (type)
5658
{
57-
static foreach (i, T; Types) static if (hasElaborateAssign!T)
59+
static foreach (i, T; Types) static if (hasElaborateCopyConstructor!T)
5860
{
5961
case i + 1:
60-
__ctor(trustedGet!T);
62+
trustedGet!T.__xpostblit();
6163
break S;
6264
}
6365
default: break;
@@ -74,6 +76,7 @@ struct Variant(Types...)
7476
{
7577
static if (hasDestructor)
7678
__dtor;
79+
payload[] = 0;
7780
type = 0;
7881
}
7982

@@ -84,7 +87,15 @@ struct Variant(Types...)
8487
static if (hasDestructor)
8588
__dtor;
8689
type = i + 1;
87-
emplaceRef(trustedGet!T);
90+
static if (__traits(isZeroInit, T))
91+
{
92+
payload[] = 0;
93+
}
94+
else
95+
{
96+
emplaceRef(trustedGet!T);
97+
payload[T.sizeof .. $] = 0;
98+
}
8899
swap(trustedGet!T, value);
89100
}
90101

@@ -93,13 +104,14 @@ struct Variant(Types...)
93104
this(T value)
94105
{
95106
type = i + 1;
96-
emplaceRef(trustedGet!T);
107+
static if (!__traits(isZeroInit, T))
108+
emplaceRef(trustedGet!T);
97109
swap(trustedGet!T, value);
98110
}
99111

100112
static foreach (i, T; Types)
101113
///
102-
ref inout(E) get(E : T)() @property return inout
114+
ref inout(T) get(E : T)() @property return inout
103115
{
104116
import mir.utility: _expect;
105117
if (_expect(i + 1 != type, false))
@@ -121,7 +133,7 @@ struct Variant(Types...)
121133

122134
static foreach (i, T; Types)
123135
/// Zero cost always nothrow `get` alternative
124-
ref inout(E) trustedGet(E : T)() @trusted @property return inout nothrow
136+
ref inout(T) trustedGet(E : T)() @trusted @property return inout nothrow
125137
{
126138
assert (i + 1 == type);
127139
return *cast(inout(T)*)payload.ptr;

0 commit comments

Comments
 (0)