unnecessary-await-in-return

Same as unnecessary_await_in_return in Dart lints

Group
Style
Path
lint/style/unnecessary-await-in-return
Default
Off, opt in
Origin
Dart lints
Rule
449 of 512

Avoid await on a returned Future the function's own Future already covers.

Returning a Future from an async function already completes the function's result with it, so awaiting first adds nothing:

Future<int> load() async => await fetch(); // BAD
Future<int> load() async => fetch(); // GOOD

Reported for return await e; statements and => await e bodies (including grouped expressions) of functions, methods, and closures returning Future<R>, when e is a Future<A> with A provably assignable to R. Closures and local functions infer their return type, flattening nested futures and respecting a closure's contextual Future or FutureOr return type. Untyped top-level declarations do not infer it. Returns inside a try or finally block are exempt.

Invalid

example.dartdart
import 'dart:async';

Future<int> fetch() async => 1;

Future<String> fetchName() async => 'name';

Future<int> arrow() async => await fetch();

Future<int> block() async {
  return await fetch();
}

Future<Object> wider() async {
  return await fetchName();
}

Future<dynamic> dynamicResult() async => await fetch();

class Repository {
  Future<int> load() async {
    return await fetch();
  }

  Future<int> get count async => await fetch();
}

void outer() {
  Future<int> local() async {
    return await fetch();
  }

  local();
}

Future<int> afterTry() async {
  try {
    print('x');
  } finally {
    print('y');
  }
  return await fetch();
}

void inferredClosures() {
  final arrow = () async => await fetch();
  final block = () async {
    return await fetch();
  };
  arrow();
  block();
}


Future<List<int>> fetchList() async => <int>[1];
Future<List<num>> covariantFuture() async => await fetchList();

Future<int> nestedClosureInTry() async {
  try {
    final callback = () async => await fetch();
    return callback();
  } catch (_) {
    return 0;
  }
}

Future<Never> neverCompletes() => Future<Never>.error('failure');
Future<int> awaitsNever() async => await neverCompletes();

class AuthResult {}
class AuthSuccess extends AuthResult {}
void registerAuth(Future<AuthResult> Function() callback) {}
void subtypeClosure(Future<AuthSuccess> result) {
  registerAuth(() async => await result);
}

void registerPreparation(FutureOr<void> Function() callback) {}
void futureOrClosure(Future<int> result) {
  registerPreparation(() async => await result);
}
Remove the unnecessary `await`.
6
7Future<int> arrow() async => await fetch();
Remove the unnecessary `await`.
9Future<int> block() async {
10 return await fetch();
Remove the unnecessary `await`.
13Future<Object> wider() async {
14 return await fetchName();
Remove the unnecessary `await`.
16
17Future<dynamic> dynamicResult() async => await fetch();
Remove the unnecessary `await`.
20 Future<int> load() async {
21 return await fetch();
Remove the unnecessary `await`.
23
24 Future<int> get count async => await fetch();
Remove the unnecessary `await`.
28 Future<int> local() async {
29 return await fetch();
Remove the unnecessary `await`.
40 }
41 return await fetch();
Remove the unnecessary `await`.
44void inferredClosures() {
45 final arrow = () async => await fetch();
Remove the unnecessary `await`.
46 final block = () async {
47 return await fetch();
Remove the unnecessary `await`.
54Future<List<int>> fetchList() async => <int>[1];
55Future<List<num>> covariantFuture() async => await fetchList();
Remove the unnecessary `await`.
58 try {
59 final callback = () async => await fetch();
Remove the unnecessary `await`.
66Future<Never> neverCompletes() => Future<Never>.error('failure');
67Future<int> awaitsNever() async => await neverCompletes();
Remove the unnecessary `await`.
72void subtypeClosure(Future<AuthSuccess> result) {
73 registerAuth(() async => await result);
Remove the unnecessary `await`.
77void futureOrClosure(Future<int> result) {
78 registerPreparation(() async => await result);

Valid

example.dartdart
Future<int> fetch() async => 1;

Future<String> fetchName() async => 'name';

Future<int> noAwait() async => fetch();

Future<int> plainReturn() async {
  return fetch();
}

Future<int> awaitInTry() async {
  try {
    return await fetch();
  } catch (e) {
    return 0;
  }
}

Future<int> awaitInFinally() async {
  try {
    print('x');
  } finally {
    return await fetch();
  }
}

Future<String> mismatch() async {
  return '${await fetch()}';
}

Future<void> used() async {
  final value = await fetch();
  print(value);
}

Future<int> awaitsNonFuture() async {
  return await 1;
}

Future<num> transformed() async {
  return (await fetch()) + 1;
}

void inferredClosureInTry() {
  final callback = () async {
    try {
      return await fetch();
    } catch (_) {
      return 0;
    }
  };
  callback();
}

inferredFunction() async => await fetch();

class UntypedDeclarations {
  method() async => await fetch();
  get value async => await fetch();
}

Future legacy() async => 1;
void register(Future<int> Function() callback) {}
void typedClosure() {
  register(() async => await legacy());
}

Future<Future<int>> nested() async => fetch();
void flattenedClosure() {
  final callback = () async => await nested();
  callback();
}

Configure unnecessary-await-in-return

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "style": {
        "unnecessary-await-in-return": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/style/unnecessary-await-in-return: <reason>
  • unnecessary-brace-in-string-interpsunnecessary_brace_in_string_interpsrecommended

    Flags ${x} string interpolations whose braces can be dropped.

  • unnecessary-breaksunnecessary_breaksrecommended

    Flags a trailing break in a switch case that already ends implicitly.

  • unnecessary-constructor-nameunnecessary_constructor_namerecommended

    Flags a redundant .new on constructor declarations and invocations.

  • unnecessary-finalunnecessary_final

    Don't use final for local variables and parameters.

  • unnecessary-lateunnecessary_laterecommended

    Flags a redundant late modifier on an initialized static or top-level variable.

  • unnecessary-library-directiveunnecessary_library_directiverecommended

    Flags a library directive that has neither a doc comment nor annotations.

  • unnecessary-library-nameunnecessary_library_namerecommended

    Flags a library directive that carries an explicit name.

  • unnecessary-newunnecessary_newrecommended

    Flags an explicit new keyword in an instance-creation expression.