-   Notifications  
You must be signed in to change notification settings  - Fork 13.9k
 
Open
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.
Description
I tried this code:
#![allow(unused)] async fn works<'a>(mut a: &'a i32, b: i32) { a = &b; } fn fails<'a>(mut a: &'a i32, b: i32) { a = &b; } fn also_fails<'a>(mut a: &'a i32, b: i32) -> impl Future<Output = ()> { async move { a = &b; } }I expected all 3 functions to compile, or all to fail to compile, but instead only the first function compiles:
error[E0521]: borrowed data escapes outside of async block --> src/lib.rs:10:9 | 8 | fn also_fails<'a>(mut a: &'a i32, b: i32) -> impl Future<Output = ()> { | ----- `a` declared here, outside of the async block body 9 | async move { 10 | a = &b; | ^^^^-- | | | | | borrow is only valid in the async block body | reference to `b` escapes the async block body here error[E0597]: `b` does not live long enough --> src/lib.rs:6:9 | 5 | fn fails<'a>(mut a: &'a i32, b: i32) { | -- - binding `b` declared here | | | lifetime `'a` defined here 6 | a = &b; | ----^^ | | | | | borrowed value does not live long enough | assignment requires that `b` is borrowed for `'a` 7 | } | - `b` dropped here while still borrowed Some errors have detailed explanations: E0521, E0597. For more information about an error, try `rustc --explain E0521`. Edit: The part below is filed separately as #148401
A different issue that's now filed separately
Additionally, there's this variant which has a very strange diagnostic that I don't understand:
#![allow(unused)] fn weird<'a, 'b>(mut a: &'a i32, b: &'b i32) -> impl Future<Output = ()> + use<'a, 'b> { async move { a = b; } }error[E0700]: hidden type for `impl Future<Output = ()>` captures lifetime that does not appear in bounds --> src/lib.rs:3:5 | 2 | fn weird<'a, 'b>(mut a: &'a i32, b: &'b i32) -> impl Future<Output = ()> + use<'a, 'b> { | -------------------------------------- opaque type defined here 3 | / async move { 4 | | a = b; 5 | | } | |_____^ | = note: hidden type `{async block@src/lib.rs:3:5: 3:15}` captures lifetime `'_` For more information about this error, try `rustc --explain E0700`. See also #128225, where a variable can be assigned a value with a different lifetime.
Related to #148463, where a similar inconsistency occurs with patterns in function arguments.
Meta
Reproducible on the playground with version 1.93.0-nightly (2025-11-01 bd3ac0330018c23b111b)
Metadata
Metadata
Assignees
Labels
A-async-awaitArea: Async & AwaitArea: Async & AwaitA-borrow-checkerArea: The borrow checkerArea: The borrow checkerA-lifetimesArea: Lifetimes / regionsArea: Lifetimes / regionsC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.needs-triageThis issue may need triage. Remove it if it has been sufficiently triaged.This issue may need triage. Remove it if it has been sufficiently triaged.