从宏中检查代码类型时,是否可以检测到由该代码中的宏扩展引起的类型检查失败?

When typechecking code from within a macro, is it possible to detect a typecheck failure caused by a macro expansion within that code?

我想编写一个宏来编译它作为字符串文字接收的代码,并检测编译代码中由于宏扩展失败(宏被中止,或者扩展的宏)导致的类型检查错误类型检查失败)

我在想这样的事情:

def myMacro(c: Context)(codeStringLiteral: c.Expr[String]): c.Expr[Unit] = {
    val codeString = getString(codeStringLiteral) // this part is easy
    val ast = c.parse(code)
    val actualCode = util.Try(c.typecheck(ast)).recover{ case t: TypecheckException =>
      if(t.isMacroExpansionFailure) doOneThing
      else doOtherThing
    }
    c.Expr(actualCode.get)
}

这可能吗?

上下文

通过将宏扩展导致的故障推迟到运行时,这样的宏将使测试其他宏变得更加愉快,因此即使您的宏的测试用例被破坏,也可以执行整个测试套件。

当然,简单地将类型检查完全区分为运行时是很容易的,但是如果只区分由于您正在测试中编写的宏而导致的错误并且在编译时失败(如果它是测试),那将是非常好的代码本身有问题。

当然,不相关的宏可能会失败,但不太可能经常发生。

c.typecheck 有一个不起眼的标志,叫做 withMacrosDisabled。如果你在那里传递 true ,那应该会阻止任何宏被展开。现在您可以比较 c.typecheck(withMacrosDisabled = false)c.typecheck(withMacrosDisabled = true) 的状态并相应地调度。

这对白框宏不起作用,因为 withMacrosDisabled = false 可能会使使用白框宏的合法代码无法通过类型检查,但对于黑框宏,它应该或多或少没问题。