Reputation: 2481
The Scala example below shows a situation where a required implicit parameter (of type TC[C]
) can be provided by both implicit methods in scope, a
and b
. But when run, no ambiguity results, and it prints "B".
object Example extends App{
trait A
trait B extends A
class C extends B
class TC[X](val label: String)
implicit def a[T <: A]: TC[T] = new TC[T]("A")
implicit def b[T <: B]: TC[T] = new TC[T]("B")
println(implicitly[TC[C]].label)
}
Note that the only different between implicit methods a
and b
are the type bounds, and both of them can match TC[C]
. If the method b
is removed, then a
is implicitly resolved instead.
While I find this behaviour convenient in practice, I'd like to understand whether it is a specified language feature, or just an implementation quirk.
Is there a language rule or principle by which the compiler prioritizes b
over a
, rather than viewing them as equivalent and thus ambiguous options?
Upvotes: 4
Views: 147
Reputation: 10677
There is a rule about this prioritization, which says that the most specific out of the two matches will get a higher priority. From Scala Reference, under 6.26.3 'Overloading Resolution':
The relative weight of an alternative A over an alternative B is a number from 0 to 2, defined as the sum of
- 1 if A is as specific as B, 0 otherwise, and
- 1 if A is defined in a class or object which is derived from the class or object defining B, 0 otherwise.
A class or object C is derived from a class or object D if one of the following holds:
- C is a subclass of D, or
- C is a companion object of a class derived from D, or
- D is a companion object of a class from which C is derived.
Upvotes: 3