在 scala 2.13 中,为什么伴随对象的隐式范围有时可能未对齐?如何纠正?

In scala 2.13, why implicit scope of a companion object may sometimes be misaligned? How to correct it?

下面是一个测试scala 2.13编译器隐式特性的简单例子:

object OverridingScope {

  trait System {

    trait Handler[T]
  }

  object Sys1 extends System {

    object Handler {

      implicit def handle1: Handler[Int] = new Handler[Int] {}
    }

    implicit def handle2: Handler[Long] = new Handler[Long] {}
  }
}

根据这篇文章:

Where does Scala look for implicits?

当使用类型 Handler[_] 时,特性 Handler 的伴随对象可以作为隐式范围的一部分自动导入,外部对象 Sys1 应该是无关紧要的。这意味着 handle1 应该可见而 handle2 应该隐藏。

但下面的测试用例恰恰相反:

class OverridingScope extends BaseSpec {

  import OverridingScope._

  it("implicits in companion is in scope") {

//    val hh = implicitly[Sys1.Handler[Int]]
    // Doesn't work
  }

  it("implicits in outer object is in scope") {

    val hh = implicitly[Sys1.Handler[Long]]
    // Should NOT work
  }
}

考虑到 Handler 既是 class 又是对象名称,handle1 不起作用这一事实看起来非常可疑。另外,我检查了隐式导入的完整列表:

First look in current scope
Implicits defined in current scope
Explicit imports
wildcard imports
Same scope in other files
Now look at associated types in
Companion objects of a type
Implicit scope of an argument's type (2.9.1)
Implicit scope of type arguments (2.8.0)
Outer objects for nested types
Other dimensions
上面的

None可以解释为什么handle2在范围内。可能是什么原因?

顺便说一句:对于那些将隐式视为一个重要的 Scala 特性的人:隐式是实现类型的唯一方法 class,如果你想用最少的样板来实现它,有时上面的模式可以是唯一的选择。

要点 3 here 解释了所讨论类型的前缀中的 implicits/givens 有助于其隐式作用域(在 Scala 3 中,如果它是一个包则不是)。因此对于类型 Sys1.Handler[Long] 隐含在 Sys1 中是在隐含范围内,因为 Sys1 是一个非包前缀。

handle1 不在隐式范围内,因为对象 Sys1 中的对象 Handler 不是特征 System 中特征 Handler 的伴随对象。