This compiles:
import scala.collection._
trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>
def bar: This = (this: SortedSetLike[A,This]).empty
}
But if the upcast is removed it fails to compile:
import scala.collection._
trait Foo[A, +This <: SortedSet[A] with SortedSetLike[A,This]]
extends SortedSetLike[A, This] { this: This =>
def bar: This = this.empty
}
Why? From the extends
clause we know that Foo
is a SortedSetLike[A, This]
, so the upcast is valid of course - but doesn't this show that the compiler has allowed conflicting inheritance to occur?
The SortedSetLike trait inherits the empty method from SetLike.
But SortedSet overrides the empty method and has an explicit return type:
Since you specify that This is a subclass of SortedSet the compiler will find SortedSet's implementation of empty first, which returns a SortedSet. The compiler does not know how to convert the resulting SortedSet to your This subclass.
But if you upcast to the SortedSetLike trait the compiler will find its empty method which returns a This.