为什么隐式对象在 Scala 2.13-M5 中优先于 val?

Why implicit object has precedence over val in Scala 2.13-M5?

我想知道这是 Scala 2.13-M5 中的错误还是预期行为。

以下代码片段编译并输出 "object in package object":

package object test {
  implicit val a: TS = new TS("val in package object")
  implicit object b extends TS("object in package object")
}

package test {
  class TS(override val toString: String)

  class Inner {
    implicit val f: TS = new TS("val in inner class")
    val resolve = implicitly[TS]
  }
  object Test extends App {
    println(new Inner().resolve)
  }
}

由于注释掉了第三行 implicit object b extends TS("object in package object" 存在一个不明确的隐式编译错误,这也是我在第一种情况下所期望的:

Error:(11, 29) ambiguous implicit values:
 both value a in package test of type => test.TS
 and value f in class Inner of type => test.TS
 match expected type test.TS
    val resolve = implicitly[TS]

在您的示例中,abf 似乎都是符合条件的隐式值。正如 FAQ 所说(强调我的):

[...] this entails selecting a narrower type or a value defined in a subclass relative to other eligible values

因此,对象 b 被选中,因为 b.typeTS 的严格子类型。


这是另一个演示相同行为但没有包或对象的示例:

case class TS(str: String)

object test {
  implicit val a: TS = new TS("val in package object")
  // implicit object b extends TS("object in package object")
  class MoreSpecial() extends TS("I'm special")
  implicit val s: MoreSpecial = new MoreSpecial()

  class TS(override val toString: String)

  class Inner {
    implicit val f: TS = new TS("val in inner class")
    val resolve = implicitly[TS]
  }
  object Test {
    def run(): Unit = {
      println(new Inner().resolve)
    }
  }
}

test.Test.run()

它会打印 "I'm special",因为 class MoreSpecial 的实例认为它是最具体的,仅仅因为它的类型 MoreSpecialMoreSpecial 的严格子类型TS.

此外,

  • 如果您取消注释 b 行,它会给出不明确的隐式错误(b: b.type <: TSs: MoreSpecial <: TS 冲突)
  • 如果您注释 s 行,它还会给出模糊的隐式错误(a: TSf: TS 冲突)
  • only if ((s is commented) XOR (b is commented)), then it compiles (both b: b.type and s: MoreSpecial win over a: TSf: TS)

这一切都符合预期。这适用于 2.12.6,因此它似乎并不特定于 2.13-Mx。