Skip to content

async fn can assign to argument to change its lifetime, but normal fn and async blocks cannot. #148389

@theemathas

Description

@theemathas

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

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitA-borrow-checkerArea: The borrow checkerA-lifetimesArea: Lifetimes / regionsC-bugCategory: This is a bug.T-typesRelevant 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.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions