Ben Hutchison
Ben Hutchison

Reputation: 2481

Type bounds unexpectedly change precedence of Scala implicit parameter resolution

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

Answers (1)

Alex Yarmula
Alex Yarmula

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

Related Questions