在上下文中从A 到B 类型只能有一个隐式(或者你会得到模棱两可的隐式),所以如果你想找到它:
import reflect.macros.Context, scala.language.experimental.macros
def fImpl(c: Context): c.Expr[Unit] = {
import c.mirror._
println(c.inferImplicitValue(typeOf[Int]))
c.universe.reify( () )
}
def f = macro fImpl
scala> f
<empty>
scala> implicit val a = 5
a: Int = 5
scala> f
$line24.$read.$iw.$iw.$iw.$iw.a
scala> implicit val b = 5
b: Int = 5
scala> f //result will be empty, but error printed to the log
error: ambiguous implicit values:
both value a of type => Int
and value b of type => Int
match expected type Int
<empty>
寻找隐式方法:
def fImpl(c: Context): c.Expr[Unit] = {
import c.mirror._
println(c.inferImplicitValue(typeOf[String => Int]))
c.universe.reify( () )
}
def f = macro fImpl
scala> f
<empty>
scala> implicit def aaa(a: String) = 5
warning: there was one feature warning; re-run with -feature for details
aaa: (a: String)Int
scala> "A" : Int
res10: Int = 5
scala> f
{
((a: String) => $line47.$read.$iw.$iw.$iw.$iw.$iw.$iw.aaa(a))
}
如果silent参数为false(默认true),则在推理错误时会抛出TypecheckException。因此,您可以对其进行分析以找到模棱两可的隐含列表。
附:如果类型 B 未知 - 没有(记录的)方法可以使用宏查找所有隐式:openImplicits/enclosingImplicits 只是寻找在宏扩展的上下文中实现的隐式 - 并非全部,存在于语境。 Compiler-plugin 可能会有所帮助,但这并不容易。
如果您真的决定尝试“编译器插件”方式 - 查找隐含的逻辑已实现 here。 Here 您可以找到编译器的 Context(与宏的不同)及其 implicitss 字段,其中包含上下文中的所有隐式(但获得适当的上下文并不是那么简单)。
我不应该告诉你,但是从宏 Context 提升到编译器级别并做你想做的事有一个棘手且不安全的技巧:
scala> def fImpl(c: Context): c.Expr[Unit] = {
| val cc = c.asInstanceOf[reflect.macros.contexts.Context]
| println(cc.callsiteTyper.context.implicitss.flatten)
| c.universe.reify( () )
| }
fImpl: (c: reflect.macros.Context)c.Expr[Unit]
scala> def f = macro fImpl
scala> f //I've defined aaaaaaaa etc. implicits while playing with that
List(aaaaaaaa: ?, lllllllllllllllllllllzzzz: ?, lllllllllllllllllllll: ?, lllllllllllllllllllll: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, aaa: ?, b: ?, a: ?, macros: ?, RuntimeClassTag:
无论如何,您必须分析ImplicitInfo 的列表以获得您正在寻找的隐含,这可能不是微不足道的,正如您从Analizer 的来源中看到的那样,但至少有可能获得近似值结果,这可能适合您的需求。但同样,最好非常非常非常小心,因为您使用的结构是可变的,并且方法不是纯的。而且,正如@Eugene Burmako 所注意到的那样,这个解决方案并没有为您提供伴随对象的隐含。