Search code examples
scalaparent-childtype-systems

How to restrict in Scala the actually valid types of the constructor parameter by a trait in a parent-child hierarchy?


Given the following code:

sealed abstract class Foobar[+Parent <: Foobar[Parent]](parent: Option[Parent])

trait Foo[+Parent <: Foobar[Parent]] extends Foobar[Parent]

class Bar[+Parent <: Foobar[Parent]](val parent: Foo[Parent]) extends Foobar(Some(parent))

The Scala Worksheet of Scala-SDK Version 3.0.2-vfinal-20131028-1923-Typesafe complains about the following:

Multiple markers at this line
- inferred type arguments [scrap.Foo[Parent]] do not conform to class Foobar's type parameter bounds [+Parent <: scrap.Foobar[Parent]]
- illegal inheritance;  self-type scrap.Bar[Parent] does not conform to scrap.Foobar[Parent]'s selftype scrap.Foobar[Parent]
- type mismatch;  found   : parent.type (with underlying type scrap.Foo[Parent])  required: Parent
- inferred type arguments [scrap.Foo[Parent]] do not conform to class Foobar's type parameter bounds [+Parent <: scrap.Foobar[Parent]]
- type mismatch;  found   : Some[scrap.Foo[Parent(in class Bar)]]  required: Option[Parent(in class Foobar)]
- illegal inheritance;  self-type scrap.Bar[Parent] does not conform to scrap.Foobar[Parent]'s selftype scrap.Foobar[Parent]
- type mismatch;  found   : Some[scrap.Foo[Parent(in class Bar)]]  required: Option[Parent(in class Foobar)]
- type mismatch;  found   : parent.type (with underlying type scrap.Foo[Parent])  required: Parent

How to solve this inheritance issue in Scala's type system?


Solution

  • Your last line is inferring the following full signature:

    class Bar[+Parent <: Foobar[Parent]](val parent: Foo[Parent]) 
      extends Foobar[Foo[Parent]](Some(parent))
    

    And the error becomes clearer:

    type arguments    [Foo[Parent]] do not conform to class Foobar's type
     parameter bounds [+Parent <: Foobar[Parent]]
    

    This would only be satisfied with

    trait Foo[+Parent <: Foobar[Parent]] extends Foobar[Foo[Parent]]