Rollup merge of #122468 - beepster4096:borrowck_prefixes_cleanup, r=Nadrieril
Cleanup `MirBorrowckCtxt::prefixes` Some of the uses of this method aren't necessary anymore and `PrefixSet::Supporting` is not used anywhere. With `PrefixSet::Supporting` removed, this could technically be moved to an extension trait on `PlaceRef`. However, it would have to be moved back to `MirBorrowckCtxt` when the `Derefer` MIR pass is moved before borrowck so I didn't.
This commit is contained in:
commit
5c0012b953
@ -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<WriteKind>,
|
||||
) {
|
||||
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 proper_span = self.body.local_decls[borrowed_local].source_info.span;
|
||||
|
||||
let root_place_projection = self.infcx.tcx.mk_place_elems(root_place.projection);
|
||||
|
||||
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(),
|
||||
|
@ -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<PlaceRef<'tcx>>,
|
||||
}
|
||||
@ -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<Self::Item> {
|
||||
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."),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user