From 6dfc9f8886535725630fdf2f5d70459a21f3ca16 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sun, 21 Jul 2024 21:37:22 -0400 Subject: [PATCH] Explain that coroutine can be marked static And also point out the def span of the coroutine --- .../rustc_borrowck/src/borrowck_errors.rs | 30 +++++++++++++++++-- tests/ui/coroutine/coroutine-with-nll.stderr | 8 +++++ tests/ui/coroutine/issue-48048.stderr | 8 +++++ tests/ui/coroutine/pattern-borrow.stderr | 7 +++++ .../self_referential_gen_block.stderr | 3 ++ tests/ui/coroutine/yield-in-args.stderr | 8 +++++ .../ui/coroutine/yield-while-iterating.stderr | 7 +++++ .../yield-while-local-borrowed.stderr | 15 ++++++++++ tests/ui/nll/issue-55850.stderr | 8 +++++ 9 files changed, 91 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index 8eb44458137..80deea14685 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -1,7 +1,9 @@ #![allow(rustc::diagnostic_outside_of_impl)] #![allow(rustc::untranslatable_diagnostic)] +use rustc_errors::Applicability; use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle}; +use rustc_hir as hir; use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; @@ -382,13 +384,35 @@ pub(crate) fn cannot_borrow_across_coroutine_yield( yield_span: Span, ) -> Diag<'infcx> { let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind; - struct_span_code_err!( + let mut diag = struct_span_code_err!( self.dcx(), span, E0626, "borrow may still be in use when {coroutine_kind:#} yields", - ) - .with_span_label(yield_span, "possible yield occurs here") + ); + diag.span_label( + self.infcx.tcx.def_span(self.body.source.def_id()), + format!("within this {coroutine_kind:#}"), + ); + diag.span_label(yield_span, "possible yield occurs here"); + if matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_)) { + let hir::Closure { capture_clause, fn_decl_span, .. } = self + .infcx + .tcx + .hir_node_by_def_id(self.body.source.def_id().expect_local()) + .expect_closure(); + let span = match capture_clause { + rustc_hir::CaptureBy::Value { move_kw } => move_kw.shrink_to_lo(), + rustc_hir::CaptureBy::Ref => fn_decl_span.shrink_to_lo(), + }; + diag.span_suggestion_verbose( + span, + "add `static` to mark this coroutine as unmovable", + "static ", + Applicability::MaybeIncorrect, + ); + } + diag } pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> { diff --git a/tests/ui/coroutine/coroutine-with-nll.stderr b/tests/ui/coroutine/coroutine-with-nll.stderr index 3f3d51da311..ee3a8f45f44 100644 --- a/tests/ui/coroutine/coroutine-with-nll.stderr +++ b/tests/ui/coroutine/coroutine-with-nll.stderr @@ -1,11 +1,19 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/coroutine-with-nll.rs:8:17 | +LL | || { + | -- within this coroutine +... LL | let b = &mut true; | ^^^^^^^^^ LL | LL | yield (); | -------- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | static || { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/issue-48048.stderr b/tests/ui/coroutine/issue-48048.stderr index 199ecf4ca6a..8231dbef7f6 100644 --- a/tests/ui/coroutine/issue-48048.stderr +++ b/tests/ui/coroutine/issue-48048.stderr @@ -1,10 +1,18 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/issue-48048.rs:9:9 | +LL | #[coroutine] || { + | -- within this coroutine +... LL | x.0({ | ^^^ LL | yield; | ----- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | #[coroutine] static || { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/pattern-borrow.stderr b/tests/ui/coroutine/pattern-borrow.stderr index 9e7b330d79d..a3954b0b8ad 100644 --- a/tests/ui/coroutine/pattern-borrow.stderr +++ b/tests/ui/coroutine/pattern-borrow.stderr @@ -1,10 +1,17 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/pattern-borrow.rs:9:24 | +LL | #[coroutine] move || { + | ------- within this coroutine LL | if let Test::A(ref _a) = test { | ^^^^^^ LL | yield (); | -------- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | #[coroutine] static move || { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/self_referential_gen_block.stderr b/tests/ui/coroutine/self_referential_gen_block.stderr index e23d653d0d4..2f53e7c84a1 100644 --- a/tests/ui/coroutine/self_referential_gen_block.stderr +++ b/tests/ui/coroutine/self_referential_gen_block.stderr @@ -1,6 +1,9 @@ error[E0626]: borrow may still be in use when `gen` block yields --> $DIR/self_referential_gen_block.rs:9:21 | +LL | let mut x = gen { + | --- within this `gen` block +LL | let y = 42; LL | let z = &y; | ^^ LL | yield 43; diff --git a/tests/ui/coroutine/yield-in-args.stderr b/tests/ui/coroutine/yield-in-args.stderr index 1d2c54f9bdb..1cc3c83deb3 100644 --- a/tests/ui/coroutine/yield-in-args.stderr +++ b/tests/ui/coroutine/yield-in-args.stderr @@ -1,8 +1,16 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/yield-in-args.rs:9:13 | +LL | || { + | -- within this coroutine +LL | let b = true; LL | foo(&b, yield); | ^^ ----- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | static || { + | ++++++ error: aborting due to 1 previous error diff --git a/tests/ui/coroutine/yield-while-iterating.stderr b/tests/ui/coroutine/yield-while-iterating.stderr index f81c914c4bd..a92237e44c1 100644 --- a/tests/ui/coroutine/yield-while-iterating.stderr +++ b/tests/ui/coroutine/yield-while-iterating.stderr @@ -1,10 +1,17 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/yield-while-iterating.rs:13:18 | +LL | let _b =#[coroutine] move || { + | ------- within this coroutine LL | for p in &x { | ^^ LL | yield(); | ------- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | let _b =#[coroutine] static move || { + | ++++++ error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable --> $DIR/yield-while-iterating.rs:58:20 diff --git a/tests/ui/coroutine/yield-while-local-borrowed.stderr b/tests/ui/coroutine/yield-while-local-borrowed.stderr index 8fe981de929..b42ca3ba461 100644 --- a/tests/ui/coroutine/yield-while-local-borrowed.stderr +++ b/tests/ui/coroutine/yield-while-local-borrowed.stderr @@ -1,20 +1,35 @@ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/yield-while-local-borrowed.rs:13:17 | +LL | let mut b = #[coroutine] move || { + | ------- within this coroutine LL | let a = &mut 3; | ^^^^^^ LL | LL | yield (); | -------- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | let mut b = #[coroutine] static move || { + | ++++++ error[E0626]: borrow may still be in use when coroutine yields --> $DIR/yield-while-local-borrowed.rs:40:21 | +LL | let mut b = #[coroutine] move || { + | ------- within this coroutine +... LL | let b = &a; | ^^ LL | LL | yield (); | -------- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | let mut b = #[coroutine] static move || { + | ++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-55850.stderr b/tests/ui/nll/issue-55850.stderr index 3d43817f4d8..5a9c7799197 100644 --- a/tests/ui/nll/issue-55850.stderr +++ b/tests/ui/nll/issue-55850.stderr @@ -10,8 +10,16 @@ LL | yield &s[..] error[E0626]: borrow may still be in use when coroutine yields --> $DIR/issue-55850.rs:28:16 | +LL | GenIter(#[coroutine] move || { + | ------- within this coroutine +LL | let mut s = String::new(); LL | yield &s[..] | -------^---- possible yield occurs here + | +help: add `static` to mark this coroutine as unmovable + | +LL | GenIter(#[coroutine] static move || { + | ++++++ error: aborting due to 2 previous errors