digitalmars.D.bugs - [Issue 19588] New: Invalid property opDispatch setter call inside
- d-bugmail puremagic.com (65/65) Jan 15 2019 https://issues.dlang.org/show_bug.cgi?id=19588
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 puremagic.com Reporter: jacob.100205 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 --
Jan 15 2019