1
Fork 0

don't rely on locals_are_invalidated_at_exit

This commit is contained in:
lcnr 2025-04-11 11:40:38 +02:00
parent 2c65469c27
commit c5fdddc7f4

View file

@ -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) };