First I want to say that Scala 3 is turning out to be a very nice language and I’m excited for what we can do with it. Thank you.
I am in the process of trying to get Breeze compiling under Scala 3. There is a common pattern in Breeze in how I organize implicits, where for a class XVector I have a trait XVectorOps with a bunch of implicits in it that object XVector extends. Usually these are stacked a bit. In Scala 2 this all worked fine, but in Scala 3, this leads to problems in the case where there is a subtype relationship between different XVectors.
This is a minimized example that compiles fine in Scala 2 but does not work in Scala 3:
trait Op[T, U]
trait HasOps[+This] {
def foo[TT>:This, U](u: U)(implicit op: Op[TT, U]) = op
}
trait Vector extends HasOps[Vector]
class DenseVector extends Vector with HasOps[DenseVector]
trait VectorOps {
implicit def vOp: Op[Vector, Double] = ???
}
object Vector extends VectorOps
trait DenseVectorOps {
implicit def dvOp: Op[DenseVector, Double] = ???
}
object DenseVector extends DenseVectorOps
object Foo {
def bar() = {
val dv = new DenseVector
dv.foo(3.0)
}
}
If I inline the Ops into DenseVector etc, this works fine, but otherwise I get an ambiguous implicit error:
26 | dv.foo(3.0)
| ^
|ambiguous implicit arguments: both method dvOp in trait DenseVectorOps and method vOp in trait VectorOps match type Op[TT, Double] of parameter op of method foo in trait HasOps
Is this intentional? It’s going to make it a lot harder to organize implicits. I’m using RC2