Contents

unsafe_variance

Contents

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:

dart
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:

dart
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:

dart
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:

analysis_options.yaml
yaml
linter:
  rules:
    - unsafe_variance