scalatypesstructural-typingcompound-type

structural type extending another structural type


Why the following is not allowed? (2.12):

type Foo <: {def foo(): Unit}
type Bar <: {def bar(): Unit} with Foo

Looks natural to me, Bar should have both foo() and bar().


Solution

  • type Foo <: {def foo(): Unit} is type Foo <: AnyRef{def foo(): Unit}.

    So while type Bar <: {def bar(): Unit} with Foo is not parsable, with AnyRef and different order it works

    type Foo <: {def foo(): Unit}
    type Bar <: Foo with AnyRef{def bar(): Unit}
    
    val b: Bar = ???
    b.foo()
    b.bar()
    

    Also with brackets (and direct order) it works

    type Foo <: {def foo(): Unit}
    type Bar <: ({def bar(): Unit}) with Foo 
    
    val b: Bar = ???
    b.foo()
    b.bar()
    

    Actually type Bar <: {def bar(): Unit} with Foo is against the spec while type Bar <: ({def bar(): Unit}) with Foo satisfies the spec because {def bar(): Unit} is not a SimpleType but ({def bar(): Unit}) is a SimpleType.

    CompoundType    ::=  AnnotType {‘with’ AnnotType} [Refinement]
                      |  Refinement
    
    AnnotType       ::=  SimpleType {Annotation}
    
    SimpleType      ::= ............
                      |  ‘(’ Types ‘)’
    
    Types           ::=  Type {‘,’ Type}
    
    Type            ::=  ...........
                      |  CompoundType
                      |  ...........
    

    https://scala-lang.org/files/archive/spec/2.13/03-types.html#compound-types