no-self-comparisons

Same as no_self_comparisons in Pyramid Lint

Path
lint/suspicious/no-self-comparisons
Default
On (recommended)
Origin
Pyramid Lint
Rule
297 of 512
recommended

Flags proven self-comparisons of side-effect-free scalar values.

Getter reads, index operations, calls, and user-defined operator receivers are intentionally excluded: evaluating the same syntax twice need not produce the same value, and equality/ordering may be overloaded. A scalar read type does not establish stability: unqualified top-level and inherited getter names still execute a getter on each evaluation.

Invalid

example.dartdart
bool a(int x) => x == x;

bool b(int x) => x != x;

bool c(int x) => x < x;

class Foo {
  int value = 0;

  bool check() => value >= value;

  bool nested(List<int> a) => a[0] == a[0];
}

void d(int x) {
  if (x > x) {
    print('never');
  }
}

// A local binding shadows the effectful top-level getter.
int get changing => 0;
bool shadowedGetter(int changing) => changing == changing;
Both operands of this comparison are identical.
1bool a(int x) => x == x;
Both operands of this comparison are identical.
2
3bool b(int x) => x != x;
Both operands of this comparison are identical.
4
5bool c(int x) => x < x;
Both operands of this comparison are identical.
9
10 bool check() => value >= value;
Both operands of this comparison are identical.
15void d(int x) {
16 if (x > x) {
Both operands of this comparison are identical.
22int get changing => 0;
23bool shadowedGetter(int changing) => changing == changing;

Valid

example.dartdart
bool a(int x, int y) => x == y;

bool b(int x) => x == x + 1;

bool c(int x) => x < x + 1;

class Foo {
  int a = 0;
  int b = 0;

  bool check() => a == b;

  bool indexed(List<int> l) => l[0] == l[1];
}

void d(int x, int y) {
  if (x > y) {
    print('maybe');
  }
}

bool e(int x) => -x == x;

// Side-effecting calls evaluate to different values, so identical text is
// not a self-comparison.
bool popEqual(List<int> l) => l.removeLast() == l.removeLast();

bool nowEqual() => DateTime.now() == DateTime.now();

int nextId = 0;
int gen() => nextId++;
bool genEqual() => gen() == gen();

// Prefix ++/-- mutate the operand, so the two sides differ.
bool preIncrement(int x) => ++x == ++x;

bool preDecrement(int x) => --x == --x;

int get changing => nextId++;
bool getterEqual() => changing == changing;
bool sameIndex(List<int> values) => values[0] == values[0];

class WeirdEquality {
  @override
  bool operator ==(Object other) => false;

  bool compare() => this == this;
}

// Resolving a getter's scalar type must not make repeated reads stable.
bool negatedGetterEqual() => -changing == -changing;

class ChangingValue {
  int get value => nextId++;
  bool equal() => value == value;
}

class InheritedChangingValue extends ChangingValue {
  bool inheritedEqual() => value == value;
}

Configure no-self-comparisons

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "suspicious": {
        "no-self-comparisons": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/suspicious/no-self-comparisons: <reason>