diff --git a/src/expression.d b/src/expression.d index b916e484c632..c2084513d258 100644 --- a/src/expression.d +++ b/src/expression.d @@ -3929,6 +3929,30 @@ extern (C++) class IdentifierExp : Expression return e; } + // If we've reached this point and are inside a with() scope then we may + // try one last attempt by checking whether the 'wthis' object supports + // dynamic dispatching via opDispatch. + // This is done by rewriting this expression as wthis.ident. + for (Scope* sc2 = sc; sc2; sc2 = sc2.enclosing) + { + if (!sc2.scopesym) + continue; + + if (auto ss = sc2.scopesym.isWithScopeSymbol()) + { + if (ss.withstate.wthis) + { + Expression e; + e = new VarExp(loc, ss.withstate.wthis); + e = new DotIdExp(loc, e, ident); + e = e.trySemantic(sc); + if (e) + return e; + } + break; + } + } + const(char)* n = importHint(ident.toChars()); if (n) error("'%s' is not defined, perhaps you need to import %s; ?", ident.toChars(), n); diff --git a/test/compilable/b6400.d b/test/compilable/b6400.d new file mode 100644 index 000000000000..2c71107e9131 --- /dev/null +++ b/test/compilable/b6400.d @@ -0,0 +1,37 @@ +/* TEST_OUTPUT: +--- +Foo +Bar +--- +*/ +class Foo +{ + void opDispatch(string name)() { pragma(msg, "Foo"); } +} +class Bar +{ + void opDispatch(string name)() { pragma(msg, "Bar"); } +} +class Baz +{ +} + +void main() +{ + auto foo = new Foo; + auto bar = new Bar; + auto baz = new Baz; + + with (foo) + { + f0(); + with (bar) + { + f1(); + } + with (baz) + { + static assert(!__traits(compiles, f2())); + } + } +}