Search code examples
scalagenericsdottyscala-3

Intersection types with Covariance


Consider the below:

trait AA {
    def children: List[AA]
}

trait BB {
    def children: List[BB]
}

class CC extends AA, BB {
    override def children: List[AA] & List[BB] = ???
}

When we override children in CC, the overridden method is merged entity of the top-level methods. And hence the return type List[AA] & List[BB] makes sense.

What I don't understand is, how does the below compile?

class DD extends AA, BB {
    override def children: List[AA & BB] = ???
}

List is co-variant, hence (here is the source for proof):

List[AA & BB] <: List[AA] & List[BB]

DD can only compile if also List[AA] & List[BB] <: List[AA & BB]. Is it true? And if so, then isn't List[AA] & List[BB] =:= List[AA & BB]. Please suggest


It appears to me that List[AA & BB] =:= List[AA] & List[BB]. Consider this:

    val xx: List[AA & BB] = ???
    val yy: List[AA] & List[BB] = ???
    
    val z1: List[AA] & List[BB] = xx
    val z2: List[AA & BB] = yy

Solution

  • You write that for DD to compile, List[AA] & List[BB] must be a subtype of List[AA & BB]. I don't see why you think that, and you're in fact mistaken. Method return types are covariant, and hence it's the other way around: List[AA & BB] must be a subtype of List[AA] & List[BB]. And this is indeed the case, so the code is fine.