Skip to content

Commit 259e4a6

Browse files
committed
Auto merge of #48592 - spastorino:borrowed_value_error, r=nikomatsakis
[NLL] Avoid borrowed value must be valid for lifetime '_#2r..." in errors Closes #48428 - [x] If NLL is enabled, [do not invoke `note_and_explain_region`](#48428 (comment)) - [x] Modify `-Zdump-nll-cause` to not print [the overwhelming debug output here](https://github.com/rust-lang/rust/blob/master/src/librustc_mir/borrow_check/nll/region_infer/mod.rs#L1288-L1299). This way we should I believe at least get nice-ish output for [our original example](#48428 (comment)). - [x] Extend `explain_why_borrow_contains_point` to also work for "universal lifetimes" like the `'a` in [the example at the end of this comment](#48428 (comment)). - [ ] Figure out how to enable causal information all the time (but that is #46590).
2 parents 1e1bfc7 + 99c42dc commit 259e4a6

18 files changed

+787
-563
lines changed

src/librustc/infer/error_reporting/mod.rs

+465-368
Large diffs are not rendered by default.

src/librustc_mir/borrow_check/error_reporting.rs

+125-71
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use rustc::ty::{self, RegionKind};
1616
use rustc_data_structures::indexed_vec::Idx;
1717
use rustc_data_structures::sync::Lrc;
1818

19-
use super::{MirBorrowckCtxt, Context};
19+
use super::{Context, MirBorrowckCtxt};
2020
use super::{InitializationRequiringAction, PrefixSet};
2121
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
2222
use dataflow::move_paths::MovePathIndex;
@@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
9696
} else {
9797
true
9898
}
99-
},
99+
}
100100
_ => true,
101101
};
102102

@@ -106,9 +106,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
106106
None => "value".to_owned(),
107107
};
108108

109-
err.note(&format!("move occurs because {} has type `{}`, \
110-
which does not implement the `Copy` trait",
111-
note_msg, ty));
109+
err.note(&format!(
110+
"move occurs because {} has type `{}`, \
111+
which does not implement the `Copy` trait",
112+
note_msg, ty
113+
));
112114
}
113115
}
114116

@@ -154,7 +156,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
154156
span,
155157
&self.describe_place(place).unwrap_or("_".to_owned()),
156158
self.retrieve_borrow_span(borrow),
157-
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
159+
&self.describe_place(&borrow.borrowed_place)
160+
.unwrap_or("_".to_owned()),
158161
Origin::Mir,
159162
);
160163

@@ -175,8 +178,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
175178
use rustc::hir::ExprClosure;
176179
use rustc::mir::AggregateKind;
177180

178-
let local = match self.mir[location.block].statements.get(location.statement_index) {
179-
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
181+
let local = match self.mir[location.block]
182+
.statements
183+
.get(location.statement_index)
184+
{
185+
Some(&Statement {
186+
kind: StatementKind::Assign(Place::Local(local), _),
187+
..
188+
}) => local,
180189
_ => return None,
181190
};
182191

@@ -202,8 +211,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
202211
.with_freevars(node_id, |freevars| {
203212
for (v, place) in freevars.iter().zip(places) {
204213
match *place {
205-
Operand::Copy(Place::Local(l)) |
206-
Operand::Move(Place::Local(l)) if local == l =>
214+
Operand::Copy(Place::Local(l))
215+
| Operand::Move(Place::Local(l)) if local == l =>
207216
{
208217
debug!(
209218
"find_closure_span: found captured local {:?}",
@@ -232,7 +241,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
232241
context: Context,
233242
(place, span): (&Place<'tcx>, Span),
234243
gen_borrow_kind: BorrowKind,
235-
issued_borrow: &BorrowData,
244+
issued_borrow: &BorrowData<'tcx>,
236245
end_issued_loan_span: Option<Span>,
237246
) {
238247
let issued_span = self.retrieve_borrow_span(issued_borrow);
@@ -255,8 +264,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
255264
"immutable",
256265
"mutable",
257266
) {
258-
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
259-
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
267+
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
268+
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
260269
.cannot_reborrow_already_borrowed(
261270
span,
262271
&desc_place,
@@ -355,25 +364,32 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
355364
context: Context,
356365
borrow: &BorrowData<'tcx>,
357366
drop_span: Span,
358-
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>
367+
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>,
359368
) {
360369
let end_span = borrows.opt_region_end_span(&borrow.region);
361370
let scope_tree = borrows.0.scope_tree();
362-
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
371+
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
372+
.last()
373+
.unwrap();
363374

364375
let borrow_span = self.mir.source_info(borrow.location).span;
365376
let proper_span = match *root_place {
366377
Place::Local(local) => self.mir.local_decls[local].source_info.span,
367378
_ => drop_span,
368379
};
369380

370-
if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) {
371-
debug!("suppressing access_place error when borrow doesn't live long enough for {:?}",
372-
borrow_span);
381+
if self.access_place_error_reported
382+
.contains(&(root_place.clone(), borrow_span))
383+
{
384+
debug!(
385+
"suppressing access_place error when borrow doesn't live long enough for {:?}",
386+
borrow_span
387+
);
373388
return;
374389
}
375390

376-
self.access_place_error_reported.insert((root_place.clone(), borrow_span));
391+
self.access_place_error_reported
392+
.insert((root_place.clone(), borrow_span));
377393

378394
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
379395
(RegionKind::ReScope(_), Some(name)) => {
@@ -385,9 +401,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
385401
drop_span,
386402
borrow_span,
387403
proper_span,
388-
end_span
404+
end_span,
389405
);
390-
},
406+
}
391407
(RegionKind::ReScope(_), None) => {
392408
self.report_scoped_temporary_value_does_not_live_long_enough(
393409
context,
@@ -396,14 +412,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
396412
drop_span,
397413
borrow_span,
398414
proper_span,
399-
end_span
415+
end_span,
400416
);
401-
},
402-
(RegionKind::ReEarlyBound(_), Some(name)) |
403-
(RegionKind::ReFree(_), Some(name)) |
404-
(RegionKind::ReStatic, Some(name)) |
405-
(RegionKind::ReEmpty, Some(name)) |
406-
(RegionKind::ReVar(_), Some(name)) => {
417+
}
418+
(RegionKind::ReEarlyBound(_), Some(name))
419+
| (RegionKind::ReFree(_), Some(name))
420+
| (RegionKind::ReStatic, Some(name))
421+
| (RegionKind::ReEmpty, Some(name))
422+
| (RegionKind::ReVar(_), Some(name)) => {
407423
self.report_unscoped_local_value_does_not_live_long_enough(
408424
context,
409425
name,
@@ -414,12 +430,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
414430
proper_span,
415431
end_span,
416432
);
417-
},
418-
(RegionKind::ReEarlyBound(_), None) |
419-
(RegionKind::ReFree(_), None) |
420-
(RegionKind::ReStatic, None) |
421-
(RegionKind::ReEmpty, None) |
422-
(RegionKind::ReVar(_), None) => {
433+
}
434+
(RegionKind::ReEarlyBound(_), None)
435+
| (RegionKind::ReFree(_), None)
436+
| (RegionKind::ReStatic, None)
437+
| (RegionKind::ReEmpty, None)
438+
| (RegionKind::ReVar(_), None) => {
423439
self.report_unscoped_temporary_value_does_not_live_long_enough(
424440
context,
425441
&scope_tree,
@@ -429,13 +445,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
429445
proper_span,
430446
end_span,
431447
);
432-
},
433-
(RegionKind::ReLateBound(_, _), _) |
434-
(RegionKind::ReSkolemized(_, _), _) |
435-
(RegionKind::ReClosureBound(_), _) |
436-
(RegionKind::ReErased, _) => {
448+
}
449+
(RegionKind::ReLateBound(_, _), _)
450+
| (RegionKind::ReSkolemized(_, _), _)
451+
| (RegionKind::ReClosureBound(_), _)
452+
| (RegionKind::ReErased, _) => {
437453
span_bug!(drop_span, "region does not make sense in this context");
438-
},
454+
}
439455
}
440456
}
441457

@@ -450,11 +466,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
450466
_proper_span: Span,
451467
end_span: Option<Span>,
452468
) {
453-
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
454-
&format!("`{}`", name),
455-
Origin::Mir);
469+
let mut err = self.tcx.path_does_not_live_long_enough(
470+
borrow_span,
471+
&format!("`{}`", name),
472+
Origin::Mir,
473+
);
456474
err.span_label(borrow_span, "borrowed value does not live long enough");
457-
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
475+
err.span_label(
476+
drop_span,
477+
format!("`{}` dropped here while still borrowed", name),
478+
);
458479
if let Some(end) = end_span {
459480
err.span_label(end, "borrowed value needs to live until here");
460481
}
@@ -472,11 +493,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
472493
proper_span: Span,
473494
end_span: Option<Span>,
474495
) {
475-
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
476-
"borrowed value",
477-
Origin::Mir);
496+
let mut err =
497+
self.tcx
498+
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
478499
err.span_label(proper_span, "temporary value does not live long enough");
479-
err.span_label(drop_span, "temporary value dropped here while still borrowed");
500+
err.span_label(
501+
drop_span,
502+
"temporary value dropped here while still borrowed",
503+
);
480504
err.note("consider using a `let` binding to increase its lifetime");
481505
if let Some(end) = end_span {
482506
err.span_label(end, "temporary value needs to live until here");
@@ -496,14 +520,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
496520
_proper_span: Span,
497521
_end_span: Option<Span>,
498522
) {
499-
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
500-
&format!("`{}`", name),
501-
Origin::Mir);
523+
debug!(
524+
"report_unscoped_local_value_does_not_live_long_enough(\
525+
{:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
526+
)",
527+
context, name, scope_tree, borrow, drop_span, borrow_span
528+
);
529+
530+
let mut err = self.tcx.path_does_not_live_long_enough(
531+
borrow_span,
532+
&format!("`{}`", name),
533+
Origin::Mir,
534+
);
502535
err.span_label(borrow_span, "borrowed value does not live long enough");
503536
err.span_label(drop_span, "borrowed value only lives until here");
504-
self.tcx.note_and_explain_region(scope_tree, &mut err,
505-
"borrowed value must be valid for ",
506-
borrow.region, "...");
537+
538+
if !self.tcx.sess.nll() {
539+
self.tcx.note_and_explain_region(
540+
scope_tree,
541+
&mut err,
542+
"borrowed value must be valid for ",
543+
borrow.region,
544+
"...",
545+
);
546+
}
547+
507548
self.explain_why_borrow_contains_point(context, borrow, &mut err);
508549
err.emit();
509550
}
@@ -516,16 +557,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
516557
drop_span: Span,
517558
_borrow_span: Span,
518559
proper_span: Span,
519-
_end_span: Option<Span>
560+
_end_span: Option<Span>,
520561
) {
521-
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
522-
"borrowed value",
523-
Origin::Mir);
562+
debug!(
563+
"report_unscoped_temporary_value_does_not_live_long_enough(\
564+
{:?}, {:?}, {:?}, {:?}, {:?}\
565+
)",
566+
context, scope_tree, borrow, drop_span, proper_span
567+
);
568+
569+
let mut err =
570+
self.tcx
571+
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
524572
err.span_label(proper_span, "temporary value does not live long enough");
525573
err.span_label(drop_span, "temporary value only lives until here");
526-
self.tcx.note_and_explain_region(scope_tree, &mut err,
527-
"borrowed value must be valid for ",
528-
borrow.region, "...");
574+
575+
if !self.tcx.sess.nll() {
576+
self.tcx.note_and_explain_region(
577+
scope_tree,
578+
&mut err,
579+
"borrowed value must be valid for ",
580+
borrow.region,
581+
"...",
582+
);
583+
}
584+
529585
self.explain_why_borrow_contains_point(context, borrow, &mut err);
530586
err.emit();
531587
}
@@ -534,7 +590,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
534590
&mut self,
535591
context: Context,
536592
(place, span): (&Place<'tcx>, Span),
537-
loan: &BorrowData,
593+
loan: &BorrowData<'tcx>,
538594
) {
539595
let mut err = self.tcx.cannot_assign_to_borrowed(
540596
span,
@@ -706,9 +762,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
706762
ProjectionElem::Field(_, field_type) => {
707763
self.describe_field_from_ty(&field_type, field)
708764
}
709-
ProjectionElem::Index(..) |
710-
ProjectionElem::ConstantIndex { .. } |
711-
ProjectionElem::Subslice { .. } => {
765+
ProjectionElem::Index(..)
766+
| ProjectionElem::ConstantIndex { .. }
767+
| ProjectionElem::Subslice { .. } => {
712768
format!("{}", self.describe_field(&proj.base, field))
713769
}
714770
},
@@ -765,13 +821,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
765821
Place::Local(local) => {
766822
let local = &self.mir.local_decls[*local];
767823
Some(local.ty)
768-
},
824+
}
769825
Place::Static(ref st) => Some(st.ty),
770-
Place::Projection(ref proj) => {
771-
match proj.elem {
772-
ProjectionElem::Field(_, ty) => Some(ty),
773-
_ => None,
774-
}
826+
Place::Projection(ref proj) => match proj.elem {
827+
ProjectionElem::Field(_, ty) => Some(ty),
828+
_ => None,
775829
},
776830
}
777831
}

src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
2121
pub(in borrow_check) fn explain_why_borrow_contains_point(
2222
&self,
2323
context: Context,
24-
borrow: &BorrowData<'_>,
24+
borrow: &BorrowData<'tcx>,
2525
err: &mut DiagnosticBuilder<'_>,
2626
) {
2727
if let Some(regioncx) = &self.nonlexical_regioncx {
@@ -70,9 +70,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
7070
}
7171
}
7272

73-
_ => {
74-
cause.label_diagnostic(mir, err);
73+
Cause::UniversalRegion(region_vid) => {
74+
if let Some(region) = regioncx.to_error_region(region_vid) {
75+
self.tcx.note_and_explain_free_region(
76+
err,
77+
"borrowed value must be valid for ",
78+
region,
79+
"...",
80+
);
81+
}
7582
}
83+
84+
_ => {}
7685
}
7786
}
7887
}

0 commit comments

Comments
 (0)