Skip to content

Use PlaceRef abstractions more often #112693

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
6 changes: 2 additions & 4 deletions compiler/rustc_borrowck/src/place_ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
27 changes: 7 additions & 20 deletions compiler/rustc_borrowck/src/places_conflict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.
Expand Down Expand Up @@ -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`
Expand All @@ -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)))
Expand Down Expand Up @@ -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,
Expand All @@ -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");
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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() {
Expand Down
16 changes: 7 additions & 9 deletions compiler/rustc_const_eval/src/transform/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 5 additions & 7 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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(
Expand All @@ -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));
};
Expand All @@ -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
)
)
}
Expand Down Expand Up @@ -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>) {
Expand Down
11 changes: 4 additions & 7 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand Down
19 changes: 4 additions & 15 deletions compiler/rustc_mir_build/src/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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.
Expand Down
19 changes: 5 additions & 14 deletions compiler/rustc_mir_dataflow/src/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() => {
Expand Down Expand Up @@ -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));
}
}

Expand Down
8 changes: 3 additions & 5 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
}

Expand Down