Open tribbloid opened 20 hours ago
Hi @tribbloid,
This is actually the correct behavior. Since Scala is subject to the erasure of type parameters, we don't have enough information at runtime to be able to execute val tt = Type.of[T](using qt)
or compute anything related to T
. To be able to use any information on the type parameter at runtime, you should include a witness (using Type[T])
(or using the following syntax [T: Type]
) that describe the type parameter T
.
To fix the provided snippet, here is the change to do:
import scala.quoted.{Expr, Quotes, Type}
case class Thing[T](vs: List[String])
def deserialize[T: Type](expr: Expr[List[String]])(using Quotes): Expr[Thing[T]] = {
'{ Thing[T]($expr) }
}
I'm keeping the ticket open to see if we might benefit from a better error reporting
@hamzaremmal I doubt if it could be that simple, everything defined in the example is indeed compile-time only.
But you are right it is not revealing enough, may I suggest a better example?
comparing the following 2 cases:
(error)
object Demo1 {
object TASTyLowering {
def deserialize[T](expr: Expr[List[String]])(
using
qt: Quotes,
tt: Type[T]
): Expr[Thing[T]] = {
'{ Thing[T]($expr) }
}
}
def deserialize[T](expr: Expr[List[String]])(
using
Quotes
): Expr[Thing[T]] = {
TASTyLowering.deserialize(expr)
}
}
(success)
object Demo2 {
object TASTyLowering {
def deserialize[T](expr: Expr[List[String]])(
using
qt: Quotes,
tt: Type[T]
): Expr[T] = {
'{ ($expr).asInstanceOf[T] }
}
}
def deserialize[T](expr: Expr[List[String]])(
using
Quotes
): Expr[T] = {
TASTyLowering.deserialize(expr)
}
}
The successful case only differs in return type of the Expr
, yet Type can be summoned from Quotes using given Type.of
, how did this happen?
Compiler version
3.5.1
Minimized code
Output
the signature of
Type.of[T]
is:so clearly something is wrong here
Expectation
both summoning should succeed