Skip to content

Warn when awaiting with other futures in scope #77448

Closed
@bugaevc

Description

@bugaevc

In programming languages where futures are callback-based and can make progress by themselves without anyone actively awaiting them, the following pattern is common for starting several actions concurrently, and waiting then for them all to complete:

future1 = do_something_async1()
future2 = do_something_async2()

res1 = await future1
res2 = await future2

However if you write code like that in Rust, the actions will be executed sequentially, since Rust futures require you to actively poll them to drive them to completion, and you won't be polling future2 while you're .awaiting future1.

Currently, the compiler does not warn on the following code:

let future1 = async { };
let future2 = async { };

future1.await;
future2.await;

(playground)

It would be nice if the compiler could catch situations like these and suggest to use futures::join() instead.

As a first approximation, the heuristic could be: warn if .await is used when a variable whose type is a Future is in scope (and is not the value being awaited) — meaning that other future won't make progress while we're awaiting this one. So in the example above, future1.await is performed while future2 is in scope.

This heuristic would not catch (false negative) the following pattern:

let futures: Vec<SomeFuture> = iter.map(make_future).collect();
for future in futures {
    future.await;
}

which, in other languages, is also a common pattern to preform and await a dynamic number of actions concurrently. In Rust, you have to use something like futures::join_all() or FuturesUnordered.

False positives (where you don't actually have to poll your future for it to make progress):

  • Join handles of spawned tasks
  • Channel receivers
  • Timers

Perhaps there could be an attribute to mark these types.

Related: rust-lang/wg-async#16; but that RFC is about specially marking some types that should not be held across .await, whereas this issue is about applying that to (almost) all futures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions