将类型应用于宏中的类型构造函数会引发异常
Applying type to a type constructor in macro throws exception
考虑以下简单的宏片段:
val lstConstructor = weakTypeTag[List[String]].tpe.typeConstructor
println(c.typecheck(tq"$lstConstructor[String]", mode = c.TYPEmode))
这似乎是一段非常简单的代码失败,没有以下信息异常:
[error] scala.reflect.macros.TypecheckException: Any does not take type parameters
[error] at scala.reflect.macros.contexts.Typers.$anonfun$typecheck(Typers.scala:44)
[error] at scala.reflect.macros.contexts.Typers.$anonfun$typecheck(Typers.scala:38)
[error] at scala.reflect.macros.contexts.Typers.doTypecheck(Typers.scala:37)
[error] at scala.reflect.macros.contexts.Typers.typecheck(Typers.scala:51)
[error] at scala.reflect.macros.contexts.Typers.typecheck$(Typers.scala:32)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:18)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:18)
将类型参数应用到类型构造函数的正确方法是什么?
UPD:
手动将类型构造函数的硬编码名称指定为
println(c.typecheck(tq"List[String]", mode = c.TYPEmode))
工作得很好
欢迎来到无类型编译器胆量的无证之地。
准引用 tq"List[String]"
生成以下树:
AppliedTypeTree(Ident(TypeName("List")), List(Ident(TypeName("String"))))
请注意,第一个参数不是 Type
,而是 Ident
。所以你的准引号 tq"$lstConstructor[String]"
默默地用一个空 TypeTree()
:
替换了不恰当类型的树
AppliedTypeTree(TypeTree(), List(Ident(TypeName("String"))))
我很确定这等同于 Any
,所以你得到了错误。
现在,要从 Type
中得到一个 Ident
,您可以使用 .typeSymbol
方法(尽管 idents 没有类型参数信息,是否你之前是否做过 .typeConstructor
)。这应该有效:
c.typecheck(tq"${lstConstructor.typeSymbol}[String]", mode = c.TYPEmode)
Scastie 上的代码(使用运行时宇宙)here。
考虑以下简单的宏片段:
val lstConstructor = weakTypeTag[List[String]].tpe.typeConstructor
println(c.typecheck(tq"$lstConstructor[String]", mode = c.TYPEmode))
这似乎是一段非常简单的代码失败,没有以下信息异常:
[error] scala.reflect.macros.TypecheckException: Any does not take type parameters
[error] at scala.reflect.macros.contexts.Typers.$anonfun$typecheck(Typers.scala:44)
[error] at scala.reflect.macros.contexts.Typers.$anonfun$typecheck(Typers.scala:38)
[error] at scala.reflect.macros.contexts.Typers.doTypecheck(Typers.scala:37)
[error] at scala.reflect.macros.contexts.Typers.typecheck(Typers.scala:51)
[error] at scala.reflect.macros.contexts.Typers.typecheck$(Typers.scala:32)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:18)
[error] at scala.reflect.macros.contexts.Context.typecheck(Context.scala:18)
将类型参数应用到类型构造函数的正确方法是什么?
UPD:
手动将类型构造函数的硬编码名称指定为
println(c.typecheck(tq"List[String]", mode = c.TYPEmode))
工作得很好
欢迎来到无类型编译器胆量的无证之地。
准引用 tq"List[String]"
生成以下树:
AppliedTypeTree(Ident(TypeName("List")), List(Ident(TypeName("String"))))
请注意,第一个参数不是 Type
,而是 Ident
。所以你的准引号 tq"$lstConstructor[String]"
默默地用一个空 TypeTree()
:
AppliedTypeTree(TypeTree(), List(Ident(TypeName("String"))))
我很确定这等同于 Any
,所以你得到了错误。
现在,要从 Type
中得到一个 Ident
,您可以使用 .typeSymbol
方法(尽管 idents 没有类型参数信息,是否你之前是否做过 .typeConstructor
)。这应该有效:
c.typecheck(tq"${lstConstructor.typeSymbol}[String]", mode = c.TYPEmode)
Scastie 上的代码(使用运行时宇宙)here。