如何在 Scala 3 宏中创建泛型类型的实例?
How to create an instance of a generic type in a Scala 3 macro?
我正在将一个宏从 Scala 2 移植到 Scala 3。作为其工作的一部分,Scala 2 宏使用默认构造函数创建泛型类型的实例。这在 Scala 2 中使用准引号很简单,但我正在努力使用 Scala 3 宏。这是我迄今为止最好的方法:
import scala.quoted.*
inline def make[A <: AnyRef]: A = ${ makeThat[A] }
private def makeThat[A <: AnyRef : Type](using Quotes): Expr[A] =
import quotes.reflect.*
'{ new A().asInstanceOf[A] }
没有 .asInstanceOf[A]
,编译器会发出一条错误消息:
[error] -- [E007] Type Mismatch Error: ...
[error] 17 | '{ new A() }
[error] | ^^^^^^^
[error] |Found: Object
[error] |Required: A
[error] |
[error] |where: A is a type in method makeThat with bounds <: AnyRef
[error] one error found
有没有运行时没有向下转型的更好的解决方案?
编辑: 从 Scala 3.0.1 开始,这甚至不再编译了。
您可以创建具有较低级别反映的正确树 API。
import scala.quoted.*
inline def make[A <: AnyRef]: A = ${ makeThat[A] }
def makeThat[A <: AnyRef : Type](using Quotes): Expr[A] =
import quotes.reflect.*
TypeRepr.of[A].classSymbol.map( sym =>
Apply(Select(New(TypeTree.of[A]), sym.primaryConstructor), Nil).asExprOf[A]
)
.getOrElse(???) // not a class, so can't instantiate
尽管您应该检查构造函数是否没有参数。
我正在将一个宏从 Scala 2 移植到 Scala 3。作为其工作的一部分,Scala 2 宏使用默认构造函数创建泛型类型的实例。这在 Scala 2 中使用准引号很简单,但我正在努力使用 Scala 3 宏。这是我迄今为止最好的方法:
import scala.quoted.*
inline def make[A <: AnyRef]: A = ${ makeThat[A] }
private def makeThat[A <: AnyRef : Type](using Quotes): Expr[A] =
import quotes.reflect.*
'{ new A().asInstanceOf[A] }
没有 .asInstanceOf[A]
,编译器会发出一条错误消息:
[error] -- [E007] Type Mismatch Error: ...
[error] 17 | '{ new A() }
[error] | ^^^^^^^
[error] |Found: Object
[error] |Required: A
[error] |
[error] |where: A is a type in method makeThat with bounds <: AnyRef
[error] one error found
有没有运行时没有向下转型的更好的解决方案?
编辑: 从 Scala 3.0.1 开始,这甚至不再编译了。
您可以创建具有较低级别反映的正确树 API。
import scala.quoted.*
inline def make[A <: AnyRef]: A = ${ makeThat[A] }
def makeThat[A <: AnyRef : Type](using Quotes): Expr[A] =
import quotes.reflect.*
TypeRepr.of[A].classSymbol.map( sym =>
Apply(Select(New(TypeTree.of[A]), sym.primaryConstructor), Nil).asExprOf[A]
)
.getOrElse(???) // not a class, so can't instantiate
尽管您应该检查构造函数是否没有参数。