I ran into some strange situation in Scala today while I tried to refine the type bounds on an abstract type member.
I have two traits that define bounds on a type member and combine them in a concrete class. That works fine but when matching / casting with the trait combination only one of the two TypeBounds is "active" and I struggle to understand why ...
I tried to prepare an example:
trait L
trait R
trait Left {
type T <: L
def get: T
}
trait Right {
type T <: R
}
now if I combine these two traits in one concrete class
val concrete = new Left with Right {
override type T = L with R
override def get: T = new L with R {}
}
I can access my member via get as intended
// works fine
val x1: L with R = concrete.get
but if I cast to (Left with Right) or pattern match I cannot access the member anymore. Dependent on the order I get either the type bounds from Left or from Right but not the combination of both.
// can only access as R, L with R won't work
val x2: R = concrete.asInstanceOf[Left with Right].get
// can only access as L, L with R won' work
val x3: L = concrete.asInstanceOf[Right with Left].get
I understand that Left with Right is not the same thing as Right with Left but in both cases both type bounds are included, so why can I only get one to work?
can anyone shed some light on why this is happening?