Skip to content

Variable lifetime is wrongly tracked in async fn #98077

Open
@thalesfragoso

Description

@thalesfragoso
async fn foo() {
    let mut f = None;
    let value = 0;
    f = Some(async { value });
    core::mem::drop(f);
}

Playground. Error:

  |
4 |     f = Some(async { value });
  |                    --^^^^^--
  |                    | |
  |                    | borrowed value does not live long enough
  |                    value captured here by generator
5 |     core::mem::drop(f);
6 | }
  | -
  | |
  | `value` dropped here while still borrowed
  | borrow might be used here, when `f` is dropped and runs the destructor for type `Option<impl Future<Output = i32>>`
  |
  = note: values in a scope are dropped in the opposite order they are defined

f is manually moved with drop and could not be dropped at the end of the scope after value.

Some bonus weird behavior, this works:

struct Foo;

async fn foo() {
    let mut f = None;
    let value = Foo;
    f = Some(async { value });
    core::mem::drop(f);
}

But if you add #[derive(Copy, Clone)] to Foo, then it fails with the same error. However, this also does not work:

struct Foo;

impl Foo {
    fn push(&mut self) {}
}

async fn foo() {
    let mut f = None;
    let value = Foo;
    f = Some(async { value.push() });
    core::mem::drop(f);
}

So, probably not necessarily connected to Copy.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitAsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.

    Type

    No type

    Projects

    Status

    On deck

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions