メインコンテンツにスキップ

unsafe_variance

実験的

unsafe_type: 型変数が共変でない位置に含まれています。

詳細

#

囲んでいるクラス、ミックスイン、または列挙型の型パラメーターを共変でない位置に持つインスタンス変数は、型チェックの失敗による実行時エラーの原因となる可能性があります。たとえば、class C<X> {...} では、void Function(X) myVariable; の形式のインスタンス変数は、このような実行時エラーの原因となる可能性があります。

囲んでいる宣言の型パラメーターの共変でない出現を戻り値の型に持つゲッターまたはメソッドについても同様です。

このリンターはこの種のメンバー宣言をフラグします。

悪い例

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.
}

問題は、Xfun の型のパラメーター型として出現することです。

実行時型エラーの可能性を減らす 1 つの方法は、共変でないメンバー funのみ this で使用されることを保証することです。これを厳密に強制することはできませんが、プライベートにし、転送メソッド 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.
}

完全に安全なアプローチには、Dart にまだない機能、つまり静的にチェックされた共変性が必要です。それがあれば、型パラメーター X が不変 (inout X) であると指定できます。

静的にチェックされた共変性のサポートなしで不変性をエミュレートすることは可能です。これにより、サブタイプの作成にいくつかの制限が課せられますが、inout が提供する型指定を忠実に提供します。

良い例

dart
typedef Inv<X> = X Function(X);
typedef C<X> = _C<X, Inv<X>>;

class _C<X, Invariance extends Inv<X>> {
  // ignore: unsafe_variance
  final bool Function(X) fun; // Safe!
  _C(this.fun);
}

void main() {
  C<int> c = C<int>((i) => i.isEven);
  c.fun(10); // Succeeds.
}

このアプローチでは、C<int>C<num> のサブタイプではないため、c は異なる宣言済み型を持つ必要があります。

別の可能性は、変数が安全だがより一般的な型を持つように宣言することです。その場合、変数自体を使用するのは安全ですが、すべての呼び出しは実行時にチェックする必要があります。

HONEST

dart
class C<X> {
  final bool Function(Never) fun;
  C(this.fun);
}

void main() {
  C<num> c = C<int>((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.
}

有効にする

#

unsafe_variance ルールを有効にするには、analysis_options.yaml ファイルの linter > rules の下に unsafe_variance を追加します。

analysis_options.yaml
yaml
linter:
  rules:
    - unsafe_variance

代わりに、YAML マップ構文を使用してリンター ルールを構成している場合は、linter > rules の下に unsafe_variance: true を追加します。

analysis_options.yaml
yaml
linter:
  rules:
    unsafe_variance: true