don't rely on locals_are_invalidated_at_exit
This commit is contained in:
parent
2c65469c27
commit
c5fdddc7f4
1 changed files with 24 additions and 32 deletions
|
@ -22,6 +22,7 @@ use std::cell::RefCell;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::{ControlFlow, Deref};
|
use std::ops::{ControlFlow, Deref};
|
||||||
|
|
||||||
|
use borrow_set::LocalsStateAtExit;
|
||||||
use root_cx::BorrowCheckRootCtxt;
|
use root_cx::BorrowCheckRootCtxt;
|
||||||
use rustc_abi::FieldIdx;
|
use rustc_abi::FieldIdx;
|
||||||
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
|
||||||
|
@ -382,7 +383,6 @@ fn do_mir_borrowck<'tcx>(
|
||||||
location_table: &location_table,
|
location_table: &location_table,
|
||||||
movable_coroutine,
|
movable_coroutine,
|
||||||
fn_self_span_reported: Default::default(),
|
fn_self_span_reported: Default::default(),
|
||||||
locals_are_invalidated_at_exit,
|
|
||||||
access_place_error_reported: Default::default(),
|
access_place_error_reported: Default::default(),
|
||||||
reservation_error_reported: Default::default(),
|
reservation_error_reported: Default::default(),
|
||||||
uninitialized_error_reported: Default::default(),
|
uninitialized_error_reported: Default::default(),
|
||||||
|
@ -441,7 +441,6 @@ fn do_mir_borrowck<'tcx>(
|
||||||
move_data: &move_data,
|
move_data: &move_data,
|
||||||
location_table: &location_table,
|
location_table: &location_table,
|
||||||
movable_coroutine,
|
movable_coroutine,
|
||||||
locals_are_invalidated_at_exit,
|
|
||||||
fn_self_span_reported: Default::default(),
|
fn_self_span_reported: Default::default(),
|
||||||
access_place_error_reported: Default::default(),
|
access_place_error_reported: Default::default(),
|
||||||
reservation_error_reported: Default::default(),
|
reservation_error_reported: Default::default(),
|
||||||
|
@ -643,13 +642,6 @@ struct MirBorrowckCtxt<'a, 'infcx, 'tcx> {
|
||||||
location_table: &'a PoloniusLocationTable,
|
location_table: &'a PoloniusLocationTable,
|
||||||
|
|
||||||
movable_coroutine: bool,
|
movable_coroutine: bool,
|
||||||
/// This keeps track of whether local variables are free-ed when the function
|
|
||||||
/// exits even without a `StorageDead`, which appears to be the case for
|
|
||||||
/// constants.
|
|
||||||
///
|
|
||||||
/// I'm not sure this is the right approach - @eddyb could you try and
|
|
||||||
/// figure this out?
|
|
||||||
locals_are_invalidated_at_exit: bool,
|
|
||||||
/// This field keeps track of when borrow errors are reported in the access_place function
|
/// This field keeps track of when borrow errors are reported in the access_place function
|
||||||
/// so that there is no duplicate reporting. This field cannot also be used for the conflicting
|
/// so that there is no duplicate reporting. This field cannot also be used for the conflicting
|
||||||
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
|
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
|
||||||
|
@ -925,13 +917,20 @@ impl<'a, 'tcx> ResultsVisitor<'a, 'tcx, Borrowck<'a, 'tcx>> for MirBorrowckCtxt<
|
||||||
| TerminatorKind::Return
|
| TerminatorKind::Return
|
||||||
| TerminatorKind::TailCall { .. }
|
| TerminatorKind::TailCall { .. }
|
||||||
| TerminatorKind::CoroutineDrop => {
|
| TerminatorKind::CoroutineDrop => {
|
||||||
// Returning from the function implicitly kills storage for all locals and statics.
|
match self.borrow_set.locals_state_at_exit() {
|
||||||
// Often, the storage will already have been killed by an explicit
|
LocalsStateAtExit::AllAreInvalidated => {
|
||||||
// StorageDead, but we don't always emit those (notably on unwind paths),
|
// Returning from the function implicitly kills storage for all locals and statics.
|
||||||
// so this "extra check" serves as a kind of backup.
|
// Often, the storage will already have been killed by an explicit
|
||||||
for i in state.borrows.iter() {
|
// StorageDead, but we don't always emit those (notably on unwind paths),
|
||||||
let borrow = &self.borrow_set[i];
|
// so this "extra check" serves as a kind of backup.
|
||||||
self.check_for_invalidation_at_exit(loc, borrow, span);
|
for i in state.borrows.iter() {
|
||||||
|
let borrow = &self.borrow_set[i];
|
||||||
|
self.check_for_invalidation_at_exit(loc, borrow, span);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we do not implicitly invalidate all locals on exit,
|
||||||
|
// we check for conflicts when dropping or moving this local.
|
||||||
|
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved: _ } => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,22 +1702,15 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, '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?
|
// FIXME: allow thread-locals to borrow other thread locals?
|
||||||
|
let might_be_alive = if self.body.local_decls[root_place.local].is_ref_to_thread_local() {
|
||||||
let (might_be_alive, will_be_dropped) =
|
// Thread-locals might be dropped after the function exits
|
||||||
if self.body.local_decls[root_place.local].is_ref_to_thread_local() {
|
// We have to dereference the outer reference because
|
||||||
// Thread-locals might be dropped after the function exits
|
// borrows don't conflict behind shared references.
|
||||||
// We have to dereference the outer reference because
|
root_place.projection = TyCtxtConsts::DEREF_PROJECTION;
|
||||||
// borrows don't conflict behind shared references.
|
true
|
||||||
root_place.projection = TyCtxtConsts::DEREF_PROJECTION;
|
} else {
|
||||||
(true, true)
|
false
|
||||||
} else {
|
};
|
||||||
(false, self.locals_are_invalidated_at_exit)
|
|
||||||
};
|
|
||||||
|
|
||||||
if !will_be_dropped {
|
|
||||||
debug!("place_is_invalidated_at_exit({:?}) - won't be dropped", place);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let sd = if might_be_alive { Deep } else { Shallow(None) };
|
let sd = if might_be_alive { Deep } else { Shallow(None) };
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue