From a5cb61d39ba92beb8b48d9b4dfe72ac06fa4503c Mon Sep 17 00:00:00 2001 From: beepster4096 <19316085+beepster4096@users.noreply.github.com> Date: Wed, 13 Mar 2024 12:34:29 -0700 Subject: [PATCH] cleanup prefixes iterator --- .../src/diagnostics/conflict_errors.rs | 27 ++---- compiler/rustc_borrowck/src/prefixes.rs | 89 +++++-------------- 2 files changed, 28 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 0776f455efd9c..cec79a4a3f537 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -39,7 +39,7 @@ use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead; use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt}; use crate::{ borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf, - InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind, + InitializationRequiringAction, MirBorrowckCtxt, WriteKind, }; use super::{ @@ -114,7 +114,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.buffer_error(err); } else { if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) { - if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) { + if used_place.is_prefix_of(*reported_place) { debug!( "report_use_of_moved_or_uninitialized place: error suppressed mois={:?}", move_out_indices @@ -1995,21 +1995,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { kind: Option, ) { let drop_span = place_span.1; - let root_place = - self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); + let borrowed_local = borrow.borrowed_place.local; let borrow_spans = self.retrieve_borrow_spans(borrow); let borrow_span = borrow_spans.var_or_use_path_span(); - assert!(root_place.projection.is_empty()); - let proper_span = self.body.local_decls[root_place.local].source_info.span; - - let root_place_projection = self.infcx.tcx.mk_place_elems(root_place.projection); + let proper_span = self.body.local_decls[borrowed_local].source_info.span; - if self.access_place_error_reported.contains(&( - Place { local: root_place.local, projection: root_place_projection }, - borrow_span, - )) { + if self.access_place_error_reported.contains(&(Place::from(borrowed_local), borrow_span)) { debug!( "suppressing access_place error when borrow doesn't live long enough for {:?}", borrow_span @@ -2017,12 +2010,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; } - self.access_place_error_reported.insert(( - Place { local: root_place.local, projection: root_place_projection }, - borrow_span, - )); + self.access_place_error_reported.insert((Place::from(borrowed_local), borrow_span)); - let borrowed_local = borrow.borrowed_place.local; if self.body.local_decls[borrowed_local].is_ref_to_thread_local() { let err = self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span); @@ -2544,9 +2533,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; (format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here")) } else { - let root_place = - self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); - let local = root_place.local; + let local = borrow.borrowed_place.local; match self.body.local_kind(local) { LocalKind::Arg => ( "function parameter".to_string(), diff --git a/compiler/rustc_borrowck/src/prefixes.rs b/compiler/rustc_borrowck/src/prefixes.rs index 8bb3dc88b3467..8a3a089d0eeba 100644 --- a/compiler/rustc_borrowck/src/prefixes.rs +++ b/compiler/rustc_borrowck/src/prefixes.rs @@ -1,7 +1,4 @@ -//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an -//! place are formed by stripping away fields and derefs, except that -//! we stop when we reach the deref of a shared reference. [...] " -//! +//! From the NLL RFC: //! "Shallow prefixes are found by stripping away fields, but stop at //! any dereference. So: writing a path like `a` is illegal if `a.b` //! is borrowed. But: writing `a` is legal if `*a` is borrowed, @@ -9,9 +6,7 @@ use super::MirBorrowckCtxt; -use rustc_hir as hir; -use rustc_middle::mir::{Body, PlaceRef, ProjectionElem}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::mir::{PlaceRef, ProjectionElem}; pub trait IsPrefixOf<'tcx> { fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool; @@ -25,9 +20,7 @@ impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> { } } -pub(super) struct Prefixes<'cx, 'tcx> { - body: &'cx Body<'tcx>, - tcx: TyCtxt<'tcx>, +pub(super) struct Prefixes<'tcx> { kind: PrefixSet, next: Option>, } @@ -39,24 +32,18 @@ pub(super) enum PrefixSet { All, /// Stops at any dereference. Shallow, - /// Stops at the deref of a shared reference. - Supporting, } impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { /// Returns an iterator over the prefixes of `place` /// (inclusive) from longest to smallest, potentially /// terminating the iteration early based on `kind`. - pub(super) fn prefixes( - &self, - place_ref: PlaceRef<'tcx>, - kind: PrefixSet, - ) -> Prefixes<'cx, 'tcx> { - Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx } + pub(super) fn prefixes(&self, place_ref: PlaceRef<'tcx>, kind: PrefixSet) -> Prefixes<'tcx> { + Prefixes { next: Some(place_ref), kind } } } -impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { +impl<'tcx> Iterator for Prefixes<'tcx> { type Item = PlaceRef<'tcx>; fn next(&mut self) -> Option { let mut cursor = self.next?; @@ -91,57 +78,23 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> { panic!("Subtype projection is not allowed before borrow check") } ProjectionElem::Deref => { - // (handled below) + match self.kind { + PrefixSet::Shallow => { + // Shallow prefixes are found by stripping away + // fields, but stop at *any* dereference. + // So we can just stop the traversal now. + self.next = None; + return Some(cursor); + } + PrefixSet::All => { + // All prefixes: just blindly enqueue the base + // of the projection. + self.next = Some(cursor_base); + return Some(cursor); + } + } } } - - assert_eq!(elem, ProjectionElem::Deref); - - match self.kind { - PrefixSet::Shallow => { - // Shallow prefixes are found by stripping away - // fields, but stop at *any* dereference. - // So we can just stop the traversal now. - self.next = None; - return Some(cursor); - } - PrefixSet::All => { - // All prefixes: just blindly enqueue the base - // of the projection. - self.next = Some(cursor_base); - return Some(cursor); - } - PrefixSet::Supporting => { - // Fall through! - } - } - - assert_eq!(self.kind, PrefixSet::Supporting); - // Supporting prefixes: strip away fields and - // derefs, except we stop at the deref of a shared - // reference. - - let ty = cursor_base.ty(self.body, self.tcx).ty; - match ty.kind() { - ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => { - // don't continue traversing over derefs of raw pointers or shared - // borrows. - self.next = None; - return Some(cursor); - } - - ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => { - self.next = Some(cursor_base); - return Some(cursor); - } - - ty::Adt(..) if ty.is_box() => { - self.next = Some(cursor_base); - return Some(cursor); - } - - _ => panic!("unknown type fed to Projection Deref."), - } } } }