Search code examples
scalalinearization

Scala mixed traits assignment compatibility (hierarchy)


I have the following declarations of classes and traits

class C
class D extends C
trait T extends C
trait U extends D with T

and the following assignments:

val x1:C with T with U = new D with U
val x2:D with T = new C with U
val x3:D with T = new U
val x4:U = new D with T

The first assignment works, the others don't. I want to understand why for both cases.

As far as I understand it, the linearizations are as follows (-> means extends):

  • C with T with U: U -> D -> T -> C
  • D with U: U -> T -> D -> C
  • D with T: T -> D -> C
  • C with U: U -> T -> D -> C

I drew the type hierarchy to get more insight:

type hierarchy

My understanding is the following:

  • x1: works because the linearized types are the same (the order of D and T is not important for the type)
  • x2: does not work because ...?
  • x3: Does not work because traits cannot be instantiated
  • x4: Does not work because D with T is a supertype of U

Number 2 is where I'm stuck. It should work IMO because the linearization of D with T is D -> T -> C, which is a supertype of the linearization of C with U (which is U -> T -> D -> C).

Either my assumption that the order of mixed traits/classes is not important (but then why does the first assignment compile?) or my linearization is wrong or ???

Can you help me on this?


Solution

  • The problem is that new C with U is not valid; the type of val x2 is not relevant.

    The trait U extends D which means it can only be applied to a subclasses of D. Since C is not a subclass of D the trait cannot be applied to it.

    A trait that extends a class is similar to a self type, but with some subtle differences. See This answer for more information.