I'm a bit perplexed by the strictness of the typechecker below — it seems that the invariant T
position of Inv[T]
is also invariant within Variantish
's parameter list:
scala> class Inv[T]
defined class Inv
scala> class Variantish[+T, +TVar <: Inv[T]]
<console>:12: error: covariant type T occurs in invariant position in type <: Inv[T] of type TVar
class Variantish[+T, +TVar <: Inv[T]]
^
Variant types can normally occur in what look like invariant argument-list positions legally, e.g. with object-protected visibility:
class Variantish[+T](protected[this] var v: Inv[T])
and it seems that the following would be just as typesafe:
class Variantish[+T, +TVar <: Inv[T]](protected[this] var v: TVar)
Need that check mentioned above be so strict?
From the language specification (emphasis mine), about conformance (ie T'
is a super-type of T
):
Type constructors
T
andT′
follow a similar discipline. We characterizeT
andT′
by their type parameter clauses[a1,…,an]
and[a′1,…,a′n]
, where anai
ora′i
may include a variance annotation, a higher-order type parameter clause, and bounds. Then,T
conforms toT′
if any list[t1,…,tn]
-- with declared variances, bounds and higher-order type parameter clauses -- of valid type arguments forT′
is also a valid list of type arguments forT
andT[t1,…,tn]<:T′[t1,…,tn]
.
This is really difficult to understand (IMHO), but I believe it means that for Variantish
to be covariant in T
, you would have to be able to write
Variantish[Dog, TVar] <: Variantish[Animal, TVar]
for any TVar
for which Variantish[Animal, TVar]
makes sense. But this doesn't even make sense (let alone have any truth value) for some of those TVar
, such as Inv[Animal]
. That's why it is forbidden in that place.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With