gpt4 book ai didi

scala - 使用宏转换树后重新建立类型一致性的最佳方法是什么

转载 作者:行者123 更新时间:2023-12-04 19:04:58 27 4
gpt4 key购买 nike

我有以下宏:

def testMacro[T](x: T): Option[T] = macro testMacroImpl[T]

def testMacroImpl[T: c.WeakTypeTag](c: Context)(x: c.Expr[T]): c.Expr[Option[T]] = {
import c.universe._
val newTree = x.tree match {
case Block(List(first), second) => {
val newFirst = first match {
case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")
}
Block(List(newFirst), second)
}
}
c.Expr[Option[T]](newTree)
}

基本上,这应该只是改变这个:
testMacro {
val aa = "hello"
aa
}

进入
{
val aa = Some("hello")
aa
}

但是,它失败并出现以下错误:
[error]  found   : String
[error] required: Option[String]
[error] val f = IdiomBracket.testMacro{
[error]
^

我的调查显示这是因为 它接收一个类型树,其标识符为 aa有类型 String .由于代码转换,现在是Option[String]类型但标识符的类型尚未更新。 我尝试创建一个新的(无类型的)标识符,这只会使错误如下:
[error]  found   : <notype>
[error] required: Option[String]
[error] val f = IdiomBracket.testMacro{
[error] ^

我曾尝试在将树发回之前对其进行类型检查,希望能填写正确的类型,但这似乎没有效果。

作为引用,这里是创建一个新 Ident 并进行类型检查的同一个宏,不幸的是它仍然不起作用。
def testMacroImpl[T: c.WeakTypeTag](c: Context)(x: c.Expr[T]): c.Expr[Option[T]] = {
import c.universe._
val newTree = x.tree match {
case Block(List(first), second) => {
val newFirst = first match {
case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")
}
val newSecond = second match {
case ident: Ident => Ident(ident.name)
}
Block(List(newFirst), newSecond)
}
}
c.Expr[Option[T]](c.typecheck(newTree))
}

最佳答案

这一行:

case ValDef(mods, name, _, rhs) => ValDef(mods, name, EmptyTree, q"Some($rhs)")

需要改为这一行:
case ValDef(mods, name, _, rhs) => ValDef(mods, name, TypeTree(), q"Some($rhs)")

将 EmptyTree 作为类型放在 ValDef 中可能永远没有意义。太糟糕了,编译器不能告诉我,本来可以为自己节省 48 小时的兼职工作。

关于scala - 使用宏转换树后重新建立类型一致性的最佳方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27608462/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com