Assume the following declarations made into the Scala repl:
class Animal
class Bird extends Animal
class Chicken extends Bird
type SubType = t forSome { type t <: Bird }
type SuperType = t forSome { type t >: Bird }
As I expect, SubType is of a type that conforms to Bird. Since Animal is a superclass of Bird, a variable of type SubType cannot hold value of type Animal:
scala> val foo: SubType = new Animal
<console>:10: error: type mismatch;
found : Animal
required: SubType
val foo: SubType = new Animal
and yet this corollary is not as I expect:
scala> val foo: SuperType = new Chicken
foo: SuperType = Chicken@1fea8dbd
The assignment succeeds, and so do these:
scala> val foo: SuperType = 2
foo: SuperType = 2
scala> val foo: SuperType = "wtf?"
foo: SuperType = wtf?
scala>
Again, here's SuperType:
type SuperType = t forSome { type t >: Bird }
According to SLS 4.3,
A type declaration type t [tps ] >: L <: U declares t to be an abstract type with lower bound type L and upper bound type U.
So I'm declaring t to be an abstract type with lower bound Bird. Chicken is not a superclass of Bird, neither are String nor Int.
I thought that maybe it's because a Chicken is an Any and a SuperType can store an Any. But if I change the declaration of SuperType to this:
type SuperType = t forSome { type t >: Bird <: Animal}
to set an upper bound of Animal nothing seems to change.
Questions
First
How are my assignments of values of types Chicken Int and String to a SuperType variable allowed by existential clauses { type t >: Bird } and { type t >: Bird <: Animal}?
Second
What is the significance of the word "abstract" in the quoted specification that "A type declaration type t [tps ] >: L <: U declares t to be an abstract type..." What would the difference in meaning be if the word "abstract' were not there?