Skip to content

Commit b5b491f

Browse files
committed
Allow selectDynamic and applyDynamic to be an extension methods
Allow selectDynamic and applyDynamic to be an extension methods when dispatching structurally. Fixes #17100
1 parent 89a744f commit b5b491f

File tree

2 files changed

+14
-4
lines changed

2 files changed

+14
-4
lines changed

compiler/src/dotty/tools/dotc/typer/Dynamic.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ trait Dynamic {
186186
// ($qual: Selectable).$selectorName("$name")
187187
val base =
188188
untpd.Apply(
189-
untpd.TypedSplice(selectable.select(selectorName)).withSpan(fun.span),
189+
untpd.Select(untpd.TypedSplice(selectable), selectorName).withSpan(fun.span),
190190
(Literal(Constant(name.encode.toString)) :: Nil).map(untpd.TypedSplice(_)))
191191

192192
val scall =
@@ -219,19 +219,19 @@ trait Dynamic {
219219
extension (tree: Tree)
220220
/** The implementations of `selectDynamic` and `applyDynamic` in `scala.reflect.SelectDynamic` have no information about the expected return type of a value/method which was declared in the refinement,
221221
* only the JVM type after erasure can be obtained through reflection, e.g.
222-
*
222+
*
223223
* class Foo(val i: Int) extends AnyVal
224224
* class Reflective extends reflect.Selectable
225225
* val reflective = new Reflective {
226226
* def foo = Foo(1) // Foo at compile time, java.lang.Integer in reflection
227227
* }
228-
*
228+
*
229229
* Because of that reflective access cannot be implemented properly in `scala.reflect.SelectDynamic` itself
230230
* because it's not known there if the value should be wrapped in a value class constructor call or not.
231231
* Hence the logic of wrapping is performed here, relying on the fact that the implementations of `selectDynamic` and `applyDynamic` in `scala.reflect.SelectDynamic` are final.
232232
*/
233233
def maybeBoxingCast(tpe: Type) =
234-
val maybeBoxed =
234+
val maybeBoxed =
235235
if ValueClasses.isDerivedValueClass(tpe.classSymbol) && qual.tpe <:< defn.ReflectSelectableTypeRef then
236236
val genericUnderlying = ValueClasses.valueClassUnbox(tpe.classSymbol.asClass)
237237
val underlying = tpe.select(genericUnderlying).widen.resultType

tests/pos/i17100.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
trait Sel extends Selectable
2+
3+
extension (s: Sel)
4+
def selectDynamic(name: String) = ???
5+
def applyDynamic(name: String)(x: Int) = ???
6+
7+
val sel = (new Sel {}).asInstanceOf[Sel{ def foo: String; def bar(x: Int): Int }]
8+
val foo = sel.selectDynamic("foo")
9+
val foo2 = sel.foo
10+
val foo3 = sel.bar(2)

0 commit comments

Comments
 (0)