在 reify 调用中搜索隐式(scala 宏)

Searching for implicit inside a reify call (scala macro)

我需要在给定位置搜索隐式值。我在 class 中保留了先前宏调用的位置,如下所示:

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

我理解具体化在概念上属于价值观的世界。我不明白的是,在将宏生成的代码写入我的源代码之前,应该解决隐式搜索。这是我能想到的使隐式搜索在宏上下文中工作的唯一方法。

我哪里错了?我确实理解编译器消息,但对我来说,在这个特定的上下文中它没有任何意义。也许我不明白 inferImplicitValue 是如何工作的。

尝试Context#eval(expr)

def find[Kind[_[_]], F[_]](c: blackbox.Context)(implicit kindTag: c.WeakTypeTag[Kind[F]], fTag: c.WeakTypeTag[F[_]]): c.Expr[Kind[F]] = {
  import c.universe._

  val self = c.eval(c.Expr[Delayed[Kind]](c.untypecheck(c.prefix.tree.duplicate)))
  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
  ))
}