unsafe_variance
Unsafe type: Has a type variable in a non-covariant position.
This rule is currently experimental and not yet available in a stable SDK.
Details
#Don't declare non-covariant members.
An instance variable whose type contains a type parameter of the enclosing class, mixin, or enum in a non-covariant position is likely to cause run-time failures due to failing type checks. For example, in class C<X> {...}
, an instance variable of the form void Function(X) myVariable;
may cause this kind of run-time failure.
The same is true for a getter or method whose return type has a non-covariant occurrence of a type parameter of the enclosing declaration.
This lint flags this kind of member declaration.
BAD:
class C<X> {
final bool Function(X) fun; // LINT
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Throws.
}
The problem is that X
occurs as a parameter type in the type of fun
. A better approach is to ensure that the non-covariant member fun
is only used on this
. We cannot strictly enforce this, but we can make it private and add a forwarding method fun
:
BETTER:
class C<X> {
// ignore: unsafe_variance
final bool Function(X) _fun;
bool fun(X x) => _fun(x);
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
c.fun(10); // Succeeds.
}
A fully safe approach requires a feature that Dart does not yet have, namely statically checked variance. With that, we could specify that the type parameter X
is invariant (inout X
).
Another possibility is to declare the variable to have a safe but more general type. It is then safe to use the variable itself, but every invocation will have to be checked at run time:
HONEST:
class C<X> {
final bool Function(Never) fun;
C(this.fun);
}
void main() {
C<num> c = C<int>((i) => i.isEven);
var cfun = c.fun; // Local variable, enables promotion.
if (cfun is bool Function(int)) cfun(10); // Succeeds.
if (cfun is bool Function(bool)) cfun(true); // Not called.
}
Usage
#To enable the unsafe_variance
rule, add unsafe_variance
under linter > rules in your analysis_options.yaml
file:
linter:
rules:
- unsafe_variance
Unless stated otherwise, the documentation on this site reflects Dart 3.6.0. Page last updated on 2024-07-03. View source or report an issue.