Consider following code in Scala:
object Test {
class A {}
class B extends A {}
class AI extends A {
def sayHello: String = "Hello from AI"
}
implicit def AtoAI(a: A): AI = a
class BI extends B {
def sayHello: String = "Hello from BI"
}
implicit def BtoBI(b: B): BI = b
def main(args: Array[String]) {
val a = new A
println(a.sayHello)
val b = new B
println(b.sayHello)
}
}
The use of implicits results in looping code. In fact, disassemblying reveals, that generated conversion methods have only a goto 0 inside:
public Test$AI AtoAI(Test$A);
Code:
0: goto 0
public Test$BI BtoBI(Test$B);
Code:
0: goto 0
What causes that behaviour? I understand, that a hierarchy of classes here is a suspect, but implicit conversion should be applied only once.
I use Scala 2.9.1
Not nice but I would definitely not call it a bug.
It boils down to
There is no need for the two sides of the conversion to be related in any way. The implicit is just the same thing as writing
because the compiler inserts the
aToBcall in order to convert the resultato the required return typeB.The
goto 0implementation is just a tail call optimization. The compiler might probably gives a warning when it generates a method that starts this way.Maybe there could be a rule that implicit methods are not available as implicits inside their own body. But it does not always create an infinite loop
(ok this is just a
map(toB)). Anyway the same could happen with two mutually recursive implicits. In my opinion, it’s not worthwhile to tweak the spec just to avoid some possibility to write an infinite, do nothing loop, among many others. But a warning when such a loop is detected, irrespective of implicits, would be nice.