unrelated-type-equality-checks

Same as unrelated_type_equality_checks in Dart lints

Path
lint/correctness/unrelated-type-equality-checks
Default
On (recommended)
Origin
Dart lints
Rule
478 of 512
recommended

Reports ==/!= comparisons and relational ==/!= patterns whose operand types are unrelated.

Relatedness is the linter's typesAreUnrelated (TypeRelation::RuntimeUnrelatedTo), with one exemption: a package:fixnum Int32/Int64 on the left of an int is comparable. Comparisons with a null literal operand are skipped.

Invalid

example.dartdart
class Alpha {}
class Beta {}

int makeNumber() => 1;

void bad(
  int number,
  String text,
  Alpha alpha,
  Beta beta,
  String value,
  List<int> ints,
  List<String> strings,
  (int,) intRecord,
  (String,) stringRecord,
) {
  number == text;
  text != true;
  alpha == beta;
  makeNumber() == text;
  ints == strings;
  intRecord == stringRecord;
  if (value case == 1) {
    print(value);
  }
}

void scopedEquality(int number) {
  (() {
    final text = 'x';
    number == text;
  })();
  for (final text in <String>['x']) {
    number == text;
  }
  number == 1;
}

class TypedBox {
  TypedBox(this.value);
  final int value;
}

void patternBindings(
  (int,) record,
  List<int> list,
  Map<String, int> map,
  TypedBox box,
) {
  if (record case (var item,)) {
    item == 'x';
  }
  if (list case [var item]) {
    item == 'x';
  }
  if (map case {'x': var item}) {
    item == 'x';
  }
  if (box case TypedBox(value: var item)) {
    item == 'x';
  }
}

abstract mixin class Equatable {
  const Equatable();
}

class Plain {}

class Equal extends Equatable {
  const Equal();
}

enum Color { red }

enum Shape { circle }

mixin Tagged {}

class Callable {
  int call() => 1;
}

void hierarchy(
  Equal equal,
  Plain plain,
  Color color,
  Shape shape,
  Tagged tagged,
  int Function() function,
  String text,
  int number,
  List<int> ints,
  Iterable<String> strings,
  String Function(String) stringFunction,
) {
  equal == plain;
  color == shape;
  tagged == plain;
  function == text;
  text == (1,);
  ints == strings;
  if (number case != null) {}
}
Equality checks should compare related types.
16) {
17 number == text;
Equality checks should compare related types.
17 number == text;
18 text != true;
Equality checks should compare related types.
18 text != true;
19 alpha == beta;
Equality checks should compare related types.
19 alpha == beta;
20 makeNumber() == text;
Equality checks should compare related types.
20 makeNumber() == text;
21 ints == strings;
Equality checks should compare related types.
21 ints == strings;
22 intRecord == stringRecord;
Equality checks should compare related types.
22 intRecord == stringRecord;
23 if (value case == 1) {
Equality checks should compare related types.
30 final text = 'x';
31 number == text;
Equality checks should compare related types.
33 for (final text in <String>['x']) {
34 number == text;
Equality checks should compare related types.
50 if (record case (var item,)) {
51 item == 'x';
Equality checks should compare related types.
53 if (list case [var item]) {
54 item == 'x';
Equality checks should compare related types.
56 if (map case {'x': var item}) {
57 item == 'x';
Equality checks should compare related types.
59 if (box case TypedBox(value: var item)) {
60 item == 'x';
Equality checks should compare related types.
96) {
97 equal == plain;
Equality checks should compare related types.
97 equal == plain;
98 color == shape;
Equality checks should compare related types.
98 color == shape;
99 tagged == plain;
Equality checks should compare related types.
99 tagged == plain;
100 function == text;
Equality checks should compare related types.
100 function == text;
101 text == (1,);
Equality checks should compare related types.
101 text == (1,);
102 ints == strings;
Equality checks should compare related types.
102 ints == strings;
103 if (number case != null) {}

Valid

example.dartdart
class Base {}
class Child extends Base {}

void good(
  int integer,
  double decimal,
  num number,
  String? nullableText,
  dynamic anything,
  Base base,
  Child child,
  Never bottom,
  List<int> values,
  List<int>? nullableValues,
) {
  integer == decimal;
  decimal != number;
  nullableText == null;
  anything == integer;
  base == child;
  bottom == 'text';
  values == nullableValues;
  if (nullableText case == null) {
    print(nullableText);
  }
}

class Sibling extends Base {}

class Box<T> {}

class Callable {
  int call() => 1;
}

void related(
  Child child,
  Sibling sibling,
  int Function(int) intFunction,
  String Function(String) stringFunction,
  int Function() function,
  Callable callable,
  Function anyFunction,
  Comparable<num> comparable,
  int integer,
  String text,
  Pattern pattern,
  (int,) record,
  Record anyRecord,
  Box<int> ints,
  Box<num> numbers,
) {
  child == sibling;
  intFunction == stringFunction;
  function == callable;
  function == anyFunction;
  integer == comparable;
  text == pattern;
  record == anyRecord;
  ints == numbers;
}

void typeParameters<T, N extends num>(T value, N number, String text) {
  value == text;
  number == text;
}

Configure unrelated-type-equality-checks

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "unrelated-type-equality-checks": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/unrelated-type-equality-checks: <reason>
  • unused-codecheck-unused-codecross-file

    Report public top-level declarations that nothing references.

  • unused-dependenciescross-file

    Report regular pubspec dependencies with no Dart import or export in the analyzed package.

  • unused-filescheck-unused-filescross-file

    Report lib/ files that no project entrypoint can reach.

  • use-build-context-synchronouslyuse_build_context_synchronouslyrecommendedflutter

    Flags BuildContext use after an asynchronous gap without a mounted guard.

  • use-closest-build-contextrecommendedflutter

    Use the nearest BuildContext parameter inside nested callbacks.

  • use-key-in-widget-constructorsuse_key_in_widget_constructorsrecommendedflutter

    Require public widget constructors to accept or initialize a Flutter Key.

  • use-once-constructors-once-provideruse_once_constructors_once_providerflutter

    Require Riverpod once-providers to be created through .once().

  • use-ref-and-state-synchronouslyrecommendedriverpod

    Flags notifier ref and state accesses after an async gap without ref.mounted.