Skip to content

Idea: lint when passing async functions into forEach #57677

@greglittlefield-wf

Description

@greglittlefield-wf

I recently ran into a few instances of code that used the following:

values.forEach((value) async {
  // ...
  doSomethingSync();
  await value.doSomethingAsync();
});
map.forEach((key, value) async {
  doSomethingSync();
  await value.doSomethingAsync();
});

The intended behavior in at least one of the cases was to wait for all of the awaits to be run before proceeding, which can be done via Future.forEach or a for loop with awaits.

Even if the intended behavior is what is actually happening, it might not be immediately obvious to someone unfamiliar with how async functions are executed in Dart 1.x.

The first example would be avoided by using the prefer_foreach rule (unless a tearoff were passed in instead), but the second would not. Still, for the first example, it might be good to have a more specific lint to catch this case.

Are Iterable.forEach/Map.forEach common-enough special cases where using async functions should result in a lint?

Another idea, though it would have far more impact and may be too noisy, would be to lint when an async function is being used where a void function is accepted.

CallbackSubscription registerVoidCallback(void callback()) { /*...*/ }

// Good
registerVoidCallback((() { /* ... */ });
// Would lint
registerVoidCallback((() async { /* ... */ });

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3A lower priority bug or feature requestarea-devexpFor issues related to the analysis server, IDE support, linter, `dart fix`, and diagnostic messages.devexp-linterIssues with the analyzer's support for the linter packagelinter-lint-proposaltype-enhancementA request for a change that isn't a bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions