If a message that is a struct comprising a struct is sent from one process to another using std.concurrency send, then the std.concurrency receive throws an assertion fail.
The code I shall attach to this issue, when run using rdmd (2.080 from d-apt) on Debian Sid gives the following:
|> rdmd receiveBreaksWithThisMessage.d
Receiver going into receive.
Sender sending.
Sender finished.
Receiver receive threw core.exception.AssertError@/usr/include/dmd/phobos/std/variant.d(323): Message
----------------
??:? _d_assert_msg [0xa362e3a6]
??:? bool std.variant.VariantN!(32uL).VariantN.handler!(receiveBreaksWithThisMessage.Message).handler(std.variant.VariantN!(32uL).VariantN.OpID, ubyte[32]*, void*).tryPutting(receiveBreaksWithThisMessage.Message*, TypeInfo, void*) [0xa361d793]
??:? long std.variant.VariantN!(32uL).VariantN.handler!(receiveBreaksWithThisMessage.Message).handler(std.variant.VariantN!(32uL).VariantN.OpID, ubyte[32]*, void*) [0xa361d341]
??:? inout @property inout(receiveBreaksWithThisMessage.Message) std.variant.VariantN!(32uL).VariantN.get!(receiveBreaksWithThisMessage.Message).get() [0xa3628643]
??:? void std.concurrency.Message.map!(void function(receiveBreaksWithThisMessage.Message) @safe*).map(void function(receiveBreaksWithThisMessage.Message) @safe*) [0xa3628600]
??:? bool std.concurrency.MessageBox.get!(void function(receiveBreaksWithThisMessage.Message) @safe*).get(scope void function(receiveBreaksWithThisMessage.Message) @safe*).onStandardMsg(ref std.concurrency.Message) [0xa362803f]
??:? bool std.concurrency.MessageBox.get!(void function(receiveBreaksWithThisMessage.Message) @safe*).get(scope void function(receiveBreaksWithThisMessage.Message) @safe*).scan(ref std.concurrency.List!(std.concurrency.Message).List) [0xa36283e7]
??:? bool std.concurrency.MessageBox.get!(void function(receiveBreaksWithThisMessage.Message) @safe*).get(scope void function(receiveBreaksWithThisMessage.Message) @safe*) [0xa3627f7a]
??:? void std.concurrency.receive!(void function(receiveBreaksWithThisMessage.Message) @safe*).receive(void function(receiveBreaksWithThisMessage.Message) @safe*) [0xa3627e09]
??:? void receiveBreaksWithThisMessage.receiver() [0xa361c387]
??:? void std.concurrency._spawn!(void function()*)._spawn(bool, void function()*).exec() [0xa362b663]
??:? void core.thread.Thread.run() [0xa362f3a3]
??:? thread_entryPoint [0xa363f23f]
??:? [0x4a4e25a9]
Receiver finished.
Comment #1 by russel — 2018-06-02T09:43:52Z
Created attachment 1699
Code exhibiting the error
Comment #2 by schveiguy — 2018-06-04T11:49:47Z
The issue comes from std.variant.Variant checking the wrong thing when it comes to constancy.
A smaller test case:
import std.variant;
import std.stdio;
struct S
{
const int x;
}
void main()
{
Variant v = S(1);
writeln(v.get!S); // error
}
The issue is with the check inside std.variant to see if you can copy the given type to the requested type. The type matches, but the copy would normally fail because you can't overwrite const data.
However, in the case of v.get!S, it's a move and not a copy. The check should be on moving the data, not copying. I have tested a fix, will submit a PR.