parameter-assignments

Same as parameter_assignments in Dart lints

Group
Style
Path
lint/style/parameter-assignments
Default
Off, opt in
Origin
Dart lints
Rule
308 of 512

Don't reassign parameters of functions, methods, or constructors.

Rebinding a parameter makes the body harder to follow: the name no longer means what the caller passed. Assignments (x = ..., x += ...), increments and decrements, and pattern assignments ((x, y) = ...) that write a parameter are flagged, including writes from closures inside the body. One exception mirrors the analyzer: an optional parameter without a default value (so it defaults to null) may be given a default once with x ??= value; a second ??= or any other assignment is still flagged. The analyzer also exempts increments/decrements of optional parameters without defaults, and this rule retains that exception.

Like the analyzer's visitor, the search does not descend into an assignment expression unless that assignment itself writes the parameter and the parameter defaults to null: writes nested in any other assignment (target[offset++] = v, x = p++, c.onCancel = () { p = 0; }, a..v = (p = 2)) are not reported. A constructor's parameters are searched for in its body only, not in its initializer list.

void f(int x) { x = 2; } // flagged
void g([int? x]) { x ??= 2; } // ok

Invalid

example.dartdart
class Point {
  int x;
  Point(this.x);

  void move(int dx) {
    dx = dx * 2;
    x += dx;
  }

  Point.from(int start) : x = 0 {
    start++;
    x = start;
  }
}

int compute(int value, [int? fallback]) {
  value += 1;
  fallback ??= 1;
  fallback ??= 2;
  fallback = 3;
  return value + fallback;
}

void named({required int count, int step = 1}) {
  count ??= 2;
  step = 2;
  print(count + step);
}

void swap(int a, int b) {
  (a, b) = (b, a);
  print(a + b);
}

void closures(int total) {
  void bump() {
    total--;
  }

  bump();
  final f = (int n) {
    n = 0;
    return n;
  };
  print(f(total));
}

void nestedInOwnAssignment(int count, [int? limit]) {
  count = count++;
  limit = limit ??= 2;
  print('$count$limit');
}

class ConstructorBody {
  final int value;
  ConstructorBody(int input) : value = input++ {
    input++;
  }
}
Avoid assigning to the parameter `dx`.
5 void move(int dx) {
6 dx = dx * 2;
Avoid assigning to the parameter `start`.
10 Point.from(int start) : x = 0 {
11 start++;
Avoid assigning to the parameter `value`.
16int compute(int value, [int? fallback]) {
17 value += 1;
Avoid assigning to the parameter `fallback`.
18 fallback ??= 1;
19 fallback ??= 2;
Avoid assigning to the parameter `fallback`.
19 fallback ??= 2;
20 fallback = 3;
Avoid assigning to the parameter `count`.
24void named({required int count, int step = 1}) {
25 count ??= 2;
Avoid assigning to the parameter `step`.
25 count ??= 2;
26 step = 2;
Avoid assigning to the parameter `a`.
30void swap(int a, int b) {
31 (a, b) = (b, a);
Avoid assigning to the parameter `b`.
30void swap(int a, int b) {
31 (a, b) = (b, a);
Avoid assigning to the parameter `total`.
36 void bump() {
37 total--;
Avoid assigning to the parameter `n`.
41 final f = (int n) {
42 n = 0;
Avoid assigning to the parameter `count`.
48void nestedInOwnAssignment(int count, [int? limit]) {
49 count = count++;
Avoid assigning to the parameter `limit`.
49 count = count++;
50 limit = limit ??= 2;
Avoid assigning to the parameter `input`.
56 ConstructorBody(int input) : value = input++ {
57 input++;

Valid

example.dartdart
class Point {
  int x;
  Point(this.x) {
    x = x + 1;
  }

  void move(int dx) {
    x += dx;
  }
}

int compute(int value, [int? fallback]) {
  fallback ??= 1;
  final result = value + fallback;
  return result;
}

void named({int? count}) {
  count ??= 2;
  print(count);
}

void shadowed(int value) {
  void inner(int value) {
    print(value);
  }

  inner(value);
  [1, 2].forEach((value) {
    print(value);
  });
}

void loop(int item, List<int> items) {
  for (item in items) {
    print(item);
  }
}

// The analyzer does not search inside assignments that write something else.
class Callbacks {
  void Function()? onCancel;
}

void nestedInAssignment(List<int> target, int targetOffset, int size, Callbacks c) {
  target[targetOffset++] = 1;
  var copy = 0;
  copy = size++;
  c.onCancel = () {
    size = 0;
  };
  print(copy);
}

class InitializerOnly {
  final int value;
  InitializerOnly(int input) : value = input++;
}

Configure parameter-assignments

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "parameter-assignments": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/parameter-assignments: <reason>