Description
We have discussed adding declaration site variance as a non-breaking feature in which type parameters to classes may be marked as out
(statically checked covariant), in
(statically checked contravariant), or inout
(statically checked invariant). In order to make the change non-breaking, unmarked type variables would continue to be treated as runtime checked covariant. This issue is to discuss whether or not we should also add an explicit marker for runtime checked covariant classes.
Syntax
An initial proposed syntax for the marker is covariant
to match the existing covariant
marker on term level parameters. Example:
class C<covariant T, inout S> {
S f1(S x) => x; // Valid because S is invariant
T f2(T x) => x; // Valid because T is covariant
}
Semantics
A type parameter marked with this modifier would be treated as runtime checked covariant exactly as if no modifier were on the type parameter. That is, for the language, class A<T> ...
and class A<covariant T> ...
would be treated equivalently. Example:
class A<covariant T, S> {
S f1(S x) => x; // Valid because S is runtime checked covariant, runtime check inserted on argument
T f2(T x) => x; // Valid because T is runtime checked covariant, runtime check inserted on argument
}
Motivation
There are several motivations behind this proposal.
The first is that some set of our users will very likely prefer to always use statically checked variance, and will prefer that any runtime checked classes be marked explicitly covariant
. This enables such marking, with a lint to prevent unmarked type parameters from being introduced.
The second is that it gives us a potential path forward towards changing the default behavior. If we eventual reach a point where the majority of code uses explicit covariant
, we could then choose to make inout
or out
the default in a language versioned breaking change.
Discussion
Since this has no semantic significance in the proposal, the same effect in the short term could be achieved with an annotation associated with a lint. This doesn't provide any organic migration path however.
cc @eernstg @lrhn @munificent @natebosch @jakemac53 @stereotype441