forEach called with a one-parameter function literal

ID

dart.performance.avoid_function_literals_foreach

Severity

info

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Idiom

Language

Dart

Description

Reports forEach called with a single-parameter function literal, in arrow or block form, where a for-in loop expresses the same iteration. Passing an existing function as a tear-off (items.forEach(print)) is not reported, and neither is an awaited Stream.forEach, which has no for-in equivalent.

Rationale

The closure turns every element into a call: the loop body cannot be inlined into the caller, and it captures the enclosing scope, so a forEach in a hot path pays for a closure allocation plus one indirect call per element that a for-in loop does not. The closure also changes what the body is allowed to do - break, continue and return no longer refer to the iteration, so an early exit has to be faked with a flag or an exception, and an await inside the literal does not suspend the iteration, which is a silent source of interleaved work. A for-in loop has none of these restrictions.

The following code illustrates the pattern detected by this rule:

class Audit {
  final List<String> events;

  Audit(this.events);

  void logAll() {
    // FLAGGED: forEach called with a one-parameter function literal
    events.forEach((e) {
      print(e);
    });
  }
}

Remediation

Rewrite as for (final item in items) { …​ }, which allows break, continue, return and await in the body. Keep forEach where the argument is an existing function passed as a tear-off, since there is no literal to allocate.

Configuration

This detector does not need any configuration.

© 2026 Xygeni. All rights reserved