【发布时间】:2019-09-12 09:40:35
【问题描述】:
我需要在给定位置搜索隐式值。我保留了类中先前宏调用的位置,如下所示:
class Delayed[+Kind[_[_]]](val sourceFilePath: String, val callSitePoint: Int) {
def find[F[_]]: Kind[F] = macro Impl.find[Kind, F]
}
前面的宏很简单:
def build[Kind[_[_]]](c: blackbox.Context): c.Expr[Delayed[Kind]] = {
import c.universe._
c.Expr(
q"""
new Delayed(${c.enclosingPosition.point}, ${c.enclosingPosition.source.path})
"""
)
}
有了这个位置,我需要做的就是启动隐式搜索吗?
def find[Kind[_[_]], F[_]](c: blackbox.Context)(implicit kindTag: c.WeakTypeTag[Kind[F]], fTag: c.WeakTypeTag[F[_]]): c.Expr[Kind[F]] = {
import c.universe._
reify {
val self = c.prefix.splice.asInstanceOf[Delayed[Kind]]
val sourceFile = AbstractFile.getFile(self.sourceFilePath)
val batchSourceFile = new BatchSourceFile(sourceFile, sourceFile.toCharArray)
val implicitSearchPosition = new OffsetPosition(batchSourceFile, self.callSitePoint).asInstanceOf[c.Position]
c.Expr[Kind[F]](c.inferImplicitValue(
appliedType(kindTag.tpe.typeConstructor, fTag.tpe.typeConstructor),
pos = implicitSearchPosition
)).splice
}
}
我使用 reify/splice 调用获得了职位,然后申请 inferImplicitValue。但是编译器抱怨隐式值的最后一个拼接:
the splice cannot be resolved statically,
which means there is a cross-stage evaluation involved
它要求我将编译器 jar 添加为依赖项,但这样做我只会得到另一个错误:
Macro expansion contains free term variable c defined by find in Delayed.scala
我知道,从概念上讲,reify 是在价值观的世界中。我不明白的是,在将宏生成的代码写入我的源代码之前,应该先解决隐式搜索。这是我能想到的让隐式搜索在宏上下文中工作的唯一方法。
我哪里错了?我确实理解编译器消息,但对我来说,在这个特定的上下文中没有任何意义。也许我不明白inferImplicitValue 的工作原理。
【问题讨论】:
标签: scala implicit scala-macros type-level-computation