Skip to content

Commit a5cb61d

Browse files
committed
cleanup prefixes iterator
1 parent 3cbb932 commit a5cb61d

File tree

2 files changed

+28
-88
lines changed

2 files changed

+28
-88
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+7-20
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
3939
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
4040
use crate::{
4141
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
42-
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
42+
InitializationRequiringAction, MirBorrowckCtxt, WriteKind,
4343
};
4444

4545
use super::{
@@ -114,7 +114,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
114114
self.buffer_error(err);
115115
} else {
116116
if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) {
117-
if self.prefixes(*reported_place, PrefixSet::All).any(|p| p == used_place) {
117+
if used_place.is_prefix_of(*reported_place) {
118118
debug!(
119119
"report_use_of_moved_or_uninitialized place: error suppressed mois={:?}",
120120
move_out_indices
@@ -1995,34 +1995,23 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
19951995
kind: Option<WriteKind>,
19961996
) {
19971997
let drop_span = place_span.1;
1998-
let root_place =
1999-
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
1998+
let borrowed_local = borrow.borrowed_place.local;
20001999

20012000
let borrow_spans = self.retrieve_borrow_spans(borrow);
20022001
let borrow_span = borrow_spans.var_or_use_path_span();
20032002

2004-
assert!(root_place.projection.is_empty());
2005-
let proper_span = self.body.local_decls[root_place.local].source_info.span;
2006-
2007-
let root_place_projection = self.infcx.tcx.mk_place_elems(root_place.projection);
2003+
let proper_span = self.body.local_decls[borrowed_local].source_info.span;
20082004

2009-
if self.access_place_error_reported.contains(&(
2010-
Place { local: root_place.local, projection: root_place_projection },
2011-
borrow_span,
2012-
)) {
2005+
if self.access_place_error_reported.contains(&(Place::from(borrowed_local), borrow_span)) {
20132006
debug!(
20142007
"suppressing access_place error when borrow doesn't live long enough for {:?}",
20152008
borrow_span
20162009
);
20172010
return;
20182011
}
20192012

2020-
self.access_place_error_reported.insert((
2021-
Place { local: root_place.local, projection: root_place_projection },
2022-
borrow_span,
2023-
));
2013+
self.access_place_error_reported.insert((Place::from(borrowed_local), borrow_span));
20242014

2025-
let borrowed_local = borrow.borrowed_place.local;
20262015
if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
20272016
let err =
20282017
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
@@ -2544,9 +2533,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
25442533
};
25452534
(format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here"))
25462535
} else {
2547-
let root_place =
2548-
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
2549-
let local = root_place.local;
2536+
let local = borrow.borrowed_place.local;
25502537
match self.body.local_kind(local) {
25512538
LocalKind::Arg => (
25522539
"function parameter".to_string(),

compiler/rustc_borrowck/src/prefixes.rs

+21-68
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
1-
//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
2-
//! place are formed by stripping away fields and derefs, except that
3-
//! we stop when we reach the deref of a shared reference. [...] "
4-
//!
1+
//! From the NLL RFC:
52
//! "Shallow prefixes are found by stripping away fields, but stop at
63
//! any dereference. So: writing a path like `a` is illegal if `a.b`
74
//! is borrowed. But: writing `a` is legal if `*a` is borrowed,
85
//! whether or not `a` is a shared or mutable reference. [...] "
96
107
use super::MirBorrowckCtxt;
118

12-
use rustc_hir as hir;
13-
use rustc_middle::mir::{Body, PlaceRef, ProjectionElem};
14-
use rustc_middle::ty::{self, TyCtxt};
9+
use rustc_middle::mir::{PlaceRef, ProjectionElem};
1510

1611
pub trait IsPrefixOf<'tcx> {
1712
fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
@@ -25,9 +20,7 @@ impl<'tcx> IsPrefixOf<'tcx> for PlaceRef<'tcx> {
2520
}
2621
}
2722

28-
pub(super) struct Prefixes<'cx, 'tcx> {
29-
body: &'cx Body<'tcx>,
30-
tcx: TyCtxt<'tcx>,
23+
pub(super) struct Prefixes<'tcx> {
3124
kind: PrefixSet,
3225
next: Option<PlaceRef<'tcx>>,
3326
}
@@ -39,24 +32,18 @@ pub(super) enum PrefixSet {
3932
All,
4033
/// Stops at any dereference.
4134
Shallow,
42-
/// Stops at the deref of a shared reference.
43-
Supporting,
4435
}
4536

4637
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
4738
/// Returns an iterator over the prefixes of `place`
4839
/// (inclusive) from longest to smallest, potentially
4940
/// terminating the iteration early based on `kind`.
50-
pub(super) fn prefixes(
51-
&self,
52-
place_ref: PlaceRef<'tcx>,
53-
kind: PrefixSet,
54-
) -> Prefixes<'cx, 'tcx> {
55-
Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
41+
pub(super) fn prefixes(&self, place_ref: PlaceRef<'tcx>, kind: PrefixSet) -> Prefixes<'tcx> {
42+
Prefixes { next: Some(place_ref), kind }
5643
}
5744
}
5845

59-
impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
46+
impl<'tcx> Iterator for Prefixes<'tcx> {
6047
type Item = PlaceRef<'tcx>;
6148
fn next(&mut self) -> Option<Self::Item> {
6249
let mut cursor = self.next?;
@@ -91,57 +78,23 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
9178
panic!("Subtype projection is not allowed before borrow check")
9279
}
9380
ProjectionElem::Deref => {
94-
// (handled below)
81+
match self.kind {
82+
PrefixSet::Shallow => {
83+
// Shallow prefixes are found by stripping away
84+
// fields, but stop at *any* dereference.
85+
// So we can just stop the traversal now.
86+
self.next = None;
87+
return Some(cursor);
88+
}
89+
PrefixSet::All => {
90+
// All prefixes: just blindly enqueue the base
91+
// of the projection.
92+
self.next = Some(cursor_base);
93+
return Some(cursor);
94+
}
95+
}
9596
}
9697
}
97-
98-
assert_eq!(elem, ProjectionElem::Deref);
99-
100-
match self.kind {
101-
PrefixSet::Shallow => {
102-
// Shallow prefixes are found by stripping away
103-
// fields, but stop at *any* dereference.
104-
// So we can just stop the traversal now.
105-
self.next = None;
106-
return Some(cursor);
107-
}
108-
PrefixSet::All => {
109-
// All prefixes: just blindly enqueue the base
110-
// of the projection.
111-
self.next = Some(cursor_base);
112-
return Some(cursor);
113-
}
114-
PrefixSet::Supporting => {
115-
// Fall through!
116-
}
117-
}
118-
119-
assert_eq!(self.kind, PrefixSet::Supporting);
120-
// Supporting prefixes: strip away fields and
121-
// derefs, except we stop at the deref of a shared
122-
// reference.
123-
124-
let ty = cursor_base.ty(self.body, self.tcx).ty;
125-
match ty.kind() {
126-
ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
127-
// don't continue traversing over derefs of raw pointers or shared
128-
// borrows.
129-
self.next = None;
130-
return Some(cursor);
131-
}
132-
133-
ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Mut) => {
134-
self.next = Some(cursor_base);
135-
return Some(cursor);
136-
}
137-
138-
ty::Adt(..) if ty.is_box() => {
139-
self.next = Some(cursor_base);
140-
return Some(cursor);
141-
}
142-
143-
_ => panic!("unknown type fed to Projection Deref."),
144-
}
14598
}
14699
}
147100
}

0 commit comments

Comments
 (0)