improve conflict error reporting

This commit is contained in:
Ariel Ben-Yehuda 2017-12-03 17:55:41 +02:00
parent f8c35d9e41
commit cbcae7f694
3 changed files with 21 additions and 11 deletions

View File

@ -548,14 +548,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
if self.place_is_invalidated_at_exit(&borrow.place) { if self.place_is_invalidated_at_exit(&borrow.place) {
debug!("borrow conflicts at exit {:?}", borrow); 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 // FIXME: should be talking about the region lifetime instead
// of just a span here. // of just a span here.
let end_span = domain.opt_region_end_span(&borrow.region); let end_span = domain.opt_region_end_span(&borrow.region);
self.report_borrowed_value_does_not_live_long_enough( self.report_borrowed_value_does_not_live_long_enough(
ContextKind::StorageDead.new(loc), ContextKind::StorageDead.new(loc),
(&borrow.place, borrow_span), (&borrow.place, end_span.unwrap_or(span)),
end_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 /// Returns whether a borrow of this place is invalidated when the function
/// exits /// 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); debug!("place_is_invalidated_at_exit({:?})", place);
let root_place = self.prefixes(place, PrefixSet::All).last().unwrap(); 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. // we'll have a memory leak) and assume that all statics have a destructor.
// //
// FIXME: allow thread-locals to borrow other thread locals?x // 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) => { Place::Static(statik) => {
// Thread-locals might be dropped after the function exits, but // Thread-locals might be dropped after the function exits, but
// "true" statics will never be. // "true" statics will never be.
@ -976,12 +975,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
.iter() .iter()
.any(|attr| attr.check_name("thread_local")); .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 // Locals are always dropped at function exit, and if they
// have a destructor it would've been called already. // 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(..) => { Place::Projection(..) => {
bug!("root of {:?} is a projection ({:?})?", place, root_place) bug!("root of {:?} is a projection ({:?})?", place, root_place)
@ -1004,8 +1003,19 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
PrefixSet::Shallow PrefixSet::Shallow
}; };
self.prefixes(place, prefix_set) let result =
.any(|prefix| prefix == root_place) 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
} }
} }

View File

@ -13,7 +13,7 @@
fn cplusplus_mode(x: isize) -> &'static isize { fn cplusplus_mode(x: isize) -> &'static isize {
&x //[ast]~ ERROR `x` does not live long enough &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() {} fn main() {}

View File

@ -14,9 +14,9 @@
fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) { fn cplusplus_mode_exceptionally_unsafe(x: &mut Option<&'static mut isize>) {
let mut z = (0, 0); let mut z = (0, 0);
*x = Some(&mut z.1); //[ast]~ ERROR [E0597] *x = Some(&mut z.1); //[ast]~ ERROR [E0597]
//[mir]~^ ERROR [E0597]
panic!("catch me for a dangling pointer!") panic!("catch me for a dangling pointer!")
} }
//[mir]~^ ERROR [E0597]
fn main() { fn main() {
cplusplus_mode_exceptionally_unsafe(&mut None); cplusplus_mode_exceptionally_unsafe(&mut None);