[Issue 19588] New: Invalid @property opDispatch setter call inside the WithStatement
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Tue Jan 15 22:41:39 UTC 2019
https://issues.dlang.org/show_bug.cgi?id=19588
Issue ID: 19588
Summary: Invalid @property opDispatch setter call inside the
WithStatement
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: jacob.100205 at gmail.com
import std.stdio;
import std.variant : Variant;
struct var {
private Variant[string] values;
@property
Variant opDispatch(string name)() const {
return values[name];
}
@property
void opDispatch(string name, T)(T val) {
values[name] = val;
}
}
void main()
{
var test;
// Normal flow
test.foo = "test";
test.bar = 50;
writeln("test.foo = ", test.foo);
writeln("test.bar = ", test.bar);
// Error flow
with (test) {
foobar = 3.14;
}
writeln(test.foobar);
}
The program will exit with a "Range Violation" exception. The reason is that
the compiler frontend generates a different AST when calling @property
opDispatch().
Here is how the AST looks like outside of "with":
test.opDispatch("test");
test.opDispatch(50);
And here is what happens inside the WithStatement:
with (test)
{
(VariantN!32LU __tmpfordtor701 = ((VariantN!32LU __tmpfordtor700 =
(*__withSym).opDispatch();) , __tmpfordtor700).opAssign(3.14);) ,
__tmpfordtor701;
}
Which means that it first calls the getter, captures a reference to a variable,
and finally calls opDispatch setter on this variable.
The right behavior would be to call the setter directly like this:
with (test)
{
var __tmp = test;
__tmp.opDispatch(3.14);
}
Dlang online sandbox link: https://run.dlang.io/is/pwbm0d
Gist: https://gist.github.com/run-dlang/a8fbbc5dc49346b887b9aaee8758ffca
--
More information about the Digitalmars-d-bugs
mailing list