如何删除宏中所有推断的隐式?

How to remove all inferred implicits in a macro?

我需要真的取消对我的宏发出的树的类型检查。这意味着不仅要删除推断类型等等,还要删除编译器推断的隐式参数。甚至 resetAllAttrs 似乎都没有解决这个问题。

Symbols 似乎有一个方法 isSynthetic 指示代码是否由编译器生成,但显然该标志仅针对自动生成的 getter 和 setter 之类的东西设置,而不是针对隐式值编译器插入。

我当然可以手动查找所有隐式参数列表并删除它们,但我也会删除那些由我的宏的用户明确提供的列表。

下面的代码非常理想

scala> def foo(a: Int)(implicit e: DummyImplicit) = a
foo: (a: Int)(implicit e: DummyImplicit)Int

scala> myMacro{ foo(4); foo(2)(DummyImplicit.dummyImplicit) }

myMacro 会发出树

{
  foo(4);
  foo(2)(Predef.this.DummyImplicit.dummyImplicit)
}

然后再次进行类型检查并编译。
但是这恐怕做不到...

他们有 internal API 来检测隐式提供的参数,但它被评论为不稳定。 (他们将使用树附件而不是 Apply 的子类型。)

$ scala
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_111).
Type in expressions for evaluation. Or try :help.

scala> import language.experimental.macros
import language.experimental.macros

scala> import reflect.macros.blackbox.Context
import reflect.macros.blackbox.Context

scala> def fImpl(c: Context)(block: c.Expr[Any]): c.Expr[Boolean] = c.Expr { import c._, universe._
     | val trees = universe.asInstanceOf[reflect.internal.Trees]
     | block.tree match {
     | case t@Apply(_,_) => Literal(Constant(t.isInstanceOf[trees.ApplyToImplicitArgs]))
     | case _ => Literal(Constant(false)) }}
fImpl: (c: scala.reflect.macros.blackbox.Context)(block: c.Expr[Any])c.Expr[Boolean]

scala> def f(block: Any): Boolean = macro fImpl
defined term macro f: (block: Any)Boolean

scala> def g(implicit d: DummyImplicit) = 42
g: (implicit d: DummyImplicit)Int

scala> f(println(""))
res0: Boolean = false

scala> f(g)
res1: Boolean = true

scala> f(g(new DummyImplicit))
res2: Boolean = false