Jess Smith Jess Smith - 4 months ago 15
Scala Question

Reflection incorrectly matching by-name parameters

I'm trying to detect by-name parameters in a method definition. My approach is based on this question's

ByNameParam
solution.

Unfortunately, by-name parameters match to
TypeRef
s for repeated arguments, and vice-versa. See the below code for an example.

I assume that this is not the intended behavior. Is the bug on my end or is there a problem with the
Definitions
module?

import scala.reflect.runtime.universe._

class X { def x(i: => Int, other: Int*) = i * 2 }

val typeSignature = typeOf[X].member(TermName("x")).typeSignature
val paramTypes = typeSignature match {
case MethodType(params, _) => params map { _.typeSignature }
}
val repeatedParamDefinition = definitions.RepeatedParamClass
val byNameDefinition = definitions.ByNameParamClass

// prints "Got repeatedParamDefinition" twice
paramTypes map { signature =>
signature match {
case TypeRef(_, repeatedParamDefinition, args) =>
println("Got repeatedParamDefinition")
args
case TypeRef(_, byNameDefinition, args) =>
println("Got byNameDefinition")
args
}
}

// Prints "Got byNameDefinition" twice
paramTypes map { signature =>
signature match {
case TypeRef(_, byNameDefinition, args) =>
println("Got byNameDefinition")
args
case TypeRef(_, repeatedParamDefinition, args) =>
println("Got repeatedParamDefinition")
args
}
}


Scala Version: 2.11.4 (OpenJDK 64-Bit Server VM, Java 1.8.0_65)

Answer

When you use a pattern like TypeRef(_, byNameDefinition, args), byNameDefinition is a fresh variable, not a comparison with your existing val byNameDefinition. Because that variable isn't used, it's effectively the same as TypeRef(_, _, args). To avoid this, you need to surround it with backticks or to name it starting with a capital letter.

Comments