unsafe_variance
This type is unsafe: a type parameter occurs in a non-covariant position.
Description
#The analyzer produces this diagnostic when an instance member has a result type which is contravariant or invariant in a type parameter of the enclosing declaration. The result type of a variable is its type, and the result type of a getter or method is its return type. This lint warns against such members because they are likely to cause a failing type check at run time, with no static warning or error at the call site.
Example
#The following code produces this diagnostic because X
occurs as a parameter type in the type of f
, which is a contravariant occurrence of this type parameter:
class C<X> {
bool Function(X) f;
C(this.f);
}
This is unsafe: If c
has static type C<num>
and run-time type C<int>
then c.f
will throw. Hence, every invocation c.f(a)
will also throw, even in the case where a
has a correct type as an argument to c.f
.
Common fixes
#If the linted member is or can be private then you may be able to enforce that it is never accessed on any other receiver than this
. This is sufficient to ensure that that the run-time type error does not occur. For example:
class C<X> {
// NB: Ensure manually that `_f` is only accessed on `this`.
// ignore: unsafe_variance
bool Function(X) _f;
C(this._f);
// We can write a forwarding method to allow clients to call `_f`.
bool f(X x) => _f(x);
}
You can eliminate the unsafe variance by using a more general type for the linted member. In this case you may need to check the run-time type and perform a downcast at call sites.
class C<X> {
bool Function(Never) f;
C(this.f);
}
If c
has static type C<num>
then you may test the type. For example, c.f is bool Function(num)
. You may safely call it with an argument of type num
if it has that type.
You can also eliminate the unsafe variance by using a much more general type like Function
, which is essentially the type dynamic
for functions.
class C<X> {
Function f;
C(this.f);
}
This will make c.f(a)
dynamically safe: It will throw if and only if the argument a
does not have the type required by the function. This is better than the original version because it will not throw because of a mismatched static type. It only throws when it must throw for soundness reasons.
Unless stated otherwise, the documentation on this site reflects Dart 3.7.3. Page last updated on 2025-05-08. View source or report an issue.