Description
The Scala compiler resolves unbound method applications by searching for implicit conversions in companion objects along a type's linearization. Leveraging this you can create statically dispatched polymorphic methods by placing definitions in an implicit class in the companion object of each template in a hierarchy. You might rightly discourage such a design, but doing so allows for aggressive inlining and closure elimination in abstract interfaces without overly constraining implementations. It also lets you override methods with incompatible type signatures.
Scaladoc's new support for documenting implicits provides discoverability and clarity for such designs. Unfortunately, Scaladoc doesn't accurately reflect the compiler's interpretation of extension methods. The following code gives an example of this pattern and notes where Scaladoc misinterprets the definitions.
package nonvirtual
class A[X] { override def toString = "A" }
object A {
implicit class AOps[X](val __ : A[X]) extends AnyVal {
def f1(x: Int) = "A"
def f2(x: Int) = new A[X]
def f3[Y](x: Int) = new A[Y]
def f4[Y](f: X => Y) = "A"
}
}
class B[X] extends A[X] { override def toString = "B" }
object B {
implicit class BOps[X](val __ : B[X]) extends AnyVal {
// Scaladoc lists f1, f2, and f3 as shadowed in B rather than overriden
def f1(x: Int) = "B"
def f2(x: Int) = new B[X]
def f3[Y](x: Int) = new B[Y]
// Scaladoc redundantly lists AOps.f4 in B when only BOps.f4 should appear
def f4[Y](f: X => Y) = "B"
}
}
object Test extends App {
// no implicit resolution conflicts
val a = new A[String]
val b = new B[String]
println("a.f1: " + a.f1(0))
println("b.f1: " + b.f1(0))
println("a.f2: " + a.f2(0))
println("b.f2: " + b.f2(0))
println("a.f3: " + a.f3(0))
println("b.f3: " + b.f3(0))
println("a.f4: " + a.f4(identity))
println("b.f4: " + b.f4(identity))
}
The test routine has no ambiguities and statically resolves method implementations as you would expect:
a.f1: A
b.f1: B
a.f2: A
b.f2: B
a.f3: A
b.f3: B
a.f4: A
b.f4: B
I appreciate all the effort that's gone into making Scaladoc such a great tool. Keep up the good work!