From 6866a94d49fbcf0de2baef4b21bdeabb88784ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 13 Jul 2026 22:58:56 +0000 Subject: [PATCH] Account for async closures when pointing at lifetime in return type ``` error: lifetime may not live long enough --> $DIR/higher-ranked-return.rs:11:46 | LL | let x = async move |x: &str| -> &str { | ________________________________-________-____^ | | | | | | | let's call the lifetime of this reference `'2` | | let's call the lifetime of this reference `'1` LL | | x LL | | }; | |_________^ returning this value requires that `'1` must outlive `'2` ``` instead of ``` error: lifetime may not live long enough --> $DIR/higher-ranked-return.rs:11:46 | LL | let x = async move |x: &str| -> &str { | ________________________________-________----_^ | | | | | | | return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:11:46: 13:10}` contains a lifetime `'2` | | let's call the lifetime of this reference `'1` LL | | x LL | | }; | |_________^ returning this value requires that `'1` must outlive `'2` ``` --- compiler/rustc_borrowck/src/diagnostics/region_name.rs | 8 +++++++- .../async-closures/higher-ranked-return.stderr | 4 ++-- tests/ui/async-await/async-closures/not-lending.stderr | 4 ++-- .../issue-74072-lifetime-name-annotations.stderr | 4 ++-- 4 files changed, 13 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index b8037fc83aad0..0e07de31c2baa 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -791,12 +791,18 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { fn give_name_if_anonymous_region_appears_in_output(&self, fr: RegionVid) -> Option { let tcx = self.infcx.tcx; - let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; + let mut return_ty = self.regioncx.universal_regions().unnormalized_output_ty; debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); if !tcx.any_free_region_meets(&return_ty, |r| r.as_var() == fr) { return None; } + if let ty::Coroutine(_, args) = return_ty.kind() { + // When the return type is identified to be `{async closure body}`, we instead care + // about the actual return type of that coroutine. + return_ty = args.as_coroutine().return_ty(); + } + let mir_hir_id = self.mir_hir_id(); let (return_span, mir_description, hir_ty) = match tcx.hir_node(mir_hir_id) { diff --git a/tests/ui/async-await/async-closures/higher-ranked-return.stderr b/tests/ui/async-await/async-closures/higher-ranked-return.stderr index 23ce3df661654..efd5698e9731f 100644 --- a/tests/ui/async-await/async-closures/higher-ranked-return.stderr +++ b/tests/ui/async-await/async-closures/higher-ranked-return.stderr @@ -2,9 +2,9 @@ error: lifetime may not live long enough --> $DIR/higher-ranked-return.rs:11:46 | LL | let x = async move |x: &str| -> &str { - | ________________________________-________----_^ + | ________________________________-________-____^ | | | | - | | | return type of async closure `{async closure body@$DIR/higher-ranked-return.rs:11:46: 13:10}` contains a lifetime `'2` + | | | let's call the lifetime of this reference `'2` | | let's call the lifetime of this reference `'1` LL | | x LL | | }; diff --git a/tests/ui/async-await/async-closures/not-lending.stderr b/tests/ui/async-await/async-closures/not-lending.stderr index fb941502d3646..989b9ccb88a76 100644 --- a/tests/ui/async-await/async-closures/not-lending.stderr +++ b/tests/ui/async-await/async-closures/not-lending.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | let x = async move || -> &String { &s }; | ------------------------ ^^^^^^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of async closure `{async closure body@$DIR/not-lending.rs:12:42: 12:48}` contains a lifetime `'2` + | | let's call the lifetime of this reference `'2` | lifetime `'1` represents this closure's body | = note: closure implements `AsyncFn`, so references to captured variables can't escape the closure @@ -15,7 +15,7 @@ error: lifetime may not live long enough LL | let x = async move || { &s }; | ------------- ^^^^^^ returning this value requires that `'1` must outlive `'2` | | | - | | return type of async closure `{async closure body@$DIR/not-lending.rs:16:31: 16:37}` contains a lifetime `'2` + | | return type of async closure is &'2 String | lifetime `'1` represents this closure's body | = note: closure implements `AsyncFn`, so references to captured variables can't escape the closure diff --git a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr index c479adfa56d7e..3cf2d20f155fd 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -29,7 +29,7 @@ error: lifetime may not live long enough LL | (async move || { | ______-------------_^ | | | | - | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:13:20: 19:6}` contains a lifetime `'2` + | | | return type of async closure is &'2 i32 | | lifetime `'1` represents this closure's body LL | | LL | | @@ -78,7 +78,7 @@ error: lifetime may not live long enough LL | (async move || -> &i32 { | ______---------------------_^ | | | | - | | | return type of async closure `{async closure body@$DIR/issue-74072-lifetime-name-annotations.rs:23:28: 29:6}` contains a lifetime `'2` + | | | let's call the lifetime of this reference `'2` | | lifetime `'1` represents this closure's body LL | | LL | |