Issue 11864 - std.variant.Variant doesn't work with CTFE
Summary: std.variant.Variant doesn't work with CTFE
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: phobos (show other issues)
Version: D2
Hardware: All All
: P4 enhancement
Assignee: No Owner
URL:
Keywords:
: 17987 (view as issue list)
Depends on:
Blocks:
 
Reported: 2014-01-03 14:45 UTC by Dylan Knutson
Modified: 2024-12-01 16:19 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Dylan Knutson 2014-01-03 14:45:12 UTC
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 Don 2014-01-14 03:29:27 UTC
> 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 Norm Rowtree 2019-02-07 07:55:06 UTC
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 anonymous4 2019-02-08 22:07:19 UTC
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 Ali Ak 2019-03-23 09:45:25 UTC
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 Norm Rowtree 2019-04-15 21:46:53 UTC
Thanks, the static opCall workaround is good enough for my needs.
Comment 6 Paul Backus 2020-06-13 19:34:16 UTC
*** Issue 17987 has been marked as a duplicate of this issue. ***
Comment 7 dlangBugzillaToGithub 2024-12-01 16:19:50 UTC
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/phobos/issues/10026

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB