www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 19588] New: Invalid property opDispatch setter call inside


          Issue ID: 19588
           Summary: Invalid  property opDispatch setter call inside the
           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;

    Variant opDispatch(string name)() const {
        return values[name];

    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;


The program will exit with a "Range Violation" exception. The reason is that
the compiler frontend generates a different AST when calling  property

Here is how the AST looks like outside of "with":


And here is what happens inside the WithStatement:

with (test)
    (VariantN!32LU __tmpfordtor701 = ((VariantN!32LU __tmpfordtor700 =
(*__withSym).opDispatch();) , __tmpfordtor700).opAssign(3.14);) ,

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;

Dlang online sandbox link: https://run.dlang.io/is/pwbm0d
Gist: https://gist.github.com/run-dlang/a8fbbc5dc49346b887b9aaee8758ffca

Jan 15 2019