Francis Toth
Francis Toth

Reputation: 1685

Why Scala's compiler is not able to use an implicit conversion of an inherited type?

I am currently digging in the implicit topic, and got myself stuck with this case :

class A
class B extends A

object A { implicit def b2String(b: B): String = "B" }
object B { implicit def a2String(a: A): String = "A" }

val s: String = new B // This does not compile

I know this is a bit of an edge case, but I wanted to understand it. Shouldn't the compiler pick A's implicit (b2String) ? Or does (as it seems) it stuck to the most specific type's companion object (B) ? Does that mean inherited type's companion object implicits are not inherited ?

Thank you in advance.

EDIT : If A's companion object is deleted, then it compiles and the value of s is "A". So the compiler is able to figure out than an implicit valid for A is also valid for B.

EDIT : If I do the following changes, this also compiles :

  class A
  class B extends A

  object A { implicit def b2String(b: B): Int = 1 }
  object B { implicit def a2String(a: A): String = "A" }

  val s: String = new B
  val i: Int = new B

So companion objects implicits are inherited.

Upvotes: 0

Views: 117

Answers (1)

Alexey Romanov
Alexey Romanov

Reputation: 170815

It doesn't compile because there are two available implicits, and by rules in http://scala-lang.org/files/archive/spec/2.11/06-expressions.html#overloading-resolution, they have equal relative weight: b2String gets 1 over a2String because it's in the companion object of the derived class, and a2String gets 1 over b2String because it's more specific.

Upvotes: 2

Related Questions