Comment #0 by snarwin+bugzilla — 2016-11-05T03:07:05Z
Under dmd 2.072, calling std.variant.visit from inside a pure function is forbidden, even if all of the functions used to instantiate visit are themselves pure.
Example code:
import std.variant;
alias IntOrString = Algebraic!(int, string);
IntOrString twice(IntOrString v) pure {
return v.visit!(
(int n) pure => IntOrString(2*n),
(string s) pure => IntOrString(s ~ s)
)();
}
...and the compiler error:
Error: pure function 'test2.twice' cannot call impure function 'std.variant.visit!(function (int n) => VariantN(& handler, cast(ubyte)0u, ).this(2 * n), function (string s) => VariantN(& handler, cast(ubyte)0u, ).this(s ~ s)).visit!(VariantN!(16LU, int, string)).visit'
Comment #1 by snarwin+bugzilla — 2017-06-04T22:28:07Z
Seems like the culprit is VariantN.peek, which calls the property function "type", which calls (through "fptr") an instance of the internal template function "handler", which isn't pure.
Almost all of VariantN's operations use "handler" internally, so making it pure would likely be difficult. On the other hand, modifying "fptr" to point to different instances of "handler" is how VariantN keeps track of the type of the stored object, so avoiding the use of "handler" would require substantial changes to VariantN's implementation.
Here's the trail of breadcrumbs:
---
// test.d
import std.variant;
alias Example = Algebraic!(int, double);
void main() {
Example x;
pragma(msg, typeof(&x.peek!int));
pragma(msg, typeof(&x.type));
}
---
$ dmd test.d
inout(int)* delegate() inout @property @system
TypeInfo delegate() const nothrow @property @trusted
$ dmd --version
DMD64 D Compiler v2.074.0
Comment #2 by ilyayaroshenko — 2017-12-16T16:05:22Z
Variant's "get" method is not pure too. It was a big surprise. No I need to figure out how to deal with it, the whole big project is pure.
Comment #3 by snarwin+bugzilla — 2018-03-20T20:39:51Z
I've made some progress on this, but am unable to make VariantN.peek pure, because this if statement
if (type != typeid(T))
return null;
...calls object.opEquals, which is not pure. So issue #13933 needs to be fixed before we can solve this.
Comment #4 by robert.schadek — 2024-12-01T16:28:12Z