Skip to content

Commit 60b6ff0

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 scala#17100
1 parent 6e5be23 commit 60b6ff0

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)