cleanup prefixes iterator
This commit is contained in:
parent
3cbb93223f
commit
a5cb61d39b
@ -39,7 +39,7 @@ use crate::diagnostics::conflict_errors::StorageDeadOrDrop::LocalStorageDead;
|
|||||||
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
use crate::diagnostics::{find_all_local_uses, CapturedMessageOpt};
|
||||||
use crate::{
|
use crate::{
|
||||||
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
|
||||||
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
|
InitializationRequiringAction, MirBorrowckCtxt, WriteKind,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -114,7 +114,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
self.buffer_error(err);
|
self.buffer_error(err);
|
||||||
} else {
|
} else {
|
||||||
if let Some((reported_place, _)) = self.has_move_error(&move_out_indices) {
|
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!(
|
debug!(
|
||||||
"report_use_of_moved_or_uninitialized place: error suppressed mois={:?}",
|
"report_use_of_moved_or_uninitialized place: error suppressed mois={:?}",
|
||||||
move_out_indices
|
move_out_indices
|
||||||
@ -1995,21 +1995,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
kind: Option<WriteKind>,
|
kind: Option<WriteKind>,
|
||||||
) {
|
) {
|
||||||
let drop_span = place_span.1;
|
let drop_span = place_span.1;
|
||||||
let root_place =
|
let borrowed_local = borrow.borrowed_place.local;
|
||||||
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
|
||||||
|
|
||||||
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
let borrow_spans = self.retrieve_borrow_spans(borrow);
|
||||||
let borrow_span = borrow_spans.var_or_use_path_span();
|
let borrow_span = borrow_spans.var_or_use_path_span();
|
||||||
|
|
||||||
assert!(root_place.projection.is_empty());
|
let proper_span = self.body.local_decls[borrowed_local].source_info.span;
|
||||||
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);
|
if self.access_place_error_reported.contains(&(Place::from(borrowed_local), borrow_span)) {
|
||||||
|
|
||||||
if self.access_place_error_reported.contains(&(
|
|
||||||
Place { local: root_place.local, projection: root_place_projection },
|
|
||||||
borrow_span,
|
|
||||||
)) {
|
|
||||||
debug!(
|
debug!(
|
||||||
"suppressing access_place error when borrow doesn't live long enough for {:?}",
|
"suppressing access_place error when borrow doesn't live long enough for {:?}",
|
||||||
borrow_span
|
borrow_span
|
||||||
@ -2017,12 +2010,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.access_place_error_reported.insert((
|
self.access_place_error_reported.insert((Place::from(borrowed_local), borrow_span));
|
||||||
Place { local: root_place.local, projection: root_place_projection },
|
|
||||||
borrow_span,
|
|
||||||
));
|
|
||||||
|
|
||||||
let borrowed_local = borrow.borrowed_place.local;
|
|
||||||
if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
|
if self.body.local_decls[borrowed_local].is_ref_to_thread_local() {
|
||||||
let err =
|
let err =
|
||||||
self.report_thread_local_value_does_not_live_long_enough(drop_span, borrow_span);
|
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"))
|
(format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here"))
|
||||||
} else {
|
} else {
|
||||||
let root_place =
|
let local = borrow.borrowed_place.local;
|
||||||
self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap();
|
|
||||||
let local = root_place.local;
|
|
||||||
match self.body.local_kind(local) {
|
match self.body.local_kind(local) {
|
||||||
LocalKind::Arg => (
|
LocalKind::Arg => (
|
||||||
"function parameter".to_string(),
|
"function parameter".to_string(),
|
||||||
|
@ -1,7 +1,4 @@
|
|||||||
//! From the NLL RFC: "The deep [aka 'supporting'] prefixes for an
|
//! From the NLL RFC:
|
||||||
//! place are formed by stripping away fields and derefs, except that
|
|
||||||
//! we stop when we reach the deref of a shared reference. [...] "
|
|
||||||
//!
|
|
||||||
//! "Shallow prefixes are found by stripping away fields, but stop at
|
//! "Shallow prefixes are found by stripping away fields, but stop at
|
||||||
//! any dereference. So: writing a path like `a` is illegal if `a.b`
|
//! any dereference. So: writing a path like `a` is illegal if `a.b`
|
||||||
//! is borrowed. But: writing `a` is legal if `*a` is borrowed,
|
//! is borrowed. But: writing `a` is legal if `*a` is borrowed,
|
||||||
@ -9,9 +6,7 @@
|
|||||||
|
|
||||||
use super::MirBorrowckCtxt;
|
use super::MirBorrowckCtxt;
|
||||||
|
|
||||||
use rustc_hir as hir;
|
use rustc_middle::mir::{PlaceRef, ProjectionElem};
|
||||||
use rustc_middle::mir::{Body, PlaceRef, ProjectionElem};
|
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
|
||||||
|
|
||||||
pub trait IsPrefixOf<'tcx> {
|
pub trait IsPrefixOf<'tcx> {
|
||||||
fn is_prefix_of(&self, other: PlaceRef<'tcx>) -> bool;
|
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> {
|
pub(super) struct Prefixes<'tcx> {
|
||||||
body: &'cx Body<'tcx>,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
kind: PrefixSet,
|
kind: PrefixSet,
|
||||||
next: Option<PlaceRef<'tcx>>,
|
next: Option<PlaceRef<'tcx>>,
|
||||||
}
|
}
|
||||||
@ -39,24 +32,18 @@ pub(super) enum PrefixSet {
|
|||||||
All,
|
All,
|
||||||
/// Stops at any dereference.
|
/// Stops at any dereference.
|
||||||
Shallow,
|
Shallow,
|
||||||
/// Stops at the deref of a shared reference.
|
|
||||||
Supporting,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
|
||||||
/// Returns an iterator over the prefixes of `place`
|
/// Returns an iterator over the prefixes of `place`
|
||||||
/// (inclusive) from longest to smallest, potentially
|
/// (inclusive) from longest to smallest, potentially
|
||||||
/// terminating the iteration early based on `kind`.
|
/// terminating the iteration early based on `kind`.
|
||||||
pub(super) fn prefixes(
|
pub(super) fn prefixes(&self, place_ref: PlaceRef<'tcx>, kind: PrefixSet) -> Prefixes<'tcx> {
|
||||||
&self,
|
Prefixes { next: Some(place_ref), kind }
|
||||||
place_ref: PlaceRef<'tcx>,
|
|
||||||
kind: PrefixSet,
|
|
||||||
) -> Prefixes<'cx, 'tcx> {
|
|
||||||
Prefixes { next: Some(place_ref), kind, body: self.body, tcx: self.infcx.tcx }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
|
impl<'tcx> Iterator for Prefixes<'tcx> {
|
||||||
type Item = PlaceRef<'tcx>;
|
type Item = PlaceRef<'tcx>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
let mut cursor = self.next?;
|
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")
|
panic!("Subtype projection is not allowed before borrow check")
|
||||||
}
|
}
|
||||||
ProjectionElem::Deref => {
|
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