Rollup merge of #128049 - compiler-errors:E0626, r=petrochenkov
Reword E0626 to mention static coroutine, add structured suggestion for adding `static`
Not certain how to make the example feel less artificial. 🤷
My main point though is that we should probably emphasize that the first solution to making a coroutine allow a borrow across an await is making it `static`.
Also adds a structured suggestion.
This commit is contained in:
commit
4d6f74b450
10 changed files with 115 additions and 11 deletions
|
@ -1,7 +1,9 @@
|
||||||
#![allow(rustc::diagnostic_outside_of_impl)]
|
#![allow(rustc::diagnostic_outside_of_impl)]
|
||||||
#![allow(rustc::untranslatable_diagnostic)]
|
#![allow(rustc::untranslatable_diagnostic)]
|
||||||
|
|
||||||
|
use rustc_errors::Applicability;
|
||||||
use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
|
use rustc_errors::{codes::*, struct_span_code_err, Diag, DiagCtxtHandle};
|
||||||
|
use rustc_hir as hir;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
@ -382,13 +384,35 @@ impl<'infcx, 'tcx> crate::MirBorrowckCtxt<'_, '_, 'infcx, 'tcx> {
|
||||||
yield_span: Span,
|
yield_span: Span,
|
||||||
) -> Diag<'infcx> {
|
) -> Diag<'infcx> {
|
||||||
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
let coroutine_kind = self.body.coroutine.as_ref().unwrap().coroutine_kind;
|
||||||
struct_span_code_err!(
|
let mut diag = struct_span_code_err!(
|
||||||
self.dcx(),
|
self.dcx(),
|
||||||
span,
|
span,
|
||||||
E0626,
|
E0626,
|
||||||
"borrow may still be in use when {coroutine_kind:#} yields",
|
"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> {
|
pub(crate) fn cannot_borrow_across_destructor(&self, borrow_span: Span) -> Diag<'infcx> {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This error occurs because a borrow in a coroutine persists across a
|
This error occurs because a borrow in a movable coroutine persists across a
|
||||||
yield point.
|
yield point.
|
||||||
|
|
||||||
Erroneous code example:
|
Erroneous code example:
|
||||||
|
@ -15,19 +15,35 @@ let mut b = #[coroutine] || {
|
||||||
Pin::new(&mut b).resume(());
|
Pin::new(&mut b).resume(());
|
||||||
```
|
```
|
||||||
|
|
||||||
At present, it is not permitted to have a yield that occurs while a
|
Coroutines may be either unmarked, or marked with `static`. If it is unmarked,
|
||||||
borrow is still in scope. To resolve this error, the borrow must
|
then the coroutine is considered "movable". At present, it is not permitted to
|
||||||
either be "contained" to a smaller scope that does not overlap the
|
have a yield in a movable coroutine that occurs while a borrow is still in
|
||||||
yield or else eliminated in another way. So, for example, we might
|
scope. To resolve this error, the coroutine may be marked `static`:
|
||||||
resolve the previous example by removing the borrow and just storing
|
|
||||||
the integer by value:
|
```
|
||||||
|
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||||
|
# use std::ops::Coroutine;
|
||||||
|
# use std::pin::Pin;
|
||||||
|
let mut b = #[coroutine] static || { // <-- note the static keyword
|
||||||
|
let a = &String::from("hello, world");
|
||||||
|
yield ();
|
||||||
|
println!("{}", a);
|
||||||
|
};
|
||||||
|
let mut b = std::pin::pin!(b);
|
||||||
|
b.as_mut().resume(());
|
||||||
|
```
|
||||||
|
|
||||||
|
If the coroutine must remain movable, for example to be used as `Unpin`
|
||||||
|
without pinning it on the stack or in an allocation, we can alternatively
|
||||||
|
resolve the previous example by removing the borrow and just storing the
|
||||||
|
type by value:
|
||||||
|
|
||||||
```
|
```
|
||||||
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
# #![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||||
# use std::ops::Coroutine;
|
# use std::ops::Coroutine;
|
||||||
# use std::pin::Pin;
|
# use std::pin::Pin;
|
||||||
let mut b = #[coroutine] || {
|
let mut b = #[coroutine] || {
|
||||||
let a = 3;
|
let a = String::from("hello, world");
|
||||||
yield ();
|
yield ();
|
||||||
println!("{}", a);
|
println!("{}", a);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,11 +1,19 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/coroutine-with-nll.rs:8:17
|
--> $DIR/coroutine-with-nll.rs:8:17
|
||||||
|
|
|
|
||||||
|
LL | || {
|
||||||
|
| -- within this coroutine
|
||||||
|
...
|
||||||
LL | let b = &mut true;
|
LL | let b = &mut true;
|
||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | yield ();
|
LL | yield ();
|
||||||
| -------- possible yield occurs here
|
| -------- possible yield occurs here
|
||||||
|
|
|
||||||
|
help: add `static` to mark this coroutine as unmovable
|
||||||
|
|
|
||||||
|
LL | static || {
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,18 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/issue-48048.rs:9:9
|
--> $DIR/issue-48048.rs:9:9
|
||||||
|
|
|
|
||||||
|
LL | #[coroutine] || {
|
||||||
|
| -- within this coroutine
|
||||||
|
...
|
||||||
LL | x.0({
|
LL | x.0({
|
||||||
| ^^^
|
| ^^^
|
||||||
LL | yield;
|
LL | yield;
|
||||||
| ----- possible yield occurs here
|
| ----- possible yield occurs here
|
||||||
|
|
|
||||||
|
help: add `static` to mark this coroutine as unmovable
|
||||||
|
|
|
||||||
|
LL | #[coroutine] static || {
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/pattern-borrow.rs:9:24
|
--> $DIR/pattern-borrow.rs:9:24
|
||||||
|
|
|
|
||||||
|
LL | #[coroutine] move || {
|
||||||
|
| ------- within this coroutine
|
||||||
LL | if let Test::A(ref _a) = test {
|
LL | if let Test::A(ref _a) = test {
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
LL | yield ();
|
LL | yield ();
|
||||||
| -------- possible yield occurs here
|
| -------- possible yield occurs here
|
||||||
|
|
|
||||||
|
help: add `static` to mark this coroutine as unmovable
|
||||||
|
|
|
||||||
|
LL | #[coroutine] static move || {
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
error[E0626]: borrow may still be in use when `gen` block yields
|
error[E0626]: borrow may still be in use when `gen` block yields
|
||||||
--> $DIR/self_referential_gen_block.rs:9:21
|
--> $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 | let z = &y;
|
||||||
| ^^
|
| ^^
|
||||||
LL | yield 43;
|
LL | yield 43;
|
||||||
|
|
|
@ -1,8 +1,16 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/yield-in-args.rs:9:13
|
--> $DIR/yield-in-args.rs:9:13
|
||||||
|
|
|
|
||||||
|
LL | || {
|
||||||
|
| -- within this coroutine
|
||||||
|
LL | let b = true;
|
||||||
LL | foo(&b, yield);
|
LL | foo(&b, yield);
|
||||||
| ^^ ----- possible yield occurs here
|
| ^^ ----- possible yield occurs here
|
||||||
|
|
|
||||||
|
help: add `static` to mark this coroutine as unmovable
|
||||||
|
|
|
||||||
|
LL | static || {
|
||||||
|
| ++++++
|
||||||
|
|
||||||
error: aborting due to 1 previous error
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,17 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/yield-while-iterating.rs:13:18
|
--> $DIR/yield-while-iterating.rs:13:18
|
||||||
|
|
|
|
||||||
|
LL | let _b =#[coroutine] move || {
|
||||||
|
| ------- within this coroutine
|
||||||
LL | for p in &x {
|
LL | for p in &x {
|
||||||
| ^^
|
| ^^
|
||||||
LL | yield();
|
LL | yield();
|
||||||
| ------- possible yield occurs here
|
| ------- 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
|
error[E0502]: cannot borrow `x` as immutable because it is also borrowed as mutable
|
||||||
--> $DIR/yield-while-iterating.rs:58:20
|
--> $DIR/yield-while-iterating.rs:58:20
|
||||||
|
|
|
@ -1,20 +1,35 @@
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/yield-while-local-borrowed.rs:13:17
|
--> $DIR/yield-while-local-borrowed.rs:13:17
|
||||||
|
|
|
|
||||||
|
LL | let mut b = #[coroutine] move || {
|
||||||
|
| ------- within this coroutine
|
||||||
LL | let a = &mut 3;
|
LL | let a = &mut 3;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
LL |
|
LL |
|
||||||
LL | yield ();
|
LL | yield ();
|
||||||
| -------- possible yield occurs here
|
| -------- 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
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/yield-while-local-borrowed.rs:40:21
|
--> $DIR/yield-while-local-borrowed.rs:40:21
|
||||||
|
|
|
|
||||||
|
LL | let mut b = #[coroutine] move || {
|
||||||
|
| ------- within this coroutine
|
||||||
|
...
|
||||||
LL | let b = &a;
|
LL | let b = &a;
|
||||||
| ^^
|
| ^^
|
||||||
LL |
|
LL |
|
||||||
LL | yield ();
|
LL | yield ();
|
||||||
| -------- possible yield occurs here
|
| -------- 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,16 @@ LL | yield &s[..]
|
||||||
error[E0626]: borrow may still be in use when coroutine yields
|
error[E0626]: borrow may still be in use when coroutine yields
|
||||||
--> $DIR/issue-55850.rs:28:16
|
--> $DIR/issue-55850.rs:28:16
|
||||||
|
|
|
|
||||||
|
LL | GenIter(#[coroutine] move || {
|
||||||
|
| ------- within this coroutine
|
||||||
|
LL | let mut s = String::new();
|
||||||
LL | yield &s[..]
|
LL | yield &s[..]
|
||||||
| -------^---- possible yield occurs here
|
| -------^---- 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
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue