Skip to content

Commit

Permalink
fix varargs when scala.reflect with implicit converison
Browse files Browse the repository at this point in the history
  • Loading branch information
G1ng3r committed Mar 30, 2024
1 parent f76d1b5 commit c680f7d
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 8 deletions.
24 changes: 18 additions & 6 deletions compiler/src/dotty/tools/dotc/typer/Dynamic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ trait Dynamic {
untpd.Apply(selectWithTypes, Literal(Constant(name.toString)))
}

extension (tpe: Type)
def isReflectSelectableTypeRef(using Context): Boolean = tpe <:< defn.ReflectSelectableTypeRef

/** Handle reflection-based dispatch for members of structural types.
*
* Given `x.a`, where `x` is of (widened) type `T` (a value type or a nullary method type),
Expand Down Expand Up @@ -181,20 +184,25 @@ trait Dynamic {
val fun @ Select(qual, name) = funPart(tree): @unchecked
val vargss = termArgss(tree)

def handleRepeated(base: untpd.Tree, possiblyCurried: List[List[Tree]]) =
possiblyCurried.map { args =>
def handleRepeated(base: untpd.Tree, possiblyCurried: List[List[Tree]], isReflectSelectable: Boolean) = {
val handled = possiblyCurried.map { args =>
val isRepeated = args.exists(_.tpe.widen.isRepeatedParam)
if isRepeated && qual.tpe <:< defn.ReflectSelectableTypeRef then
if isRepeated && isReflectSelectable then
List(untpd.TypedSplice(tpd.repeatedSeq(args, TypeTree(defn.AnyType))))
else args.map { t =>
val clzSym = t.tpe.resultType.classSymbol.asClass
if ValueClasses.isDerivedValueClass(clzSym) && qual.tpe <:< defn.ReflectSelectableTypeRef then
if ValueClasses.isDerivedValueClass(clzSym) && isReflectSelectable then
val underlying = ValueClasses.valueClassUnbox(clzSym).asTerm
tpd.Select(t, underlying.name)
else
t
}.map(untpd.TypedSplice(_))
}.foldLeft(base)((base, args) => untpd.Apply(base, args))
}

if isReflectSelectable
then untpd.Apply(base, handled.flatten)
else handled.foldLeft(base)((base, args) => untpd.Apply(base, args))
}

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

val scall =
if (vargss.isEmpty) base
else handleRepeated(base, vargss)
else handleRepeated(
base,
vargss,
qual.tpe.isReflectSelectableTypeRef || selectable.tpe.isReflectSelectableTypeRef
)

// If function is an `applyDynamic` that takes a Class* parameter,
// add `classOfs`.
Expand Down
4 changes: 3 additions & 1 deletion tests/run/i16995.check
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ check
5
3
3
7
3
7
3
21 changes: 20 additions & 1 deletion tests/run/i16995.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ class Foo(val i: Int) extends AnyVal
class Argument(val x: String) extends AnyVal
class Reflective extends reflect.Selectable

type ReflectiveType = {
def reflectiveCall(arg1: Int)(arg2: Int): Int
}

class ClassWithReflectiveCall {
def reflectiveCall(x: Int)(y: Int): Int = x + y
}

class ScalaSelectable(values: Map[String, Any], methods: Map[String, (Int, Seq[Foo]) => Int]) extends Selectable {
def selectDynamic(name: String): Any = values(name)

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

println(reflective.curried(foo1)(arg1)(1))

val cont2values = Map.empty[String, Any]

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

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

println(cont2.curried(Foo(1))(Argument("123"))(3))
println(cont2.curried(Foo(1))(Argument("123"))(3))

{
import scala.reflect.Selectable.reflectiveSelectable
val obj = new ClassWithReflectiveCall()
def instantiate(): ReflectiveType = obj

val rtype = instantiate()
println(rtype.reflectiveCall(1)(2))
}

0 comments on commit c680f7d

Please sign in to comment.