Reputation: 2250
So, implicit precedence is based on two factors: one is about the scope of declaration itself having precedence (scope A extending scope/trait B, or scope A being a companion object of a type extended from a type with scope B as its companion object). The other simply mentions that declaration A is more specific than declaration B. Now, when reading it for the first time I had several possible interpretations in mind, especially considering potential parameters (implicit and not) of implicit method and type parameters. Experience seemed to teach me that it means that the type of the returned value by declaration A, after all type inference/tapply, is a subtype of the return type of declaration B. So, this is fine:
class A
class B extends A
implicit val A = new A
implicit val B = new B
implicitly[A]
Why this doesn't compile, then?
implicit class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
implicit class B(i :Int) extends A(i)
1.!
When this does?
class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
class B(i :Int) extends A(i)
implicit val A = { i :Int => new A(i) }
implicit val B = { i :Int => new B(i) }
1.!
Is it another case of 'the compiler works in mysterious ways'?
Upvotes: 2
Views: 61
Reputation: 141635
Based on SIP-13 - IMPLICIT CLASSES proposal your declaration:
implicit class A(val toInt :Int) {
def ! = (1 /: (2 to toInt))(_ * _)
}
Will be transformed to something like:
class A(toInt: Int) {
...
}
implicit final def A(toInt: Int): A = new A(toInt);
And your B
in its turn will be transformed to something like:
class B(i: Int) extends A(i) {
...
}
implicit final def B(i: Int): B = new B(i);
So you are basically declaring 2 implicit conversion methods with the same parameters which are ambiguous. While the last one is not ambiguous due to already mentioned "most specific" rule for implicit parameters resolution.
Upvotes: 3