类型检查后重写的类型树

Typetree rewritten after type checking

在维护用 Scala 2.10.x 编写的旧 Scala 代码时,当我尝试对 macros 中的 TypeTree 进行类型检查时,发生了意想不到的事情。看下面的代码,

annottees.map(_.tree).toList match {
  case q"$mods def $name[..$tpes](...$args) : $returnType = { ..$body }" :: Nil =>
    val isUnit = c.typeCheck(q"type T = $returnType; ()").children.head match {
      case TypeDef(_, _, _, tpt) => tpt.tpe =:= typeOf[Unit]
    }
    //... business logic

如您所见,我想做的很简单——尝试判断注释方法的 return 类型是否为 Unit。它达到了目的,但是我注意到有时 returnType 的 AST 被重写 returnType 确实是 Unit。例如,

returnType 的原始 AST 是,

Select(Ident(scala), newTypeName("Unit"))

isUnit之后,

Select(Ident(scala), scala.Unit)

因此, return Unit 的某些方法的宏扩展编译失败。

这是错误还是我应该预料到的?有办法绕过它吗?

好的,所以 AST 树确实是可变的。我想我需要传递 returnType 的副本以防止它被转换成其他东西。

annottees.map(_.tree).toList match {
  case q"$mods def $name[..$tpes](...$args) : $returnType = { ..$body }" :: Nil =>
    val isUnit = c.typeCheck(q"type T = ${returnType.duplicate}; ()").children.head match {
      case TypeDef(_, _, _, tpt) => tpt.tpe =:= typeOf[Unit]
    }
//... business logic