如何在Scala3宏中创建泛型类型的实例



我正在将一个宏从Scala 2移植到Scala 3。作为其工作的一部分,Scala2宏使用默认构造函数创建一个泛型类型的实例。在Scala2中使用准引号很简单,但我在Scala3宏中遇到了困难。这是我迄今为止最好的方法:

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

有没有更好的解决方案在运行时不进行下转换?

编辑:从Scala3.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

尽管您应该包括一个检查,看看您的构造函数是否没有参数。

最新更新