From 2808f3d7b04867626081e21538faa13f570b6d3a Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 15 Mar 2023 13:41:31 +0100 Subject: [PATCH] Also allow structural dispatch on Dynamic Given ```scala trait Sel extends Dynamic extension (s: Sel) def selectDynamic(name: String) = ??? ``` the following worked: ```scala val sel = new Sel {} val foo = sel.foo ``` but the following didn't: ```scala val sel2 = (new Sel {}).asInstanceOf[Sel{ def foo: String }] val foo2 = sel2.foo ``` The problem was that we recognized a structural dispatch and then required the qualifier to be an instance of `Selectable`. But in fact, `Dynamic` works just as well, and the mechanism is the same. It's just that `Dynamic` is less type safe then `Selectable`. --- compiler/src/dotty/tools/dotc/typer/Dynamic.scala | 2 +- tests/pos/i17100a.scala | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 tests/pos/i17100a.scala diff --git a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala index 1513872cf47a..717966923708 100644 --- a/compiler/src/dotty/tools/dotc/typer/Dynamic.scala +++ b/compiler/src/dotty/tools/dotc/typer/Dynamic.scala @@ -181,7 +181,7 @@ trait Dynamic { val vargss = termArgss(tree) def structuralCall(selectorName: TermName, classOfs: => List[Tree]) = { - val selectable = adapt(qual, defn.SelectableClass.typeRef) + val selectable = adapt(qual, defn.SelectableClass.typeRef | defn.DynamicClass.typeRef) // ($qual: Selectable).$selectorName("$name") val base = diff --git a/tests/pos/i17100a.scala b/tests/pos/i17100a.scala new file mode 100644 index 000000000000..abf74c80a4f5 --- /dev/null +++ b/tests/pos/i17100a.scala @@ -0,0 +1,12 @@ + +import scala.language.dynamics +trait Sel extends Dynamic + +extension (s: Sel) + def selectDynamic(name: String) = ??? + +val sel = new Sel {} +val foo = sel.foo +val sel2 = (new Sel {}).asInstanceOf[Sel{ def foo: String }] +val foo2 = sel2.foo +