Type boundaries unexpectedly change Scala priority of implicit parameter resolution

The Scala example below shows a situation where the required implicit parameter (of type TC[C] ) can be provided by both implicit scope methods and a and b . But there is no ambiguity at startup, 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 difference between the implicit methods a and b is the type boundaries, and both of them can correspond to TC[C] . If method b removed, then a will be implicitly allowed.

While I find this behavior convenient in practice, I would like to understand whether this is a given function of the language or just the complexity of the implementation.

Is there a language rule or principle by which the compiler selects b over a instead of treating them as equivalent and, therefore, ambiguous?

+4
source share
1 answer

There is a rule about this prioritization, which states that the most specific of the two matches will receive a higher priority. From the Scala Link , in section 6.26.3 "Overload Resolution":

The relative weight of alternative A over alternative B is a number from 0 to 2, defined as the sum

  • 1 if A has the value B, 0 otherwise and
  • 1 if A is defined in a class or object that is derived from a class or object defining B, 0 otherwise.

A class or object C is obtained 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 the class from which C. is deduced.
+3
source

All Articles