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`](https://github.com/rust-lang/rust/issues/48428#issuecomment-367691123) - [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](https://github.com/rust-lang/rust/issues/48428#issue-299364536). - [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](https://github.com/rust-lang/rust/issues/48428#issuecomment-367691123). - [ ] Figure out how to enable causal information all the time (but that is https://github.com/rust-lang/rust/issues/46590).
This commit is contained in:
commit
259e4a6784
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,7 @@ use rustc::ty::{self, RegionKind};
|
||||
use rustc_data_structures::indexed_vec::Idx;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
|
||||
use super::{MirBorrowckCtxt, Context};
|
||||
use super::{Context, MirBorrowckCtxt};
|
||||
use super::{InitializationRequiringAction, PrefixSet};
|
||||
use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements};
|
||||
use dataflow::move_paths::MovePathIndex;
|
||||
@ -96,7 +96,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
} else {
|
||||
true
|
||||
}
|
||||
},
|
||||
}
|
||||
_ => true,
|
||||
};
|
||||
|
||||
@ -106,9 +106,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
None => "value".to_owned(),
|
||||
};
|
||||
|
||||
err.note(&format!("move occurs because {} has type `{}`, \
|
||||
which does not implement the `Copy` trait",
|
||||
note_msg, ty));
|
||||
err.note(&format!(
|
||||
"move occurs because {} has type `{}`, \
|
||||
which does not implement the `Copy` trait",
|
||||
note_msg, ty
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +156,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
span,
|
||||
&self.describe_place(place).unwrap_or("_".to_owned()),
|
||||
self.retrieve_borrow_span(borrow),
|
||||
&self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()),
|
||||
&self.describe_place(&borrow.borrowed_place)
|
||||
.unwrap_or("_".to_owned()),
|
||||
Origin::Mir,
|
||||
);
|
||||
|
||||
@ -175,8 +178,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
use rustc::hir::ExprClosure;
|
||||
use rustc::mir::AggregateKind;
|
||||
|
||||
let local = match self.mir[location.block].statements.get(location.statement_index) {
|
||||
Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local,
|
||||
let local = match self.mir[location.block]
|
||||
.statements
|
||||
.get(location.statement_index)
|
||||
{
|
||||
Some(&Statement {
|
||||
kind: StatementKind::Assign(Place::Local(local), _),
|
||||
..
|
||||
}) => local,
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
@ -202,8 +211,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
.with_freevars(node_id, |freevars| {
|
||||
for (v, place) in freevars.iter().zip(places) {
|
||||
match *place {
|
||||
Operand::Copy(Place::Local(l)) |
|
||||
Operand::Move(Place::Local(l)) if local == l =>
|
||||
Operand::Copy(Place::Local(l))
|
||||
| Operand::Move(Place::Local(l)) if local == l =>
|
||||
{
|
||||
debug!(
|
||||
"find_closure_span: found captured local {:?}",
|
||||
@ -232,7 +241,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
context: Context,
|
||||
(place, span): (&Place<'tcx>, Span),
|
||||
gen_borrow_kind: BorrowKind,
|
||||
issued_borrow: &BorrowData,
|
||||
issued_borrow: &BorrowData<'tcx>,
|
||||
end_issued_loan_span: Option<Span>,
|
||||
) {
|
||||
let issued_span = self.retrieve_borrow_span(issued_borrow);
|
||||
@ -255,8 +264,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
"immutable",
|
||||
"mutable",
|
||||
) {
|
||||
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) |
|
||||
(BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
|
||||
(BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt)
|
||||
| (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx
|
||||
.cannot_reborrow_already_borrowed(
|
||||
span,
|
||||
&desc_place,
|
||||
@ -355,11 +364,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
context: Context,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
drop_span: Span,
|
||||
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>
|
||||
borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>,
|
||||
) {
|
||||
let end_span = borrows.opt_region_end_span(&borrow.region);
|
||||
let scope_tree = borrows.0.scope_tree();
|
||||
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap();
|
||||
let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All)
|
||||
.last()
|
||||
.unwrap();
|
||||
|
||||
let borrow_span = self.mir.source_info(borrow.location).span;
|
||||
let proper_span = match *root_place {
|
||||
@ -367,13 +378,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
_ => drop_span,
|
||||
};
|
||||
|
||||
if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) {
|
||||
debug!("suppressing access_place error when borrow doesn't live long enough for {:?}",
|
||||
borrow_span);
|
||||
if self.access_place_error_reported
|
||||
.contains(&(root_place.clone(), borrow_span))
|
||||
{
|
||||
debug!(
|
||||
"suppressing access_place error when borrow doesn't live long enough for {:?}",
|
||||
borrow_span
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
self.access_place_error_reported.insert((root_place.clone(), borrow_span));
|
||||
self.access_place_error_reported
|
||||
.insert((root_place.clone(), borrow_span));
|
||||
|
||||
match (borrow.region, &self.describe_place(&borrow.borrowed_place)) {
|
||||
(RegionKind::ReScope(_), Some(name)) => {
|
||||
@ -385,9 +401,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
drop_span,
|
||||
borrow_span,
|
||||
proper_span,
|
||||
end_span
|
||||
end_span,
|
||||
);
|
||||
},
|
||||
}
|
||||
(RegionKind::ReScope(_), None) => {
|
||||
self.report_scoped_temporary_value_does_not_live_long_enough(
|
||||
context,
|
||||
@ -396,14 +412,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
drop_span,
|
||||
borrow_span,
|
||||
proper_span,
|
||||
end_span
|
||||
end_span,
|
||||
);
|
||||
},
|
||||
(RegionKind::ReEarlyBound(_), Some(name)) |
|
||||
(RegionKind::ReFree(_), Some(name)) |
|
||||
(RegionKind::ReStatic, Some(name)) |
|
||||
(RegionKind::ReEmpty, Some(name)) |
|
||||
(RegionKind::ReVar(_), Some(name)) => {
|
||||
}
|
||||
(RegionKind::ReEarlyBound(_), Some(name))
|
||||
| (RegionKind::ReFree(_), Some(name))
|
||||
| (RegionKind::ReStatic, Some(name))
|
||||
| (RegionKind::ReEmpty, Some(name))
|
||||
| (RegionKind::ReVar(_), Some(name)) => {
|
||||
self.report_unscoped_local_value_does_not_live_long_enough(
|
||||
context,
|
||||
name,
|
||||
@ -414,12 +430,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
proper_span,
|
||||
end_span,
|
||||
);
|
||||
},
|
||||
(RegionKind::ReEarlyBound(_), None) |
|
||||
(RegionKind::ReFree(_), None) |
|
||||
(RegionKind::ReStatic, None) |
|
||||
(RegionKind::ReEmpty, None) |
|
||||
(RegionKind::ReVar(_), None) => {
|
||||
}
|
||||
(RegionKind::ReEarlyBound(_), None)
|
||||
| (RegionKind::ReFree(_), None)
|
||||
| (RegionKind::ReStatic, None)
|
||||
| (RegionKind::ReEmpty, None)
|
||||
| (RegionKind::ReVar(_), None) => {
|
||||
self.report_unscoped_temporary_value_does_not_live_long_enough(
|
||||
context,
|
||||
&scope_tree,
|
||||
@ -429,13 +445,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
proper_span,
|
||||
end_span,
|
||||
);
|
||||
},
|
||||
(RegionKind::ReLateBound(_, _), _) |
|
||||
(RegionKind::ReSkolemized(_, _), _) |
|
||||
(RegionKind::ReClosureBound(_), _) |
|
||||
(RegionKind::ReErased, _) => {
|
||||
}
|
||||
(RegionKind::ReLateBound(_, _), _)
|
||||
| (RegionKind::ReSkolemized(_, _), _)
|
||||
| (RegionKind::ReClosureBound(_), _)
|
||||
| (RegionKind::ReErased, _) => {
|
||||
span_bug!(drop_span, "region does not make sense in this context");
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -450,11 +466,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
_proper_span: Span,
|
||||
end_span: Option<Span>,
|
||||
) {
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
|
||||
&format!("`{}`", name),
|
||||
Origin::Mir);
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(
|
||||
borrow_span,
|
||||
&format!("`{}`", name),
|
||||
Origin::Mir,
|
||||
);
|
||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||
err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name));
|
||||
err.span_label(
|
||||
drop_span,
|
||||
format!("`{}` dropped here while still borrowed", name),
|
||||
);
|
||||
if let Some(end) = end_span {
|
||||
err.span_label(end, "borrowed value needs to live until here");
|
||||
}
|
||||
@ -472,11 +493,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
proper_span: Span,
|
||||
end_span: Option<Span>,
|
||||
) {
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
|
||||
"borrowed value",
|
||||
Origin::Mir);
|
||||
let mut err =
|
||||
self.tcx
|
||||
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
||||
err.span_label(proper_span, "temporary value does not live long enough");
|
||||
err.span_label(drop_span, "temporary value dropped here while still borrowed");
|
||||
err.span_label(
|
||||
drop_span,
|
||||
"temporary value dropped here while still borrowed",
|
||||
);
|
||||
err.note("consider using a `let` binding to increase its lifetime");
|
||||
if let Some(end) = end_span {
|
||||
err.span_label(end, "temporary value needs to live until here");
|
||||
@ -496,14 +520,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
_proper_span: Span,
|
||||
_end_span: Option<Span>,
|
||||
) {
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(borrow_span,
|
||||
&format!("`{}`", name),
|
||||
Origin::Mir);
|
||||
debug!(
|
||||
"report_unscoped_local_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}, {:?}, {:?}\
|
||||
)",
|
||||
context, name, scope_tree, borrow, drop_span, borrow_span
|
||||
);
|
||||
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(
|
||||
borrow_span,
|
||||
&format!("`{}`", name),
|
||||
Origin::Mir,
|
||||
);
|
||||
err.span_label(borrow_span, "borrowed value does not live long enough");
|
||||
err.span_label(drop_span, "borrowed value only lives until here");
|
||||
self.tcx.note_and_explain_region(scope_tree, &mut err,
|
||||
"borrowed value must be valid for ",
|
||||
borrow.region, "...");
|
||||
|
||||
if !self.tcx.sess.nll() {
|
||||
self.tcx.note_and_explain_region(
|
||||
scope_tree,
|
||||
&mut err,
|
||||
"borrowed value must be valid for ",
|
||||
borrow.region,
|
||||
"...",
|
||||
);
|
||||
}
|
||||
|
||||
self.explain_why_borrow_contains_point(context, borrow, &mut err);
|
||||
err.emit();
|
||||
}
|
||||
@ -516,16 +557,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
drop_span: Span,
|
||||
_borrow_span: Span,
|
||||
proper_span: Span,
|
||||
_end_span: Option<Span>
|
||||
_end_span: Option<Span>,
|
||||
) {
|
||||
let mut err = self.tcx.path_does_not_live_long_enough(proper_span,
|
||||
"borrowed value",
|
||||
Origin::Mir);
|
||||
debug!(
|
||||
"report_unscoped_temporary_value_does_not_live_long_enough(\
|
||||
{:?}, {:?}, {:?}, {:?}, {:?}\
|
||||
)",
|
||||
context, scope_tree, borrow, drop_span, proper_span
|
||||
);
|
||||
|
||||
let mut err =
|
||||
self.tcx
|
||||
.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir);
|
||||
err.span_label(proper_span, "temporary value does not live long enough");
|
||||
err.span_label(drop_span, "temporary value only lives until here");
|
||||
self.tcx.note_and_explain_region(scope_tree, &mut err,
|
||||
"borrowed value must be valid for ",
|
||||
borrow.region, "...");
|
||||
|
||||
if !self.tcx.sess.nll() {
|
||||
self.tcx.note_and_explain_region(
|
||||
scope_tree,
|
||||
&mut err,
|
||||
"borrowed value must be valid for ",
|
||||
borrow.region,
|
||||
"...",
|
||||
);
|
||||
}
|
||||
|
||||
self.explain_why_borrow_contains_point(context, borrow, &mut err);
|
||||
err.emit();
|
||||
}
|
||||
@ -534,7 +590,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
&mut self,
|
||||
context: Context,
|
||||
(place, span): (&Place<'tcx>, Span),
|
||||
loan: &BorrowData,
|
||||
loan: &BorrowData<'tcx>,
|
||||
) {
|
||||
let mut err = self.tcx.cannot_assign_to_borrowed(
|
||||
span,
|
||||
@ -706,9 +762,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
ProjectionElem::Field(_, field_type) => {
|
||||
self.describe_field_from_ty(&field_type, field)
|
||||
}
|
||||
ProjectionElem::Index(..) |
|
||||
ProjectionElem::ConstantIndex { .. } |
|
||||
ProjectionElem::Subslice { .. } => {
|
||||
ProjectionElem::Index(..)
|
||||
| ProjectionElem::ConstantIndex { .. }
|
||||
| ProjectionElem::Subslice { .. } => {
|
||||
format!("{}", self.describe_field(&proj.base, field))
|
||||
}
|
||||
},
|
||||
@ -765,13 +821,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
Place::Local(local) => {
|
||||
let local = &self.mir.local_decls[*local];
|
||||
Some(local.ty)
|
||||
},
|
||||
}
|
||||
Place::Static(ref st) => Some(st.ty),
|
||||
Place::Projection(ref proj) => {
|
||||
match proj.elem {
|
||||
ProjectionElem::Field(_, ty) => Some(ty),
|
||||
_ => None,
|
||||
}
|
||||
Place::Projection(ref proj) => match proj.elem {
|
||||
ProjectionElem::Field(_, ty) => Some(ty),
|
||||
_ => None,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
pub(in borrow_check) fn explain_why_borrow_contains_point(
|
||||
&self,
|
||||
context: Context,
|
||||
borrow: &BorrowData<'_>,
|
||||
borrow: &BorrowData<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
if let Some(regioncx) = &self.nonlexical_regioncx {
|
||||
@ -70,9 +70,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
_ => {
|
||||
cause.label_diagnostic(mir, err);
|
||||
Cause::UniversalRegion(region_vid) => {
|
||||
if let Some(region) = regioncx.to_error_region(region_vid) {
|
||||
self.tcx.note_and_explain_free_region(
|
||||
err,
|
||||
"borrowed value must be valid for ",
|
||||
region,
|
||||
"...",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@ use rustc::ty::{self, RegionVid, Ty, TypeFoldable};
|
||||
use rustc::util::common::ErrorReported;
|
||||
use rustc_data_structures::bitvec::BitVector;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use std::fmt;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
@ -435,7 +434,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut());
|
||||
|
||||
self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut());
|
||||
self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut());
|
||||
|
||||
let outlives_requirements = outlives_requirements.unwrap_or(vec![]);
|
||||
|
||||
@ -574,10 +573,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// an error that multiple bounds are required.
|
||||
tcx.sess.span_err(
|
||||
type_test.span,
|
||||
&format!(
|
||||
"`{}` does not live long enough",
|
||||
type_test.generic_kind,
|
||||
),
|
||||
&format!("`{}` does not live long enough", type_test.generic_kind,),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -589,13 +585,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
/// existentially bound, then we check its inferred value and try
|
||||
/// to find a good name from that. Returns `None` if we can't find
|
||||
/// one (e.g., this is just some random part of the CFG).
|
||||
fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
pub fn to_error_region(&self, r: RegionVid) -> Option<ty::Region<'tcx>> {
|
||||
if self.universal_regions.is_universal_region(r) {
|
||||
return self.definitions[r].external_name;
|
||||
} else {
|
||||
let inferred_values = self.inferred_values
|
||||
.as_ref()
|
||||
.expect("region values not yet inferred");
|
||||
.as_ref()
|
||||
.expect("region values not yet inferred");
|
||||
let upper_bound = self.universal_upper_bound(r);
|
||||
if inferred_values.contains(r, upper_bound) {
|
||||
self.to_error_region(upper_bound)
|
||||
@ -807,9 +803,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
) -> bool {
|
||||
debug!(
|
||||
"eval_region_test(point={:?}, lower_bound={:?}, test={:?})",
|
||||
point,
|
||||
lower_bound,
|
||||
test
|
||||
point, lower_bound, test
|
||||
);
|
||||
|
||||
match test {
|
||||
@ -841,9 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
) -> bool {
|
||||
debug!(
|
||||
"eval_outlives({:?}: {:?} @ {:?})",
|
||||
sup_region,
|
||||
sub_region,
|
||||
point
|
||||
sup_region, sub_region, point
|
||||
);
|
||||
|
||||
// Roughly speaking, do a DFS of all region elements reachable
|
||||
@ -897,7 +889,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn check_universal_regions<'gcx>(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
mir_def_id: DefId,
|
||||
mut propagated_outlives_requirements: Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||
) {
|
||||
@ -913,7 +904,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
for (fr, _) in universal_definitions {
|
||||
self.check_universal_region(
|
||||
infcx,
|
||||
mir,
|
||||
mir_def_id,
|
||||
fr,
|
||||
&mut propagated_outlives_requirements,
|
||||
@ -932,7 +922,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn check_universal_region<'gcx>(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, 'gcx, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
mir_def_id: DefId,
|
||||
longer_fr: RegionVid,
|
||||
propagated_outlives_requirements: &mut Option<&mut Vec<ClosureOutlivesRequirement<'gcx>>>,
|
||||
@ -951,8 +940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
|
||||
debug!(
|
||||
"check_universal_region: fr={:?} does not outlive shorter_fr={:?}",
|
||||
longer_fr,
|
||||
shorter_fr,
|
||||
longer_fr, shorter_fr,
|
||||
);
|
||||
|
||||
let blame_span = self.blame_span(longer_fr, shorter_fr);
|
||||
@ -990,7 +978,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
// Note: in this case, we use the unapproximated regions
|
||||
// to report the error. This gives better error messages
|
||||
// in some cases.
|
||||
self.report_error(infcx, mir, mir_def_id, longer_fr, shorter_fr, blame_span);
|
||||
self.report_error(infcx, mir_def_id, longer_fr, shorter_fr, blame_span);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1005,7 +993,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
fn report_error(
|
||||
&self,
|
||||
infcx: &InferCtxt<'_, '_, 'tcx>,
|
||||
mir: &Mir<'tcx>,
|
||||
mir_def_id: DefId,
|
||||
fr: RegionVid,
|
||||
outlived_fr: RegionVid,
|
||||
@ -1039,12 +1026,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||
&format!("{} does not outlive {}", fr_string, outlived_fr_string,),
|
||||
);
|
||||
|
||||
// Find out why `fr` had to outlive `outlived_fr`...
|
||||
let inferred_values = self.inferred_values.as_ref().unwrap();
|
||||
if let Some(cause) = inferred_values.cause(fr, outlived_fr) {
|
||||
cause.label_diagnostic(mir, &mut diag);
|
||||
}
|
||||
|
||||
diag.emit();
|
||||
}
|
||||
|
||||
@ -1134,10 +1115,7 @@ impl fmt::Debug for Constraint {
|
||||
write!(
|
||||
formatter,
|
||||
"({:?}: {:?} @ {:?}) due to {:?}",
|
||||
self.sup,
|
||||
self.sub,
|
||||
self.point,
|
||||
self.span
|
||||
self.sup, self.sub, self.point, self.span
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1187,9 +1165,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
|
||||
|
||||
debug!(
|
||||
"apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})",
|
||||
location,
|
||||
closure_def_id,
|
||||
closure_substs
|
||||
location, closure_def_id, closure_substs
|
||||
);
|
||||
|
||||
// Get Tu.
|
||||
@ -1217,9 +1193,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
|
||||
"apply_requirements: region={:?} \
|
||||
outlived_region={:?} \
|
||||
outlives_requirement={:?}",
|
||||
region,
|
||||
outlived_region,
|
||||
outlives_requirement,
|
||||
region, outlived_region, outlives_requirement,
|
||||
);
|
||||
infcx.sub_regions(origin, outlived_region, region);
|
||||
}
|
||||
@ -1230,9 +1204,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi
|
||||
"apply_requirements: ty={:?} \
|
||||
outlived_region={:?} \
|
||||
outlives_requirement={:?}",
|
||||
ty,
|
||||
outlived_region,
|
||||
outlives_requirement,
|
||||
ty, outlived_region, outlives_requirement,
|
||||
);
|
||||
infcx.register_region_obligation(
|
||||
body_id,
|
||||
@ -1285,77 +1257,14 @@ impl CauseExt for Rc<Cause> {
|
||||
}
|
||||
|
||||
impl Cause {
|
||||
pub(crate) fn label_diagnostic(&self, mir: &Mir<'_>, diag: &mut DiagnosticBuilder<'_>) {
|
||||
// The cause information is pretty messy. Only dump it as an
|
||||
// internal debugging aid if -Znll-dump-cause is given.
|
||||
let nll_dump_cause = ty::tls::with(|tcx| tcx.sess.nll_dump_cause());
|
||||
if !nll_dump_cause {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut string = String::new();
|
||||
self.push_diagnostic_string(mir, &mut string);
|
||||
diag.note(&string);
|
||||
}
|
||||
|
||||
fn push_diagnostic_string(&self, mir: &Mir<'_>, string: &mut String) {
|
||||
match self {
|
||||
Cause::LiveVar(local, location) => {
|
||||
string.push_str(&format!("because `{:?}` is live at {:?}", local, location));
|
||||
}
|
||||
|
||||
Cause::DropVar(local, location) => {
|
||||
string.push_str(&format!(
|
||||
"because `{:?}` is dropped at {:?}",
|
||||
local,
|
||||
location
|
||||
));
|
||||
}
|
||||
|
||||
Cause::LiveOther(location) => {
|
||||
string.push_str(&format!(
|
||||
"because of a general liveness constraint at {:?}",
|
||||
location
|
||||
));
|
||||
}
|
||||
|
||||
Cause::UniversalRegion(region_vid) => {
|
||||
string.push_str(&format!(
|
||||
"because `{:?}` is universally quantified",
|
||||
region_vid
|
||||
));
|
||||
}
|
||||
|
||||
Cause::Outlives {
|
||||
original_cause,
|
||||
constraint_location,
|
||||
constraint_span: _,
|
||||
} => {
|
||||
string.push_str(&format!(
|
||||
"because of an outlives relation created at `{:?}`\n",
|
||||
constraint_location
|
||||
));
|
||||
|
||||
original_cause.push_diagnostic_string(mir, string);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn root_cause(&self) -> &Cause {
|
||||
match self {
|
||||
Cause::LiveVar(..) |
|
||||
Cause::DropVar(..) |
|
||||
Cause::LiveOther(..) |
|
||||
Cause::UniversalRegion(..) => {
|
||||
self
|
||||
}
|
||||
Cause::LiveVar(..)
|
||||
| Cause::DropVar(..)
|
||||
| Cause::LiveOther(..)
|
||||
| Cause::UniversalRegion(..) => self,
|
||||
|
||||
Cause::Outlives {
|
||||
original_cause,
|
||||
..
|
||||
} => {
|
||||
original_cause.root_cause()
|
||||
}
|
||||
Cause::Outlives { original_cause, .. } => original_cause.root_cause(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
26
src/test/ui/nll/borrowed-local-error.rs
Normal file
26
src/test/ui/nll/borrowed-local-error.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Znll-dump-cause
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
fn gimme(x: &(u32,)) -> &u32 {
|
||||
&x.0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = gimme({
|
||||
let v = (22,);
|
||||
&v
|
||||
//~^ ERROR `v` does not live long enough [E0597]
|
||||
});
|
||||
println!("{:?}", x);
|
||||
}
|
17
src/test/ui/nll/borrowed-local-error.stderr
Normal file
17
src/test/ui/nll/borrowed-local-error.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0597]: `v` does not live long enough
|
||||
--> $DIR/borrowed-local-error.rs:22:9
|
||||
|
|
||||
LL | let x = gimme({
|
||||
| _____________-
|
||||
LL | | let v = (22,);
|
||||
LL | | &v
|
||||
| | ^^ borrowed value does not live long enough
|
||||
LL | | //~^ ERROR `v` does not live long enough [E0597]
|
||||
LL | | });
|
||||
| |_____-- borrow later used here
|
||||
| |
|
||||
| borrowed value only lives until here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0597"
|
26
src/test/ui/nll/borrowed-temporary-error.rs
Normal file
26
src/test/ui/nll/borrowed-temporary-error.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Znll-dump-cause
|
||||
|
||||
#![feature(nll)]
|
||||
|
||||
fn gimme(x: &(u32,)) -> &u32 {
|
||||
&x.0
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let x = gimme({
|
||||
let v = 22;
|
||||
&(v,)
|
||||
//~^ ERROR borrowed value does not live long enough [E0597]
|
||||
});
|
||||
println!("{:?}", x);
|
||||
}
|
14
src/test/ui/nll/borrowed-temporary-error.stderr
Normal file
14
src/test/ui/nll/borrowed-temporary-error.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowed-temporary-error.rs:22:10
|
||||
|
|
||||
LL | &(v,)
|
||||
| ^^^^ temporary value does not live long enough
|
||||
LL | //~^ ERROR borrowed value does not live long enough [E0597]
|
||||
LL | });
|
||||
| - temporary value only lives until here
|
||||
LL | println!("{:?}", x);
|
||||
| - borrow later used here
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0597"
|
22
src/test/ui/nll/borrowed-universal-error-2.rs
Normal file
22
src/test/ui/nll/borrowed-universal-error-2.rs
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Znll-dump-cause
|
||||
|
||||
#![feature(nll)]
|
||||
#![allow(warnings)]
|
||||
|
||||
fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||
let v = 22;
|
||||
&v
|
||||
//~^ ERROR `v` does not live long enough [E0597]
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/ui/nll/borrowed-universal-error-2.stderr
Normal file
18
src/test/ui/nll/borrowed-universal-error-2.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error[E0597]: `v` does not live long enough
|
||||
--> $DIR/borrowed-universal-error-2.rs:18:5
|
||||
|
|
||||
LL | &v
|
||||
| ^^ borrowed value does not live long enough
|
||||
LL | //~^ ERROR `v` does not live long enough [E0597]
|
||||
LL | }
|
||||
| - borrowed value only lives until here
|
||||
|
|
||||
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 16:1...
|
||||
--> $DIR/borrowed-universal-error-2.rs:16:1
|
||||
|
|
||||
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0597"
|
26
src/test/ui/nll/borrowed-universal-error.rs
Normal file
26
src/test/ui/nll/borrowed-universal-error.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// compile-flags: -Znll-dump-cause
|
||||
|
||||
#![feature(nll)]
|
||||
#![allow(warnings)]
|
||||
|
||||
fn gimme(x: &(u32,)) -> &u32 {
|
||||
&x.0
|
||||
}
|
||||
|
||||
fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||
let v = 22;
|
||||
gimme(&(v,))
|
||||
//~^ ERROR borrowed value does not live long enough [E0597]
|
||||
}
|
||||
|
||||
fn main() {}
|
18
src/test/ui/nll/borrowed-universal-error.stderr
Normal file
18
src/test/ui/nll/borrowed-universal-error.stderr
Normal file
@ -0,0 +1,18 @@
|
||||
error[E0597]: borrowed value does not live long enough
|
||||
--> $DIR/borrowed-universal-error.rs:22:12
|
||||
|
|
||||
LL | gimme(&(v,))
|
||||
| ^^^^ temporary value does not live long enough
|
||||
LL | //~^ ERROR borrowed value does not live long enough [E0597]
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:1...
|
||||
--> $DIR/borrowed-universal-error.rs:20:1
|
||||
|
|
||||
LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
If you want more information on this error, try using "rustc --explain E0597"
|
@ -9,8 +9,6 @@ LL | }
|
||||
LL |
|
||||
LL | deref(p);
|
||||
| - borrow later used here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#5r...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -34,8 +34,6 @@ LL | }
|
||||
LL |
|
||||
LL | deref(p);
|
||||
| - borrow later used here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#6r...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -61,8 +61,6 @@ LL | }
|
||||
LL |
|
||||
LL | deref(p);
|
||||
| - borrow later used here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#4r...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -38,8 +38,6 @@ LL | }
|
||||
LL |
|
||||
LL | deref(p);
|
||||
| - borrow later used here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#4r...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -78,8 +78,6 @@ LL | let cell = Cell::new(&a);
|
||||
...
|
||||
LL | }
|
||||
| - borrowed value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#2r...
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -6,8 +6,6 @@ LL | let ref mut x = 1234543; //~ ERROR borrowed value does not live long en
|
||||
LL | x
|
||||
LL | }
|
||||
| - temporary value only lives until here
|
||||
|
|
||||
= note: borrowed value must be valid for lifetime '_#2r...
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user