diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 34d466db2b409..1646bb63e15c0 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -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() { diff --git a/compiler/rustc_borrowck/src/place_ext.rs b/compiler/rustc_borrowck/src/place_ext.rs index d521d0db21323..3d7e8c6ebf330 100644 --- a/compiler/rustc_borrowck/src/place_ext.rs +++ b/compiler/rustc_borrowck/src/place_ext.rs @@ -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 diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 25c485b814f4a..612406ce9134a 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -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"); diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6697e1aff7dd0..ec9577af80295 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -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() { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index 106cf1114749a..61bc24b4c6168 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -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); diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 3c350e25ba6ec..eda50d3a76787 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -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>) { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8d44e929afde3..68f24d7eaa460 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -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, diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 7ec57add66b59..623bef5ff2dba 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -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. diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 096bc0acfccb9..7cdd3a21acad6 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -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)); } } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index b28fed7159f1e..37c7a3b588062 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -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); } }