从 return 类型推断通用隐式参数的类型

Inferring type of generic implicit parameter from return type

假设我有一个像这样的简单 class

abstract class Foo {
  implicit val impInt: Int = 42
  def f[A]()(implicit a: A): A
  val f2: Int = f()
}

当声明 val f2 时,编译器能够推断出函数 f 的隐式参数类型是 Int 因为该类型与结果类型相同,并且结果类型需要匹配值的类型 f2,即 Int.

但是,将 Ordering[A] 加入组合:

def f[A]()(implicit a: A, m: Ordering[A]): A
val f2: Int = f()

导致此编译错误:

Ambiguous implicit values: both value StringCanBuildFrom in object Predef of type => scala.collection.generic.CanBuildFrom[String,Char,String] and method $conforms in object Predef of type [A]=> <:<[A,A] match expected type A

如果我在调用 f() 时添加类型信息,它会编译:

val f2: Int = f[Int]()

首先我遇到了隐式排序的情况,我认为这与 Scala 从左到右推断有关;我认为它无法先匹配 return 类型,然后 然后 推断 f 的(隐式)参数类型。但后来我在没有隐式排序的情况下尝试了这种情况,发现它有效 - 它推断 f 必须由 Int 参数化,因为 return 类型必须是 Int (因为 f2 是一个 Int)。

请注意,如果我们删除 implicit a: A 并仅保留 Ordering 隐式参数,错误仍然存​​在,但变为

Diverging implicit expansion for type Ordering[A] starting with method Tuple9 in object Ordering.

同样,添加类型参数使其变为 val f2: Int = f[Int]() 有帮助。

这是怎么回事?为什么编译器可以推断参数 A 必须是 Int,但不能推断参数 Ordering[A] 必须是 Ordering[Int]

排序实例的生成方式肯定有问题,因为下面的代码有效。我会报告错误。

case object types {
  implicit def buh[X]: List[X] = List()
}
abstract class Foo {

  import types._

  def f[A]()(implicit l: List[A]): A
  val f2: Int = f()
}