diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index a8feaa9ca94..186598001da 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -9,11 +9,14 @@ // except according to those terms. use syntax_pos::Span; +use rustc::middle::region::ScopeTree; use rustc::mir::{BorrowKind, Field, Local, Location, Operand}; use rustc::mir::{Place, ProjectionElem, Rvalue, StatementKind}; use rustc::ty::{self, RegionKind}; use rustc_data_structures::indexed_vec::Idx; +use std::rc::Rc; + use super::{MirBorrowckCtxt, Context}; use super::{InitializationRequiringAction, PrefixSet}; use dataflow::{BorrowData, Borrows, FlowAtLocation, MovingOutStatements}; @@ -354,64 +357,100 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => drop_span, }; - match &self.describe_place(&borrow.place) { - Some(description) => { - match borrow.region { - RegionKind::ReScope(_) => { - let mut err = self.tcx.path_does_not_live_long_enough( - drop_span, &format!("`{}`", description), Origin::Mir); - err.span_label(borrow_span, "borrow occurs here"); - err.span_label(drop_span, - format!("`{}` dropped here while still borrowed", - description)); - if let Some(end) = end_span { - err.span_label(end, "borrowed value needs to live until here"); - } - err.emit(); - }, - _ => { - let mut err = self.tcx.path_does_not_live_long_enough( - borrow_span, &format!("`{}`", description), Origin::Mir); - err.span_label(borrow_span, "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, "..."); - err.emit(); - } - } + match (borrow.region, &self.describe_place(&borrow.place)) { + (RegionKind::ReScope(_), Some(name)) => { + self.report_scoped_local_value_does_not_live_long_enough( + name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); }, - None => { - match borrow.region { - RegionKind::ReEarlyBound(_) | RegionKind::ReFree(_) => { - let mut err = self.tcx.path_does_not_live_long_enough(proper_span, - "borrowed value", - Origin::Mir); - err.span_label(proper_span, "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, "..."); - err.emit(); - }, - _ => { - let mut err = self.tcx.path_does_not_live_long_enough(drop_span, - "borrowed value", - Origin::Mir); - err.span_label(proper_span, "temporary value created here"); - 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"); - } - err.emit(); - }, - } + (RegionKind::ReScope(_), None) => { + self.report_scoped_temporary_value_does_not_live_long_enough( + &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); + }, + (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( + name, &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); + }, + (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( + &scope_tree, &borrow, drop_span, borrow_span, proper_span, end_span); + }, + (RegionKind::ReLateBound(_, _), _) | + (RegionKind::ReSkolemized(_, _), _) | + (RegionKind::ReErased, _) => { + span_bug!(drop_span, "region does not make sense in this context"); }, } } + fn report_scoped_local_value_does_not_live_long_enough( + &mut self, name: &String, _scope_tree: &Rc, _borrow: &BorrowData<'tcx>, + drop_span: Span, borrow_span: Span, _proper_span: Span, end_span: Option + ) { + let mut err = self.tcx.path_does_not_live_long_enough(drop_span, + &format!("`{}`", name), + Origin::Mir); + err.span_label(borrow_span, "borrow occurs here"); + 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"); + } + err.emit(); + } + + fn report_scoped_temporary_value_does_not_live_long_enough( + &mut self, _scope_tree: &Rc, _borrow: &BorrowData<'tcx>, + drop_span: Span, borrow_span: Span, proper_span: Span, end_span: Option + ) { + let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, + "borrowed value", + Origin::Mir); + err.span_label(proper_span, "temporary value created here"); + 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"); + } + err.emit(); + } + + fn report_unscoped_local_value_does_not_live_long_enough( + &mut self, name: &String, scope_tree: &Rc, borrow: &BorrowData<'tcx>, + drop_span: Span, borrow_span: Span, _proper_span: Span, _end_span: Option + ) { + let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, + &format!("`{}`", name), + Origin::Mir); + err.span_label(borrow_span, "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, "..."); + err.emit(); + } + + fn report_unscoped_temporary_value_does_not_live_long_enough( + &mut self, scope_tree: &Rc, borrow: &BorrowData<'tcx>, + drop_span: Span, _borrow_span: Span, proper_span: Span, _end_span: Option + ) { + let mut err = self.tcx.path_does_not_live_long_enough(proper_span, + "borrowed value", + Origin::Mir); + err.span_label(proper_span, "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, "..."); + err.emit(); + } + pub(super) fn report_illegal_mutation_of_borrowed( &mut self, _: Context,