From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_borrowck/src/place_ext.rs | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 compiler/rustc_borrowck/src/place_ext.rs (limited to 'compiler/rustc_borrowck/src/place_ext.rs') diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs new file mode 100644 index 000000000..93d202e49 --- /dev/null +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -0,0 +1,81 @@ +use crate::borrow_set::LocalsStateAtExit; +use rustc_hir as hir; +use rustc_middle::mir::ProjectionElem; +use rustc_middle::mir::{Body, Mutability, Place}; +use rustc_middle::ty::{self, TyCtxt}; + +/// Extension methods for the `Place` type. +pub(crate) trait PlaceExt<'tcx> { + /// Returns `true` if we can safely ignore borrows of this place. + /// This is true whenever there is no action that the user can do + /// to the place `self` that would invalidate the borrow. This is true + /// for borrows of raw pointer dereferents as well as shared references. + fn ignore_borrow( + &self, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + locals_state_at_exit: &LocalsStateAtExit, + ) -> bool; +} + +impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { + fn ignore_borrow( + &self, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + locals_state_at_exit: &LocalsStateAtExit, + ) -> bool { + // If a local variable is immutable, then we only need to track borrows to guard + // against two kinds of errors: + // * The variable being dropped while still borrowed (e.g., because the fn returns + // a reference to a local variable) + // * The variable being moved while still borrowed + // + // In particular, the variable cannot be mutated -- the "access checks" will fail -- + // so we don't have to worry about mutation while borrowed. + if let LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved } = + locals_state_at_exit + { + let ignore = !has_storage_dead_or_moved.contains(self.local) + && body.local_decls[self.local].mutability == Mutability::Not; + debug!("ignore_borrow: local {:?} => {:?}", self.local, ignore); + if ignore { + return true; + } + } + + for (i, elem) in self.projection.iter().enumerate() { + let proj_base = &self.projection[..i]; + + if elem == ProjectionElem::Deref { + let ty = Place::ty_from(self.local, proj_base, body, tcx).ty; + match ty.kind() { + ty::Ref(_, _, hir::Mutability::Not) if i == 0 => { + // For references to thread-local statics, we do need + // to track the borrow. + if body.local_decls[self.local].is_ref_to_thread_local() { + continue; + } + return true; + } + ty::RawPtr(..) | ty::Ref(_, _, hir::Mutability::Not) => { + // For both derefs of raw pointers and `&T` + // references, the original path is `Copy` and + // therefore not significant. In particular, + // there is nothing the user can do to the + // original path that would invalidate the + // newly created reference -- and if there + // were, then the user could have copied the + // original path into a new variable and + // borrowed *that* one, leaving the original + // path unborrowed. + return true; + } + _ => {} + } + } + } + + false + } +} -- cgit v1.2.3