scala – 使用宏转换树后重新建立类型一致性的最佳方法是什么
发布时间:2020-12-16 18:16:42 所属栏目:安全 来源:网络整理
导读:我有以下宏: 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) = {
我有以下宏:
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,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的类型树.由于代码转换,它现在是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),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,q"Some($rhs)") 需要更改为此行: case ValDef(mods,TypeTree(),q"Some($rhs)") 将EmptyTree作为ValDef中的类型可能永远不会有意义.太糟糕了,编译器无法告诉我,本来可以节省48小时的兼职工作. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |