mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
use PlaceRef abstractions more consistently
This commit is contained in:
parent
0c2c243342
commit
c07c10d1e4
@ -123,13 +123,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
|
||||
item_msg = access_place_desc;
|
||||
debug_assert!(self.body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty.is_ref());
|
||||
debug_assert!(is_closure_or_generator(
|
||||
Place::ty_from(
|
||||
the_place_err.local,
|
||||
the_place_err.projection,
|
||||
self.body,
|
||||
self.infcx.tcx
|
||||
)
|
||||
.ty
|
||||
the_place_err.ty(self.body, self.infcx.tcx).ty
|
||||
));
|
||||
|
||||
reason = if self.is_upvar_field_projection(access_place.as_ref()).is_some() {
|
||||
|
@ -46,11 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
for (i, elem) in self.projection.iter().enumerate() {
|
||||
let proj_base = &self.projection[..i];
|
||||
|
||||
for (i, (proj_base, elem)) in self.iter_projections().enumerate() {
|
||||
if elem == ProjectionElem::Deref {
|
||||
let ty = Place::ty_from(self.local, proj_base, body, tcx).ty;
|
||||
let ty = proj_base.ty(body, tcx).ty;
|
||||
match ty.kind() {
|
||||
ty::Ref(_, _, hir::Mutability::Not) if i == 0 => {
|
||||
// For references to thread-local statics, we do need
|
||||
|
@ -135,13 +135,11 @@ fn place_components_conflict<'tcx>(
|
||||
}
|
||||
|
||||
// loop invariant: borrow_c is always either equal to access_c or disjoint from it.
|
||||
for (i, (borrow_c, &access_c)) in
|
||||
iter::zip(borrow_place.projection, access_place.projection).enumerate()
|
||||
for ((borrow_place, borrow_c), &access_c) in
|
||||
iter::zip(borrow_place.iter_projections(), access_place.projection)
|
||||
{
|
||||
debug!(?borrow_c, ?access_c);
|
||||
|
||||
let borrow_proj_base = &borrow_place.projection[..i];
|
||||
|
||||
// Borrow and access path both have more components.
|
||||
//
|
||||
// Examples:
|
||||
@ -154,15 +152,7 @@ fn place_components_conflict<'tcx>(
|
||||
// check whether the components being borrowed vs
|
||||
// accessed are disjoint (as in the second example,
|
||||
// but not the first).
|
||||
match place_projection_conflict(
|
||||
tcx,
|
||||
body,
|
||||
borrow_local,
|
||||
borrow_proj_base,
|
||||
borrow_c,
|
||||
access_c,
|
||||
bias,
|
||||
) {
|
||||
match place_projection_conflict(tcx, body, borrow_place, borrow_c, access_c, bias) {
|
||||
Overlap::Arbitrary => {
|
||||
// We have encountered different fields of potentially
|
||||
// the same union - the borrow now partially overlaps.
|
||||
@ -193,8 +183,7 @@ fn place_components_conflict<'tcx>(
|
||||
}
|
||||
|
||||
if borrow_place.projection.len() > access_place.projection.len() {
|
||||
for (i, elem) in borrow_place.projection[access_place.projection.len()..].iter().enumerate()
|
||||
{
|
||||
for (base, elem) in borrow_place.iter_projections().skip(access_place.projection.len()) {
|
||||
// Borrow path is longer than the access path. Examples:
|
||||
//
|
||||
// - borrow of `a.b.c`, access to `a.b`
|
||||
@ -203,8 +192,7 @@ fn place_components_conflict<'tcx>(
|
||||
// our place. This is a conflict if that is a part our
|
||||
// access cares about.
|
||||
|
||||
let proj_base = &borrow_place.projection[..access_place.projection.len() + i];
|
||||
let base_ty = Place::ty_from(borrow_local, proj_base, body, tcx).ty;
|
||||
let base_ty = base.ty(body, tcx).ty;
|
||||
|
||||
match (elem, &base_ty.kind(), access) {
|
||||
(_, _, Shallow(Some(ArtificialField::ArrayLength)))
|
||||
@ -308,8 +296,7 @@ fn place_base_conflict(l1: Local, l2: Local) -> Overlap {
|
||||
fn place_projection_conflict<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
body: &Body<'tcx>,
|
||||
pi1_local: Local,
|
||||
pi1_proj_base: &[PlaceElem<'tcx>],
|
||||
pi1: PlaceRef<'tcx>,
|
||||
pi1_elem: PlaceElem<'tcx>,
|
||||
pi2_elem: PlaceElem<'tcx>,
|
||||
bias: PlaceConflictBias,
|
||||
@ -331,7 +318,7 @@ fn place_projection_conflict<'tcx>(
|
||||
debug!("place_element_conflict: DISJOINT-OR-EQ-FIELD");
|
||||
Overlap::EqualOrDisjoint
|
||||
} else {
|
||||
let ty = Place::ty_from(pi1_local, pi1_proj_base, body, tcx).ty;
|
||||
let ty = pi1.ty(body, tcx).ty;
|
||||
if ty.is_union() {
|
||||
// Different fields of a union, we are basically stuck.
|
||||
debug!("place_element_conflict: STUCK-UNION");
|
||||
|
@ -2499,7 +2499,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
location, borrow_region, borrowed_place
|
||||
);
|
||||
|
||||
let mut cursor = borrowed_place.projection.as_ref();
|
||||
let tcx = self.infcx.tcx;
|
||||
let field = path_utils::is_upvar_field_projection(
|
||||
tcx,
|
||||
@ -2513,14 +2512,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
|
||||
ConstraintCategory::Boring
|
||||
};
|
||||
|
||||
while let [proj_base @ .., elem] = cursor {
|
||||
cursor = proj_base;
|
||||
|
||||
for (base, elem) in borrowed_place.as_ref().iter_projections().rev() {
|
||||
debug!("add_reborrow_constraint - iteration {:?}", elem);
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let base_ty = Place::ty_from(borrowed_place.local, proj_base, body, tcx).ty;
|
||||
let base_ty = base.ty(body, tcx).ty;
|
||||
|
||||
debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
|
||||
match base_ty.kind() {
|
||||
|
@ -617,30 +617,28 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
}
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
place_local: Local,
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
elem: PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
trace!(
|
||||
"visit_projection_elem: place_local={:?} proj_base={:?} elem={:?} \
|
||||
"visit_projection_elem: place_ref={:?} elem={:?} \
|
||||
context={:?} location={:?}",
|
||||
place_local,
|
||||
proj_base,
|
||||
place_ref,
|
||||
elem,
|
||||
context,
|
||||
location,
|
||||
);
|
||||
|
||||
self.super_projection_elem(place_local, proj_base, elem, context, location);
|
||||
self.super_projection_elem(place_ref, elem, context, location);
|
||||
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let base_ty = Place::ty_from(place_local, proj_base, self.body, self.tcx).ty;
|
||||
let base_ty = place_ref.ty(self.body, self.tcx).ty;
|
||||
if base_ty.is_unsafe_ptr() {
|
||||
if proj_base.is_empty() {
|
||||
let decl = &self.body.local_decls[place_local];
|
||||
if place_ref.projection.is_empty() {
|
||||
let decl = &self.body.local_decls[place_ref.local];
|
||||
if let LocalInfo::StaticRef { def_id, .. } = *decl.local_info() {
|
||||
let span = decl.source_info.span;
|
||||
self.check_static(def_id, span);
|
||||
|
@ -318,8 +318,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
local: Local,
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
elem: PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
@ -334,7 +333,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
ProjectionElem::Deref
|
||||
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::PostCleanup) =>
|
||||
{
|
||||
let base_ty = Place::ty_from(local, proj_base, &self.body.local_decls, self.tcx).ty;
|
||||
let base_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
|
||||
|
||||
if base_ty.is_box() {
|
||||
self.fail(
|
||||
@ -344,8 +343,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
ProjectionElem::Field(f, ty) => {
|
||||
let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) };
|
||||
let parent_ty = parent.ty(&self.body.local_decls, self.tcx);
|
||||
let parent_ty = place_ref.ty(&self.body.local_decls, self.tcx);
|
||||
let fail_out_of_bounds = |this: &Self, location| {
|
||||
this.fail(location, format!("Out of bounds field {:?} for {:?}", f, parent_ty));
|
||||
};
|
||||
@ -355,7 +353,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
location,
|
||||
format!(
|
||||
"Field projection `{:?}.{:?}` specified type `{:?}`, but actual type is `{:?}`",
|
||||
parent, f, ty, f_ty
|
||||
place_ref, f, ty, f_ty
|
||||
)
|
||||
)
|
||||
}
|
||||
@ -434,7 +432,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.super_projection_elem(local, proj_base, elem, context, location);
|
||||
self.super_projection_elem(place_ref, elem, context, location);
|
||||
}
|
||||
|
||||
fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) {
|
||||
|
@ -1136,13 +1136,12 @@ macro_rules! visit_place_fns {
|
||||
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
local: Local,
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
elem: PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
self.super_projection_elem(local, proj_base, elem, context, location);
|
||||
self.super_projection_elem(place_ref, elem, context, location);
|
||||
}
|
||||
|
||||
fn super_place(&mut self, place: &Place<'tcx>, context: PlaceContext, location: Location) {
|
||||
@ -1171,15 +1170,13 @@ macro_rules! visit_place_fns {
|
||||
location: Location,
|
||||
) {
|
||||
for (base, elem) in place_ref.iter_projections().rev() {
|
||||
let base_proj = base.projection;
|
||||
self.visit_projection_elem(place_ref.local, base_proj, elem, context, location);
|
||||
self.visit_projection_elem(base, elem, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
fn super_projection_elem(
|
||||
&mut self,
|
||||
_local: Local,
|
||||
_proj_base: &[PlaceElem<'tcx>],
|
||||
_place_ref: PlaceRef<'tcx>,
|
||||
elem: PlaceElem<'tcx>,
|
||||
_context: PlaceContext,
|
||||
location: Location,
|
||||
|
@ -677,21 +677,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
// check that we just did stays valid. Since we can't assign to
|
||||
// unsized values, we only need to ensure that none of the
|
||||
// pointers in the base place are modified.
|
||||
for (idx, elem) in base_place.projection.iter().enumerate().rev() {
|
||||
for (base_place, elem) in base_place.iter_projections().rev() {
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let fake_borrow_deref_ty = Place::ty_from(
|
||||
base_place.local,
|
||||
&base_place.projection[..idx],
|
||||
&self.local_decls,
|
||||
tcx,
|
||||
)
|
||||
.ty;
|
||||
let fake_borrow_deref_ty = base_place.ty(&self.local_decls, tcx).ty;
|
||||
let fake_borrow_ty =
|
||||
tcx.mk_imm_ref(tcx.lifetimes.re_erased, fake_borrow_deref_ty);
|
||||
let fake_borrow_temp =
|
||||
self.local_decls.push(LocalDecl::new(fake_borrow_ty, expr_span));
|
||||
let projection = tcx.mk_place_elems(&base_place.projection[..idx]);
|
||||
let projection = tcx.mk_place_elems(&base_place.projection);
|
||||
self.cfg.push_assign(
|
||||
block,
|
||||
source_info,
|
||||
@ -705,12 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
fake_borrow_temps.push(fake_borrow_temp);
|
||||
}
|
||||
ProjectionElem::Index(_) => {
|
||||
let index_ty = Place::ty_from(
|
||||
base_place.local,
|
||||
&base_place.projection[..idx],
|
||||
&self.local_decls,
|
||||
tcx,
|
||||
);
|
||||
let index_ty = base_place.ty(&self.local_decls, tcx);
|
||||
match index_ty.ty.kind() {
|
||||
// The previous index expression has already
|
||||
// done any index expressions needed here.
|
||||
|
@ -113,22 +113,16 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||
// from `*(u.f: &_)` isn't allowed.
|
||||
let mut union_path = None;
|
||||
|
||||
for (i, elem) in place.projection.iter().enumerate() {
|
||||
let proj_base = &place.projection[..i];
|
||||
for (place_ref, elem) in place.as_ref().iter_projections() {
|
||||
let body = self.builder.body;
|
||||
let tcx = self.builder.tcx;
|
||||
let place_ty = Place::ty_from(place.local, proj_base, body, tcx).ty;
|
||||
let place_ty = place_ref.ty(body, tcx).ty;
|
||||
|
||||
match place_ty.kind() {
|
||||
ty::Ref(..) | ty::RawPtr(..) => {
|
||||
let proj = &place.projection[..i + 1];
|
||||
return Err(MoveError::cannot_move_out_of(
|
||||
self.loc,
|
||||
BorrowedContent {
|
||||
target_place: Place {
|
||||
local: place.local,
|
||||
projection: tcx.mk_place_elems(proj),
|
||||
},
|
||||
},
|
||||
BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) },
|
||||
));
|
||||
}
|
||||
ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
|
||||
@ -163,10 +157,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
|
||||
};
|
||||
|
||||
if union_path.is_none() {
|
||||
base = self.add_move_path(base, elem, |tcx| Place {
|
||||
local: place.local,
|
||||
projection: tcx.mk_place_elems(&place.projection[..i + 1]),
|
||||
});
|
||||
base = self.add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -839,15 +839,13 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
/// to normalization failure.
|
||||
fn visit_projection_elem(
|
||||
&mut self,
|
||||
local: Local,
|
||||
proj_base: &[PlaceElem<'tcx>],
|
||||
place_ref: PlaceRef<'tcx>,
|
||||
elem: PlaceElem<'tcx>,
|
||||
context: PlaceContext,
|
||||
location: Location,
|
||||
) {
|
||||
if let ProjectionElem::Field(f, ty) = elem {
|
||||
let parent = Place { local, projection: self.tcx.mk_place_elems(proj_base) };
|
||||
let parent_ty = parent.ty(&self.callee_body.local_decls, self.tcx);
|
||||
let parent_ty = place_ref.ty(&self.callee_body.local_decls, self.tcx);
|
||||
let check_equal = |this: &mut Self, f_ty| {
|
||||
if !util::is_equal_up_to_subtyping(this.tcx, this.param_env, ty, f_ty) {
|
||||
trace!(?ty, ?f_ty);
|
||||
@ -926,7 +924,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
self.super_projection_elem(local, proj_base, elem, context, location);
|
||||
self.super_projection_elem(place_ref, elem, context, location);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user