prefer-final-in-for-each

Same as prefer_final_in_for_each in Dart lints

Group
Style
Path
lint/style/prefer-final-in-for-each
Default
On (recommended)
Origin
Dart lints
Rule
355 of 512
recommended

Prefer final for a for-each loop variable that is never reassigned.

for (var item in items) where item is never written in its scope reads better as for (final item in items). Destructuring loops are covered when the top-level record, object, list, or map pattern binds only plain variables and none of them is reassigned. A loop over an existing variable (for (item in items)) declares nothing and is ignored. Collection loops outside function bodies (top-level and field initializers) are also ignored.

for (var name in names) print(name); // flagged
for (final name in names) print(name); // ok

Invalid

example.dartdart
class Pair {
  final int a;
  final int b;
  Pair(this.a, this.b);
}

void loops(List<int> numbers, List<(int, String)> rows, List<Pair> pairs, List<List<int>> lists,
    List<Map<String, int>> maps) {
  for (var n in numbers) {
    print(n);
  }
  for (int n in numbers) {
    print(n);
  }
  for (var (i, s) in rows) {
    print('$i$s');
  }
  for (var Pair(a: x, b: y) in pairs) {
    print(x + y);
  }
  for (var [first, second] in lists) {
    print(first + second);
  }
  for (var {'k': value} in maps) {
    print(value);
  }
  final doubled = [for (var n in numbers) n * 2];
  print(doubled);
}

Future<void> streams(Stream<int> values) async {
  await for (var v in values) {
    print(v);
  }
}
The variable `n` should be `final`.
8 List<Map<String, int>> maps) {
9 for (var n in numbers) {
The variable `n` should be `final`.
11 }
12 for (int n in numbers) {
The pattern should be `final`.
14 }
15 for (var (i, s) in rows) {
The pattern should be `final`.
17 }
18 for (var Pair(a: x, b: y) in pairs) {
The pattern should be `final`.
20 }
21 for (var [first, second] in lists) {
The pattern should be `final`.
23 }
24 for (var {'k': value} in maps) {
The variable `n` should be `final`.
26 }
27 final doubled = [for (var n in numbers) n * 2];
The variable `v` should be `final`.
31Future<void> streams(Stream<int> values) async {
32 await for (var v in values) {

Valid

example.dartdart
void loops(List<int> numbers, List<(int, String)> rows, List<List<int>> lists) {
  for (final n in numbers) {
    print(n);
  }
  for (var n in numbers) {
    n += 1;
    print(n);
  }
  for (var n in numbers) {
    void bump() {
      n++;
    }

    bump();
  }
  for (final (i, s) in rows) {
    print('$i$s');
  }
  for (var (i, s) in rows) {
    i = 0;
    print('$i$s');
  }
  for (var (i, _) in rows) {
    print(i);
  }
  for (var [first, ...rest] in lists) {
    print('$first$rest');
  }
  var existing = 0;
  for (existing in numbers) {
    print(existing);
  }
  for (var i = 0; i < numbers.length; i++) {
    print(i);
  }
  final copy = [for (final n in numbers) n];
  print(copy);
}

// The analyzer requires an enclosing function body, not a field initializer.
final topLevelCollection = [for (var n in [1, 2]) n];

class Initializer {
  final values = [for (var n in [1, 2]) n];
}

Configure prefer-final-in-for-each

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "prefer-final-in-for-each": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/prefer-final-in-for-each: <reason>