Skip to content

Commit c680f7d

Browse files
committed
fix varargs when scala.reflect with implicit converison
1 parent f76d1b5 commit c680f7d

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ trait Dynamic {
148148
untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
149149
}
150150

151+
extension (tpe: Type)
152+
def isReflectSelectableTypeRef(using Context): Boolean = tpe <:< defn.ReflectSelectableTypeRef
153+
151154
/** Handle reflection-based dispatch for members of structural types.
152155
*
153156
* Given `x.a`, where `x` is of (widened) type `T` (a value type or a nullary method type),
@@ -181,20 +184,25 @@ trait Dynamic {
181184
val fun @ Select(qual, name) = funPart(tree): @unchecked
182185
val vargss = termArgss(tree)
183186

184-
def handleRepeated(base: untpd.Tree, possiblyCurried: List[List[Tree]]) =
185-
possiblyCurried.map { args =>
187+
def handleRepeated(base: untpd.Tree, possiblyCurried: List[List[Tree]], isReflectSelectable: Boolean) = {
188+
val handled = possiblyCurried.map { args =>
186189
val isRepeated = args.exists(_.tpe.widen.isRepeatedParam)
187-
if isRepeated && qual.tpe <:< defn.ReflectSelectableTypeRef then
190+
if isRepeated && isReflectSelectable then
188191
List(untpd.TypedSplice(tpd.repeatedSeq(args, TypeTree(defn.AnyType))))
189192
else args.map { t =>
190193
val clzSym = t.tpe.resultType.classSymbol.asClass
191-
if ValueClasses.isDerivedValueClass(clzSym) && qual.tpe <:< defn.ReflectSelectableTypeRef then
194+
if ValueClasses.isDerivedValueClass(clzSym) && isReflectSelectable then
192195
val underlying = ValueClasses.valueClassUnbox(clzSym).asTerm
193196
tpd.Select(t, underlying.name)
194197
else
195198
t
196199
}.map(untpd.TypedSplice(_))
197-
}.foldLeft(base)((base, args) => untpd.Apply(base, args))
200+
}
201+
202+
if isReflectSelectable
203+
then untpd.Apply(base, handled.flatten)
204+
else handled.foldLeft(base)((base, args) => untpd.Apply(base, args))
205+
}
198206

199207
def structuralCall(selectorName: TermName, classOfs: => List[Tree]) = {
200208
val selectable = adapt(qual, defn.SelectableClass.typeRef | defn.DynamicClass.typeRef)
@@ -207,7 +215,11 @@ trait Dynamic {
207215

208216
val scall =
209217
if (vargss.isEmpty) base
210-
else handleRepeated(base, vargss)
218+
else handleRepeated(
219+
base,
220+
vargss,
221+
qual.tpe.isReflectSelectableTypeRef || selectable.tpe.isReflectSelectableTypeRef
222+
)
211223

212224
// If function is an `applyDynamic` that takes a Class* parameter,
213225
// add `classOfs`.

tests/run/i16995.check

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,6 @@ check
55
5
66
3
77
3
8-
7
8+
3
9+
7
10+
3

tests/run/i16995.scala

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ class Foo(val i: Int) extends AnyVal
22
class Argument(val x: String) extends AnyVal
33
class Reflective extends reflect.Selectable
44

5+
type ReflectiveType = {
6+
def reflectiveCall(arg1: Int)(arg2: Int): Int
7+
}
8+
9+
class ClassWithReflectiveCall {
10+
def reflectiveCall(x: Int)(y: Int): Int = x + y
11+
}
12+
513
class ScalaSelectable(values: Map[String, Any], methods: Map[String, (Int, Seq[Foo]) => Int]) extends Selectable {
614
def selectDynamic(name: String): Any = values(name)
715

@@ -48,6 +56,8 @@ class ScalaSelectable(values: Map[String, Any], methods: Map[String, (Int, Seq[F
4856
val p = reflective.letsHaveSeq(seq)
4957
println(p)
5058

59+
println(reflective.curried(foo1)(arg1)(1))
60+
5161
val cont2values = Map.empty[String, Any]
5262

5363
val cont2methods = Map[String, (Int, Seq[Foo]) => Int](
@@ -61,4 +71,13 @@ class ScalaSelectable(values: Map[String, Any], methods: Map[String, (Int, Seq[F
6171

6272
println(cont2.varargs(1, Foo(1), Foo(1)))
6373

64-
println(cont2.curried(Foo(1))(Argument("123"))(3))
74+
println(cont2.curried(Foo(1))(Argument("123"))(3))
75+
76+
{
77+
import scala.reflect.Selectable.reflectiveSelectable
78+
val obj = new ClassWithReflectiveCall()
79+
def instantiate(): ReflectiveType = obj
80+
81+
val rtype = instantiate()
82+
println(rtype.reflectiveCall(1)(2))
83+
}

0 commit comments

Comments
 (0)