parent
1d284af117
commit
ce6b7179af
9 changed files with 75 additions and 36 deletions
|
@ -440,15 +440,14 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
closure_kind: &str,
|
closure_kind: &str,
|
||||||
borrowed_path: &str,
|
borrowed_path: &str,
|
||||||
capture_span: Span,
|
capture_span: Span,
|
||||||
|
scope: &str,
|
||||||
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
|
||||||
let mut err = struct_span_err!(
|
let mut err = struct_span_err!(
|
||||||
self,
|
self,
|
||||||
closure_span,
|
closure_span,
|
||||||
E0373,
|
E0373,
|
||||||
"{} may outlive the current function, but it borrows {}, which is owned by the current \
|
"{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \
|
||||||
function",
|
which is owned by the current {scope}",
|
||||||
closure_kind,
|
|
||||||
borrowed_path,
|
|
||||||
);
|
);
|
||||||
err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
|
err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
|
||||||
.span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
|
.span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
|
||||||
|
|
|
@ -1423,6 +1423,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
//
|
//
|
||||||
// then just use the normal error. The closure isn't escaping
|
// then just use the normal error. The closure isn't escaping
|
||||||
// and `move` will not help here.
|
// and `move` will not help here.
|
||||||
|
(
|
||||||
|
Some(name),
|
||||||
|
BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
|
||||||
|
) => self.report_escaping_closure_capture(
|
||||||
|
borrow_spans,
|
||||||
|
borrow_span,
|
||||||
|
&RegionName {
|
||||||
|
name: self.synthesize_region_name(),
|
||||||
|
source: RegionNameSource::Static,
|
||||||
|
},
|
||||||
|
ConstraintCategory::CallArgument(None),
|
||||||
|
var_or_use_span,
|
||||||
|
&format!("`{}`", name),
|
||||||
|
"block",
|
||||||
|
),
|
||||||
(
|
(
|
||||||
Some(name),
|
Some(name),
|
||||||
BorrowExplanation::MustBeValidFor {
|
BorrowExplanation::MustBeValidFor {
|
||||||
|
@ -1443,6 +1458,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
category,
|
category,
|
||||||
span,
|
span,
|
||||||
&format!("`{}`", name),
|
&format!("`{}`", name),
|
||||||
|
"function",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
name,
|
name,
|
||||||
|
@ -1895,6 +1911,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
Some(err)
|
Some(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn report_escaping_closure_capture(
|
fn report_escaping_closure_capture(
|
||||||
&mut self,
|
&mut self,
|
||||||
use_span: UseSpans<'tcx>,
|
use_span: UseSpans<'tcx>,
|
||||||
|
@ -1903,6 +1920,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
category: ConstraintCategory<'tcx>,
|
category: ConstraintCategory<'tcx>,
|
||||||
constraint_span: Span,
|
constraint_span: Span,
|
||||||
captured_var: &str,
|
captured_var: &str,
|
||||||
|
scope: &str,
|
||||||
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
) -> DiagnosticBuilder<'cx, ErrorGuaranteed> {
|
||||||
let tcx = self.infcx.tcx;
|
let tcx = self.infcx.tcx;
|
||||||
let args_span = use_span.args_or_use();
|
let args_span = use_span.args_or_use();
|
||||||
|
@ -1933,8 +1951,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
None => "closure",
|
None => "closure",
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut err =
|
let mut err = self.cannot_capture_in_long_lived_closure(
|
||||||
self.cannot_capture_in_long_lived_closure(args_span, kind, captured_var, var_span);
|
args_span,
|
||||||
|
kind,
|
||||||
|
captured_var,
|
||||||
|
var_span,
|
||||||
|
scope,
|
||||||
|
);
|
||||||
err.span_suggestion_verbose(
|
err.span_suggestion_verbose(
|
||||||
sugg_span,
|
sugg_span,
|
||||||
&format!(
|
&format!(
|
||||||
|
@ -1956,10 +1979,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
|
if matches!(use_span.generator_kind(), Some(GeneratorKind::Async(_))) {
|
||||||
err.note(
|
err.note(
|
||||||
"async blocks are not executed immediately and must either take a \
|
"async blocks are not executed immediately and must either take a \
|
||||||
reference or ownership of outside variables they use",
|
reference or ownership of outside variables they use",
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let msg = format!("function requires argument type to outlive `{}`", fr_name);
|
let msg = format!("{scope} requires argument type to outlive `{fr_name}`");
|
||||||
err.span_note(constraint_span, &msg);
|
err.span_note(constraint_span, &msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -444,6 +444,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
/// First span returned points to the location of the conflicting use
|
/// First span returned points to the location of the conflicting use
|
||||||
/// Second span if `Some` is returned in the case of closures and points
|
/// Second span if `Some` is returned in the case of closures and points
|
||||||
/// to the use of the path
|
/// to the use of the path
|
||||||
|
#[instrument(level = "debug", skip(self))]
|
||||||
fn later_use_kind(
|
fn later_use_kind(
|
||||||
&self,
|
&self,
|
||||||
borrow: &BorrowData<'tcx>,
|
borrow: &BorrowData<'tcx>,
|
||||||
|
@ -461,11 +462,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
let block = &self.body.basic_blocks[location.block];
|
let block = &self.body.basic_blocks[location.block];
|
||||||
|
|
||||||
let kind = if let Some(&Statement {
|
let kind = if let Some(&Statement {
|
||||||
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), _)),
|
kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)),
|
||||||
..
|
..
|
||||||
}) = block.statements.get(location.statement_index)
|
}) = block.statements.get(location.statement_index)
|
||||||
{
|
{
|
||||||
LaterUseKind::FakeLetRead
|
if let Some(l) = place.as_local()
|
||||||
|
&& let local_decl = &self.body.local_decls[l]
|
||||||
|
&& local_decl.ty.is_closure()
|
||||||
|
{
|
||||||
|
LaterUseKind::ClosureCapture
|
||||||
|
} else {
|
||||||
|
LaterUseKind::FakeLetRead
|
||||||
|
}
|
||||||
} else if self.was_captured_by_trait_object(borrow) {
|
} else if self.was_captured_by_trait_object(borrow) {
|
||||||
LaterUseKind::TraitCapture
|
LaterUseKind::TraitCapture
|
||||||
} else if location.statement_index == block.statements.len() {
|
} else if location.statement_index == block.statements.len() {
|
||||||
|
|
|
@ -200,7 +200,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
|
||||||
/// increment the counter.
|
/// increment the counter.
|
||||||
///
|
///
|
||||||
/// This is _not_ idempotent. Call `give_region_a_name` when possible.
|
/// This is _not_ idempotent. Call `give_region_a_name` when possible.
|
||||||
fn synthesize_region_name(&self) -> Symbol {
|
pub(crate) fn synthesize_region_name(&self) -> Symbol {
|
||||||
let c = self.next_region_name.replace_with(|counter| *counter + 1);
|
let c = self.next_region_name.replace_with(|counter| *counter + 1);
|
||||||
Symbol::intern(&format!("'{:?}", c))
|
Symbol::intern(&format!("'{:?}", c))
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,9 @@ struct Point {
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut c = {
|
let mut c = {
|
||||||
let mut p = Point {x: "1".to_string(), y: "2".to_string() };
|
let mut p = Point {x: "1".to_string(), y: "2".to_string() };
|
||||||
|| {
|
|| { //~ ERROR closure may outlive the current block, but it borrows `p`
|
||||||
let x = &mut p.x;
|
let x = &mut p.x;
|
||||||
println!("{:?}", p);
|
println!("{:?}", p);
|
||||||
//~^ ERROR `p` does not live long enough
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
c();
|
c();
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
error[E0597]: `p` does not live long enough
|
error[E0373]: closure may outlive the current block, but it borrows `p`, which is owned by the current block
|
||||||
--> $DIR/borrowck-3.rs:13:29
|
--> $DIR/borrowck-3.rs:11:9
|
||||||
|
|
|
|
||||||
LL | let mut c = {
|
|
||||||
| ----- borrow later stored here
|
|
||||||
LL | let mut p = Point {x: "1".to_string(), y: "2".to_string() };
|
|
||||||
LL | || {
|
LL | || {
|
||||||
| -- value captured here
|
| ^^ may outlive borrowed value `p`
|
||||||
LL | let x = &mut p.x;
|
LL | let x = &mut p.x;
|
||||||
LL | println!("{:?}", p);
|
LL | println!("{:?}", p);
|
||||||
| ^ borrowed value does not live long enough
|
| - `p` is borrowed here
|
||||||
...
|
|
|
||||||
LL | };
|
note: block requires argument type to outlive `'1`
|
||||||
| - `p` dropped here while still borrowed
|
--> $DIR/borrowck-3.rs:9:9
|
||||||
|
|
|
||||||
|
LL | let mut c = {
|
||||||
|
| ^^^^^
|
||||||
|
help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword
|
||||||
|
|
|
||||||
|
LL | move || {
|
||||||
|
| ++++
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0597`.
|
For more information about this error, try `rustc --explain E0373`.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
fn main() {
|
fn main() {
|
||||||
let _f = {
|
let _f = {
|
||||||
let x = 0;
|
let x = 0;
|
||||||
|| x //~ ERROR `x` does not live long enough
|
|| x //~ ERROR closure may outlive the current block, but it borrows `x`
|
||||||
};
|
};
|
||||||
_f;
|
_f;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
error[E0597]: `x` does not live long enough
|
error[E0373]: closure may outlive the current block, but it borrows `x`, which is owned by the current block
|
||||||
--> $DIR/unboxed-closure-region.rs:8:12
|
--> $DIR/unboxed-closure-region.rs:8:9
|
||||||
|
|
|
||||||
|
LL | || x
|
||||||
|
| ^^ - `x` is borrowed here
|
||||||
|
| |
|
||||||
|
| may outlive borrowed value `x`
|
||||||
|
|
|
||||||
|
note: block requires argument type to outlive `'1`
|
||||||
|
--> $DIR/unboxed-closure-region.rs:6:9
|
||||||
|
|
|
|
||||||
LL | let _f = {
|
LL | let _f = {
|
||||||
| -- borrow later stored here
|
| ^^
|
||||||
LL | let x = 0;
|
help: to force the closure to take ownership of `x` (and any other referenced variables), use the `move` keyword
|
||||||
LL | || x
|
|
|
||||||
| -- ^ borrowed value does not live long enough
|
LL | move || x
|
||||||
| |
|
| ++++
|
||||||
| value captured here
|
|
||||||
LL | };
|
|
||||||
| - `x` dropped here while still borrowed
|
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0597`.
|
For more information about this error, try `rustc --explain E0373`.
|
||||||
|
|
|
@ -20,6 +20,7 @@ fn bindings() {
|
||||||
category,
|
category,
|
||||||
span,
|
span,
|
||||||
&format!("`{}`", name),
|
&format!("`{}`", name),
|
||||||
|
"function",
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ref name,
|
ref name,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue