如何删除宏中所有推断的含义?

时间:2017-01-13 23:45:54

标签: scala implicit scala-macros

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

Symbol似乎有一个方法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)
}

然后再次进行类型检查并编译 但我担心这不可能......

1 个答案:

答案 0 :(得分:2)

他们有internal API来检测隐式提供的args,但它被评为不稳定。 (他们将使用树附件而不是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