Scala 在宏上下文中查找隐式方法定义

Scala 在宏上下文中查找隐式方法定义,scala,macros,scala-macros,Scala,Macros,Scala Macros,我了解Scala中宏的基本概念,但目前无法完成这项(简单?)工作: 查找编译器当前可见的所有隐式defs/vals,以从给定类型转换为另一种类型 我希望得到的是对象的列表,或者类似的东西。我已经玩过enclosuringimplicits,但总是得到一个空列表,不知道下一步该去哪里 要获取我要查找的列表,我需要做什么?上下文中只能有一个从A到B的隐式类型(或者您得到模糊隐式),因此如果您想找到它: import reflect.macros.Context, scala.language.e

我了解Scala中宏的基本概念,但目前无法完成这项(简单?)工作:

  • 查找编译器当前可见的所有隐式
    def
    s/
    val
    s,以从给定类型转换为另一种类型
我希望得到的是
对象的
列表
,或者类似的东西。我已经玩过
enclosuringimplicits
,但总是得到一个空列表,不知道下一步该去哪里


要获取我要查找的列表,我需要做什么?

上下文中只能有一个从
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>

无论如何,您必须分析一个列表,以获得您正在寻找的隐式信息,正如您可以从的源代码中看到的那样,它可能不是微不足道的,但至少有可能得到近似的结果,这可能适合您的需要。但是再次强调,最好非常非常小心地这样做,因为您使用的结构是可变的,方法也不是纯粹的。而且,正如@Eugene Burmako所注意到的,这个解决方案并没有从同伴对象中得到隐式信息。

我读到的问题是,源类型已经给出,而目标类型没有,在这种情况下,我认为没有好的解决方案。@Travis Brown在这种情况下,我甚至没有看到任何,除了编译器插件。我不认为Context.implicits包含整个隐式范围的内容。Iirc,在伴随对象中声明的隐式的查找是单独完成的。此外,信息本身可能非常好,但试图自己理解它可能非常困难,因为在编译器中有一个1.5kloc文件专门用于此目的。总而言之,你必须亲自实验看看这种黑客行为是否适用于你的用例,但一定要检查疯狂的情况,以确保你不会错过任何东西。此外,像这样的黑客行为的最大风险是它们肯定无法移植到scala.meta(或者,很可能,甚至根本无法在scala.meta中表达),因此,如果您计划将来与scala.meta兼容,这将是一个问题。最后,我不确定您是否可以在编译器插件中实现此逻辑。关于词法作用域(包括词法作用域的隐式)的信息仅在
typer
阶段可用,传统插件无法在那里注入。
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))
}
 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: