Skip to content

Inconsistent move behavior in closure with async block #81653

@vultix

Description

@vultix

This closure fails to compile:

|val: i32| async {
    dbg!(val)
};

error[E0373]: async block may outlive the current function, but it borrows `val`, which is owned by the current function

I'd expect that this would compile - val should be moved into the async closure.

This is inconsistent with the following cases where it compiles (playground link):

  • If you change the type of val to a !Copy type (such as String)
  • If you get rid of the async keyword
  • If you don't use a closure and just have an async block capture a Copy variable

This has a serious drawback in that it forces you to use async move even when you can't move everything into the async block.

Workaround

This is super unergonomic, but as a workaround you can surround the copy type with a NonCopy newtype.

struct NonCopy(i32);
|val: NonCopy| async {
    dbg!{val.0}
};

Meta

This happens on Stable, Nightly, and Beta

rustc --version --verbose:

rustc 1.50.0-nightly (1c389ffef 2020-11-24)
binary: rustc
commit-hash: 1c389ffeff814726dec325f0f2b0c99107df2673
commit-date: 2020-11-24
host: x86_64-apple-darwin
release: 1.50.0-nightly

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-closuresArea: Closures (`|…| { … }`)AsyncAwait-TriagedAsync-await issues that have been triaged during a working group meeting.C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status

    On deck

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions