From cbcae7f69414fd0e5de6bad771df12bfde4f2908 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 3 Dec 2017 17:55:41 +0200 Subject: [PATCH] improve conflict error reporting --- src/librustc_mir/borrow_check/mod.rs | 28 +++++++++++++------ .../borrowck-local-borrow-outlives-fn.rs | 2 +- ...wck-local-borrow-with-panic-outlives-fn.rs | 2 +- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 890680b8b293b..61e7eb5933915 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -548,14 +548,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx if self.place_is_invalidated_at_exit(&borrow.place) { debug!("borrow conflicts at exit {:?}", borrow); - let borrow_span = self.mir.source_info(borrow.location).span; // FIXME: should be talking about the region lifetime instead // of just a span here. let end_span = domain.opt_region_end_span(&borrow.region); self.report_borrowed_value_does_not_live_long_enough( ContextKind::StorageDead.new(loc), - (&borrow.place, borrow_span), + (&borrow.place, end_span.unwrap_or(span)), end_span, ) } @@ -958,7 +957,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// Returns whether a borrow of this place is invalidated when the function /// exits - fn place_is_invalidated_at_exit(&self, place: &Place<'tcx>) -> bool { + fn place_is_invalidated_at_exit(&mut self, place: &Place<'tcx>) -> bool { debug!("place_is_invalidated_at_exit({:?})", place); let root_place = self.prefixes(place, PrefixSet::All).last().unwrap(); @@ -967,7 +966,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // we'll have a memory leak) and assume that all statics have a destructor. // // FIXME: allow thread-locals to borrow other thread locals?x - let (might_be_alive, will_be_dropped) = match root_place { + let (might_be_alive, will_be_dropped, local) = match root_place { Place::Static(statik) => { // Thread-locals might be dropped after the function exits, but // "true" statics will never be. @@ -976,12 +975,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .iter() .any(|attr| attr.check_name("thread_local")); - (true, is_thread_local) + (true, is_thread_local, None) } - Place::Local(_) => { + Place::Local(local) => { // Locals are always dropped at function exit, and if they // have a destructor it would've been called already. - (false, self.locals_are_invalidated_at_exit) + (false, self.locals_are_invalidated_at_exit, Some(*local)) } Place::Projection(..) => { bug!("root of {:?} is a projection ({:?})?", place, root_place) @@ -1004,8 +1003,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { PrefixSet::Shallow }; - self.prefixes(place, prefix_set) - .any(|prefix| prefix == root_place) + let result = + self.prefixes(place, prefix_set).any(|prefix| prefix == root_place); + + if result { + if let Some(local) = local { + if let Some(_) = self.storage_dead_or_drop_error_reported.replace(local) { + debug!("place_is_invalidated_at_exit({:?}) - suppressed", place); + return false; + } + } + } + + result } } diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs index 3f5725029d887..fa80a2efdf83d 100644 --- a/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-outlives-fn.rs @@ -13,7 +13,7 @@ fn cplusplus_mode(x: isize) -> &'static isize { &x //[ast]~ ERROR `x` does not live long enough - //[mir]~^ ERROR borrowed value does not live long enough } +//[mir]~^ ERROR borrowed value does not live long enough fn main() {} diff --git a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs index 7009c6f33e61a..78f0d321e0d3d 100644 --- a/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs +++ b/src/test/compile-fail/borrowck/borrowck-local-borrow-with-panic-outlives-fn.rs @@ -14,9 +14,9 @@ fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) { let mut z = (0, 0); *x = Some(&mut z.1); //[ast]~ ERROR [E0597] - //[mir]~^ ERROR [E0597] panic!("catch me for a dangling pointer!") } +//[mir]~^ ERROR [E0597] fn main() { cplusplus_mode_exceptionally_unsafe(&mut None);