Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions std/concurrency.d
Original file line number Diff line number Diff line change
Expand Up @@ -2529,3 +2529,17 @@ auto ref initOnce(alias var)(lazy typeof(var) init, Mutex mutex)
static assert(!__traits(compiles, initOnce!c(true))); // TLS
static assert(!__traits(compiles, initOnce!d(true))); // local variable
}

// test ability to send shared arrays
@system unittest
{
static shared int[] x = new shared(int)[1];
auto tid = spawn({
auto arr = receiveOnly!(shared(int)[]);
arr[0] = 5;
ownerTid.send(true);
});
tid.send(x);
receiveOnly!(bool);
assert(x[0] == 5);
}
10 changes: 8 additions & 2 deletions std/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -4596,8 +4596,14 @@ template ImplicitConversionTargets(T)
else static if (is(T : Object))
alias ImplicitConversionTargets = TransitiveBaseTypeTuple!(T);
else static if (isDynamicArray!T && !is(typeof(T.init[0]) == const))
alias ImplicitConversionTargets =
AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
{
static if (is(typeof(T.init[0]) == shared))
alias ImplicitConversionTargets =
AliasSeq!(const(shared(Unqual!(typeof(T.init[0]))))[]);
else
alias ImplicitConversionTargets =
AliasSeq!(const(Unqual!(typeof(T.init[0])))[]);
}
else static if (is(T : void*))
alias ImplicitConversionTargets = AliasSeq!(void*);
else
Expand Down
75 changes: 63 additions & 12 deletions std/variant.d
Original file line number Diff line number Diff line change
Expand Up @@ -529,14 +529,14 @@ private:
case OpID.postblit:
static if (hasElaborateCopyConstructor!A)
{
typeid(A).postblit(zis);
zis.__xpostblit();
}
break;

case OpID.destruct:
static if (hasElaborateDestructor!A)
{
typeid(A).destroy(zis);
zis.__xdtor();
}
break;

Expand Down Expand Up @@ -613,19 +613,21 @@ public:
static if (T.sizeof <= size)
{
import core.stdc.string : memcpy;
// If T is a class we're only copying the reference, so it
// should be safe to cast away shared so the memcpy will work.
// rhs has already been copied onto the stack, so even if T is
// shared, it's not really shared. Therefore, we can safely
// remove the shared qualifier when copying, as we are only
// copying from the unshared stack.
//
// TODO: If a shared class has an atomic reference then using
// an atomic load may be more correct. Just make sure
// to use the fastest approach for the load op.
static if (is(T == class) && is(T == shared))
memcpy(&store, cast(const(void*)) &rhs, rhs.sizeof);
else
memcpy(&store, &rhs, rhs.sizeof);
// In addition, the storage location is not accessible outside
// the Variant, so even if shared data is stored there, it's
// not really shared, as it's copied out as well.
memcpy(&store, cast(const(void*)) &rhs, rhs.sizeof);
static if (hasElaborateCopyConstructor!T)
{
typeid(T).postblit(&store);
// Safer than using typeid's postblit function because it
// type-checks the postblit function against the qualifiers
// of the type.
(cast(T*)&store).__xpostblit();
}
}
else
Expand Down Expand Up @@ -1375,6 +1377,55 @@ pure nothrow @nogc
v.get!S;
}

// issue 13262
@system unittest
{
static void fun(T)(Variant v){
T x;
v = x;
auto r = v.get!(T);
}
Variant v;
fun!(shared(int))(v);
fun!(shared(int)[])(v);

static struct S1
{
int c;
string a;
}

static struct S2
{
string a;
shared int[] b;
}

static struct S3
{
string a;
shared int[] b;
int c;
}

fun!(S1)(v);
fun!(shared(S1))(v);
fun!(S2)(v);
fun!(shared(S2))(v);
fun!(S3)(v);
fun!(shared(S3))(v);

// ensure structs that are shared, but don't have shared postblits
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to ensure that a struct that does have a shared postblit can be used.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried. It can't, but not because of this code, there are a whole bunch of places where it fails. I didn't want to fix everything 😉

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough :)

// can't be used.
static struct S4
{
int x;
this(this) {x = 0;}
}

fun!(S4)(v);
static assert(!is(typeof(fun!(shared(S4))(v))));
}

/**
_Algebraic data type restricted to a closed set of possible
Expand Down