diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 963f902b71fcb..a00d39eea12d3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -111,9 +111,12 @@ impl RegionName { | RegionNameSource::NamedEarlyParamRegion(span) => { diag.span_label(*span, format!("lifetime `{self}` defined here")); } - RegionNameSource::SynthesizedFreeEnvRegion(span, note) => { + RegionNameSource::SynthesizedFreeEnvRegion(span, closure_trait) => { diag.span_label(*span, format!("lifetime `{self}` represents this closure's body")); - diag.note(*note); + diag.note(format!( + "closure implements `{closure_trait}`, so references to captured variables \ + can't escape the closure" + )); } RegionNameSource::AnonRegionFromArgument(RegionNameHighlight::CannotMatchHirTy( span, @@ -326,9 +329,15 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { ty::LateParamRegionKind::ClosureEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; - let closure_kind = match def_ty { - DefiningTy::Closure(_, args) => args.as_closure().kind(), - DefiningTy::CoroutineClosure(_, args) => args.as_coroutine_closure().kind(), + let (is_lending_coroutine_closure, closure_kind) = match def_ty { + DefiningTy::Closure(_, args) => (false, args.as_closure().kind()), + DefiningTy::CoroutineClosure(_, args) => { + let args = args.as_coroutine_closure(); + ( + !args.tupled_upvars_ty().is_ty_var() && args.has_self_borrows(), + args.kind(), + ) + } _ => { // Can't have BrEnv in functions, constants or coroutines. bug!("BrEnv outside of closure."); @@ -340,23 +349,19 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { bug!("Closure is not defined by a closure expr"); }; let region_name = self.synthesize_region_name(); - let note = match closure_kind { - ty::ClosureKind::Fn => { - "closure implements `Fn`, so references to captured variables \ - can't escape the closure" - } - ty::ClosureKind::FnMut => { - "closure implements `FnMut`, so references to captured variables \ - can't escape the closure" - } - ty::ClosureKind::FnOnce => { - bug!("BrEnv in a `FnOnce` closure"); - } + let closure_trait = match (is_lending_coroutine_closure, closure_kind) { + (false, kind) => kind.as_str(), + (true, ty::ClosureKind::Fn) => "AsyncFn", + (true, ty::ClosureKind::FnMut) => "AsyncFnMut", + (true, ty::ClosureKind::FnOnce) => "AsyncFnOnce", }; Some(RegionName { name: region_name, - source: RegionNameSource::SynthesizedFreeEnvRegion(fn_decl_span, note), + source: RegionNameSource::SynthesizedFreeEnvRegion( + fn_decl_span, + closure_trait, + ), }) } diff --git a/tests/ui/async-await/async-closures/not-lending.stderr b/tests/ui/async-await/async-closures/not-lending.stderr index f0028129caa02..fb941502d3646 100644 --- a/tests/ui/async-await/async-closures/not-lending.stderr +++ b/tests/ui/async-await/async-closures/not-lending.stderr @@ -7,7 +7,7 @@ LL | let x = async move || -> &String { &s }; | | return type of async closure `{async closure body@$DIR/not-lending.rs:12:42: 12:48}` contains a lifetime `'2` | lifetime `'1` represents this closure's body | - = note: closure implements `Fn`, so references to captured variables can't escape the closure + = note: closure implements `AsyncFn`, so references to captured variables can't escape the closure error: lifetime may not live long enough --> $DIR/not-lending.rs:16:31 @@ -18,7 +18,7 @@ LL | let x = async move || { &s }; | | return type of async closure `{async closure body@$DIR/not-lending.rs:16:31: 16:37}` contains a lifetime `'2` | lifetime `'1` represents this closure's body | - = note: closure implements `Fn`, so references to captured variables can't escape the closure + = note: closure implements `AsyncFn`, so references to captured variables can't escape the closure error: aborting due to 2 previous errors 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 e1f268116fc54..c479adfa56d7e 100644 --- a/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr +++ b/tests/ui/async-await/issue-74072-lifetime-name-annotations.stderr @@ -39,7 +39,7 @@ LL | | y LL | | })() | |_____^ returning this value requires that `'1` must outlive `'2` | - = note: closure implements `FnMut`, so references to captured variables can't escape the closure + = note: closure implements `AsyncFnMut`, so references to captured variables can't escape the closure error[E0716]: temporary value dropped while borrowed --> $DIR/issue-74072-lifetime-name-annotations.rs:13:5 @@ -88,7 +88,7 @@ LL | | y LL | | })() | |_____^ returning this value requires that `'1` must outlive `'2` | - = note: closure implements `FnMut`, so references to captured variables can't escape the closure + = note: closure implements `AsyncFnMut`, so references to captured variables can't escape the closure error[E0716]: temporary value dropped while borrowed --> $DIR/issue-74072-lifetime-name-annotations.rs:23:5