问题描述
implicit def materializeHelper[C <: Any]: Helper[C] = macro materializeHelperImpl[C]
def materializeHelperImpl[C <: Any: ctx.WeakTypeTag](ctx: blackBox.Context): ctx.Expr[Helper[C]] = ???
根据它的签名,它将为任何C体现一个Helper[C]
。但是,身体更具挑剔性。它仅接受C
个密封特征。
宏应该返回什么来告诉编译器“忘记我的结果,继续进行隐式搜索,就像我不存在一样?”
当前,我正在返回一个空块(q""
),这是不理想的,因为当所述隐式用作中间规则时,编译器会实现null
。例如,在下面的行中,当宏返回空(helper
)时,q""
参数设置为null。
implicit def parser[C <: Any](implicit helper: Helper[C]): Parser[C] = new Parser[C](helper)
我的目的是,在C
不是密封特征的情况下,编译器将丢弃前面提到的两个隐式值,并继续搜索另一个更具体的隐式值。
解决方法
您没有将宏实现类型类Helper
设置为白盒。
通常隐式宏应该是白盒。
如果黑盒宏(甚至是隐式黑盒宏)抛出异常 那么它将在编译主代码时出现编译错误。如果一个 whitebox隐式宏会在编译过程中引发异常 主代码中的隐式代码将从候选者中静默删除。
Implicit macro. Default implicit value. How?
https://docs.scala-lang.org/overviews/macros/blackbox-whitebox.html
使用自定义错误消息调用c.abort
更为习惯。抛出异常,调用c.error
,然后返回EmptyTree
(在这种情况下,只是不进行类型检查)也是可能的,尽管它们看起来不那么习惯(最好有清晰的编译错误消息)。 / p>