e.g.
---
import std.variant : Variant;
Variant makeVariant(T)(T value)
{
return Variant(value);
}
void main()
{
const a = makeVariant("bar");
pragma(msg, a);
}
---
Results in:
/opt/compilers/dmd2/include/std/variant.d(547): Error: memcpy cannot be interpreted at compile time, because it has no available source code
/opt/compilers/dmd2/include/std/variant.d(512): called from here: this.opAssign(value)
/d214/f186.d(6): called from here: (VariantN!(32LU) __ctmp1402 = VariantN;
, __ctmp1402).this(value)
/d214/f186.d(11): called from here: makeVariant("bar")
/d214/f186.d(12): while evaluating a.init
/d214/f186.d(12): while evaluating pragma(msg, a)
Note that the error doesn't happen if pragma(msg, a) is removed. I guess the compiler is lazily evaluating 'a'?
Comment #1 by clugdbug — 2014-01-14T03:29:27Z
> Note that the error doesn't happen if pragma(msg, a) is removed. I guess the
compiler is lazily evaluating 'a'?
No, 'a' is normally just a run-time value. By putting it in a pragma(msg), you're asking the compiler to evaluate it at compile time. This fails because Variant uses memcpy. This isn't a bug. Replacing the memcpy with an array slice assignment would just cause it to fail in a different way.
Variants are intrinsically a bit nasty, they're basically a union, so there's actually multiple reasons why they don't work in CTFE.
Comment #2 by norm.rowtree — 2019-02-07T07:55:06Z
I get pretty much the same error reported using the code snippet below and DMD D Compiler v2.084.0
struct S {
Variant v = Variant(10);
}
void main() {auto s = S();}
dmd2/linux/bin64/../../src/phobos/std/variant.d(661): Error: memcpy cannot be interpreted at compile time, because it has no available source code
Error: cannot interpret <error> at compile time
I don't need this evaluated at compile time, I just want a default value when the struct is instantiated at runtime.
Thanks,
Norm
Comment #3 by dfj1esp02 — 2019-02-08T22:07:19Z
Default struct value doesn't run code at runtime and there are no plans for it. You can disable default struct constructor to make non-default constructor mandatory, `S()` form is fine too if you declare static opCall.
Comment #4 by ali.akhtarzada — 2019-03-23T09:45:25Z
This is unfortunately a pain point in the language. The problem is that D expects a .init value for every type to be known. So currently, the (arbitrary) choice has been to not allow a default constructor because people could get confused by statements such as
struct A {
int i;
this() { i = 4; }
}
A a;
writeln(a.i); // prints 0
The code above, in D, needs to call A.init, which is not the same as the constructor.
The only work around is the static opCall, but then you can't have any constructors, which is unfortunately not practical.
D could either allow a default constructor and document the differences between initialization and construction, or lift the restriction of static opCall and other constructors in the same type.
Comment #5 by norm.rowtree — 2019-04-15T21:46:53Z
Thanks, the static opCall workaround is good enough for my needs.
Comment #6 by snarwin+bugzilla — 2020-06-13T19:34:16Z
*** Issue 17987 has been marked as a duplicate of this issue. ***
Comment #7 by robert.schadek — 2024-12-01T16:19:50Z