Reputation: 3838
The following is a simple example that tests the implicit feature of the scala 2.13 compiler:
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] {}
}
}
According this article:
Where does Scala look for implicits?
The companion object of the trait Handler
can be automatically imported as part of the implicit scope when type Handler[_]
is used, the outer object Sys1
should be irrelevant. This means handle1 should be visible and handle2 should be hidden.
But the following test case shows the exact opposite:
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
}
}
Considering that Handler is both a class & object name, the fact that handle1 doesn't work looks highly suspicious. Also, I've checked the full list of implicit import:
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 of the above can explain why handle2 is in the scope. What could be the reasons?
BTW: For those who dismissed implicit as a important scala feature: Implicit is the only way to implement type class, and if you want to implement it with minimal boilerplate, sometimes the above pattern can be the only choice.
Upvotes: 0
Views: 262
Reputation: 15086
Point 3 here explains that implicits/givens in prefixes of the type in question contribute to its implicit scope (in Scala 3 not if it's a package). So for the type Sys1.Handler[Long]
implicits in Sys1
are in the implicit scope because Sys1
is a non-package prefix.
handle1
is not in the implicit scope because object Handler
in object Sys1
is not the companion object of trait Handler
in trait System
.
Upvotes: 5