From e73d189e4e2ad55fcea595a14f9adea0960c65a1 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sat, 24 Aug 2019 20:53:20 -0400 Subject: [PATCH] Use slice patterns to match projection base --- src/librustc/mir/visit.rs | 5 +- src/librustc_codegen_ssa/mir/analyze.rs | 5 +- src/librustc_codegen_ssa/mir/place.rs | 8 +- .../borrow_check/error_reporting.rs | 10 +- src/librustc_mir/borrow_check/mod.rs | 4 +- src/librustc_mir/borrow_check/move_errors.rs | 7 +- .../borrow_check/mutability_errors.rs | 8 +- src/librustc_mir/borrow_check/prefixes.rs | 4 +- .../dataflow/move_paths/builder.rs | 3 +- src/librustc_mir/transform/instcombine.rs | 17 +--- src/librustc_mir/transform/qualify_consts.rs | 99 +++++++++---------- .../transform/uniform_array_move_out.rs | 15 +-- 12 files changed, 67 insertions(+), 118 deletions(-) diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 36aa891aaf4..9f3df7cc58f 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -720,12 +720,9 @@ fn super_projection(&mut self, projection: & $($mutability)? [PlaceElem<'tcx>], context: PlaceContext, location: Location) { - if !projection.is_empty() { - let proj_len = projection.len(); - let proj_base = & $($mutability)? projection[..proj_len - 1]; + if let [proj_base @ .., elem] = projection { self.visit_projection(base, proj_base, context, location); - let elem = & $($mutability)? projection[proj_len - 1]; match elem { ProjectionElem::Field(_field, ty) => { self.visit_ty(ty, TyContext::Location(location)); diff --git a/src/librustc_codegen_ssa/mir/analyze.rs b/src/librustc_codegen_ssa/mir/analyze.rs index 5449dbdc913..d192f2ffb6f 100644 --- a/src/librustc_codegen_ssa/mir/analyze.rs +++ b/src/librustc_codegen_ssa/mir/analyze.rs @@ -105,10 +105,7 @@ fn process_place( ) { let cx = self.fx.cx; - if let [.., elem] = place_ref.projection { - // FIXME(spastorino) include this in the pattern when stabilized - let proj_base = &place_ref.projection[..place_ref.projection.len() - 1]; - + if let [proj_base @ .., elem] = place_ref.projection { // Allow uses of projections that are ZSTs or from scalar fields. let is_consume = match context { PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) | diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index df90da7ee8f..ef9fc36b0f1 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -514,10 +514,8 @@ pub fn codegen_place( }, mir::PlaceRef { base, - projection: [.., mir::ProjectionElem::Deref], + projection: [proj_base @ .., mir::ProjectionElem::Deref], } => { - let proj_base = &place_ref.projection[..place_ref.projection.len() - 1]; - // Load the pointer from its location. self.codegen_consume(bx, &mir::PlaceRef { base, @@ -526,10 +524,8 @@ pub fn codegen_place( } mir::PlaceRef { base, - projection: [.., elem], + projection: [proj_base @ .., elem], } => { - let proj_base = &place_ref.projection[..place_ref.projection.len() - 1]; - // FIXME turn this recursion into iteration let cg_base = self.codegen_place(bx, &mir::PlaceRef { base, diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 1fbedc49ecf..aeee961d2d3 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -179,10 +179,8 @@ fn append_place_to_string( } PlaceRef { base, - projection: [.., elem], + projection: [proj_base @ .., elem], } => { - let proj_base = &place.projection[..place.projection.len() - 1]; - match elem { ProjectionElem::Deref => { let upvar_field_projection = @@ -363,11 +361,9 @@ fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String { self.describe_field_from_ty(&static_.ty, field, None), PlaceRef { base, - projection: [.., elem], + projection: [proj_base @ .., elem], } => match elem { ProjectionElem::Deref => { - let proj_base = &place.projection[..place.projection.len() - 1]; - self.describe_field(PlaceRef { base, projection: proj_base, @@ -384,8 +380,6 @@ fn describe_field(&self, place: PlaceRef<'cx, 'tcx>, field: Field) -> String { ProjectionElem::Index(..) | ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => { - let proj_base = &place.projection[..place.projection.len() - 1]; - self.describe_field(PlaceRef { base, projection: proj_base, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 041047bf7cd..2305984a017 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -2187,10 +2187,8 @@ fn is_mutable<'d>( } PlaceRef { base: _, - projection: [.., elem], + projection: [proj_base @ .., elem], } => { - let proj_base = &place.projection[..place.projection.len() - 1]; - match elem { ProjectionElem::Deref => { let base_ty = diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index d346a4cdfa2..cdba1aafdac 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -305,11 +305,8 @@ fn report_cannot_move_from_borrowed_content( let upvar_field = self.prefixes(move_place.as_ref(), PrefixSet::All) .find_map(|p| self.is_upvar_field_projection(p)); - let deref_base = match deref_target_place.projection { - box [.., ProjectionElem::Deref] => { - let proj_base = - &deref_target_place.projection[..deref_target_place.projection.len() - 1]; - + let deref_base = match &deref_target_place.projection { + box [proj_base @ .., ProjectionElem::Deref] => { PlaceRef { base: &deref_target_place.base, projection: proj_base, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index dbc1d170093..12dc2cd1f91 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -65,10 +65,8 @@ pub(super) fn report_mutability_error( PlaceRef { base: _, - projection: [.., ProjectionElem::Field(upvar_index, _)], + projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { - let proj_base = &the_place_err.projection[..the_place_err.projection.len() - 1]; - debug_assert!(is_closure_or_generator( Place::ty_from(&the_place_err.base, proj_base, self.body, self.infcx.tcx).ty )); @@ -329,10 +327,8 @@ pub(super) fn report_mutability_error( // Also suggest adding mut for upvars PlaceRef { base, - projection: [.., ProjectionElem::Field(upvar_index, _)], + projection: [proj_base @ .., ProjectionElem::Field(upvar_index, _)], } => { - let proj_base = &the_place_err.projection[..the_place_err.projection.len() - 1]; - debug_assert!(is_closure_or_generator( Place::ty_from(base, proj_base, self.body, self.infcx.tcx).ty )); diff --git a/src/librustc_mir/borrow_check/prefixes.rs b/src/librustc_mir/borrow_check/prefixes.rs index 6adc693527f..819678dfaf2 100644 --- a/src/librustc_mir/borrow_check/prefixes.rs +++ b/src/librustc_mir/borrow_check/prefixes.rs @@ -88,10 +88,8 @@ fn next(&mut self) -> Option { } PlaceRef { base: _, - projection: [.., elem], + projection: [proj_base @ .., elem], } => { - let proj_base = &cursor.projection[..cursor.projection.len() - 1]; - match elem { ProjectionElem::Field(_ /*field*/, _ /*ty*/) => { // FIXME: add union handling diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index 1d99470d08b..a4427287c4f 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -436,8 +436,7 @@ fn gather_init(&mut self, place: PlaceRef<'cx, 'tcx>, kind: InitKind) { // Check if we are assigning into a field of a union, if so, lookup the place // of the union so it is marked as initialized again. - if let [.., ProjectionElem::Field(_, _)] = place.projection { - let proj_base = &place.projection[..place.projection.len() - 1]; + if let [proj_base @ .., ProjectionElem::Field(_, _)] = place.projection { if let ty::Adt(def, _) = Place::ty_from(place.base, proj_base, self.builder.body, self.builder.tcx).ty.sty { diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index b949e2f5ddd..2b8e66e3dec 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -90,20 +90,11 @@ fn new(body: &'b Body<'tcx>, tcx: TyCtxt<'tcx>) -> OptimizationFinder<'b, 'tcx> impl Visitor<'tcx> for OptimizationFinder<'b, 'tcx> { fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { if let Rvalue::Ref(_, _, Place { - base: _, - projection: box [.., elem], + base, + projection: box [proj_base @ .., ProjectionElem::Deref], }) = rvalue { - if *elem == ProjectionElem::Deref { - // FIXME remove this once we can use slices patterns - if let Rvalue::Ref(_, _, Place { - base, - projection, - }) = rvalue { - let proj_base = &projection[..projection.len() - 1]; - if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() { - self.optimizations.and_stars.insert(location); - } - } + if Place::ty_from(base, proj_base, self.body, self.tcx).ty.is_region_ptr() { + self.optimizations.and_stars.insert(location); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 27a46d34503..e05b0c96620 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -187,27 +187,28 @@ fn in_projection_structurally( cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>, ) -> bool { - let elem = &place.projection[place.projection.len() - 1]; - let proj_base = &place.projection[..place.projection.len() - 1]; + if let [proj_base @ .., elem] = place.projection { + let base_qualif = Self::in_place(cx, PlaceRef { + base: place.base, + projection: proj_base, + }); + let qualif = base_qualif && Self::mask_for_ty( + cx, + Place::ty_from(place.base, proj_base, cx.body, cx.tcx) + .projection_ty(cx.tcx, elem) + .ty, + ); + match elem { + ProjectionElem::Deref | + ProjectionElem::Subslice { .. } | + ProjectionElem::Field(..) | + ProjectionElem::ConstantIndex { .. } | + ProjectionElem::Downcast(..) => qualif, - let base_qualif = Self::in_place(cx, PlaceRef { - base: place.base, - projection: proj_base, - }); - let qualif = base_qualif && Self::mask_for_ty( - cx, - Place::ty_from(place.base, proj_base, cx.body, cx.tcx) - .projection_ty(cx.tcx, elem) - .ty, - ); - match elem { - ProjectionElem::Deref | - ProjectionElem::Subslice { .. } | - ProjectionElem::Field(..) | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Downcast(..) => qualif, - - ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local), + ProjectionElem::Index(local) => qualif || Self::in_local(cx, *local), + } + } else { + bug!("This should be called if projection is not empty"); } } @@ -290,10 +291,7 @@ fn in_rvalue_structurally(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool Rvalue::Ref(_, _, ref place) => { // Special-case reborrows to be more like a copy of the reference. - if !place.projection.is_empty() { - let elem = &place.projection[place.projection.len() - 1]; - let proj_base = &place.projection[..place.projection.len() - 1]; - + if let box [proj_base @ .., elem] = &place.projection { if ProjectionElem::Deref == *elem { let base_ty = Place::ty_from(&place.base, proj_base, cx.body, cx.tcx).ty; if let ty::Ref(..) = base_ty.sty { @@ -457,31 +455,32 @@ fn in_projection( cx: &ConstCx<'_, 'tcx>, place: PlaceRef<'_, 'tcx>, ) -> bool { - let elem = &place.projection[place.projection.len() - 1]; - let proj_base = &place.projection[..place.projection.len() - 1]; - - match elem { - ProjectionElem::Deref | - ProjectionElem::Downcast(..) => return true, - - ProjectionElem::ConstantIndex {..} | - ProjectionElem::Subslice {..} | - ProjectionElem::Index(_) => {} + if let [proj_base @ .., elem] = place.projection { + match elem { + ProjectionElem::Deref | + ProjectionElem::Downcast(..) => return true, - ProjectionElem::Field(..) => { - if cx.mode == Mode::NonConstFn { - let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty; - if let Some(def) = base_ty.ty_adt_def() { - // No promotion of union field accesses. - if def.is_union() { - return true; + ProjectionElem::ConstantIndex {..} | + ProjectionElem::Subslice {..} | + ProjectionElem::Index(_) => {} + + ProjectionElem::Field(..) => { + if cx.mode == Mode::NonConstFn { + let base_ty = Place::ty_from(place.base, proj_base, cx.body, cx.tcx).ty; + if let Some(def) = base_ty.ty_adt_def() { + // No promotion of union field accesses. + if def.is_union() { + return true; + } } } } } - } - Self::in_projection_structurally(cx, place) + Self::in_projection_structurally(cx, place) + } else { + bug!("This should be called if projection is not empty"); + } } fn in_rvalue(cx: &ConstCx<'_, 'tcx>, rvalue: &Rvalue<'tcx>) -> bool { @@ -866,14 +865,12 @@ fn assign(&mut self, dest: &Place<'tcx>, source: ValueSource<'_, 'tcx>, location // projections are transparent for assignments // we qualify the entire destination at once, even if just a field would have // stricter qualification - (base, proj @ [.., _]) => { - let proj_base = &proj[..proj.len() - 1]; - + (base, [proj_base @ .., _]) => { // Catch more errors in the destination. `visit_place` also checks various // projection rules like union field access and raw pointer deref let context = PlaceContext::MutatingUse(MutatingUseContext::Store); self.visit_place_base(base, context, location); - self.visit_projection(base, proj, context, location); + self.visit_projection(base, dest_projection, context, location); dest_projection = proj_base; }, (&PlaceBase::Static(box Static { @@ -1096,10 +1093,7 @@ fn visit_projection( ); self.super_projection(place_base, proj, context, location); - if !proj.is_empty() { - let elem = &proj[proj.len() - 1]; - let proj_base = &proj[..proj.len() - 1]; - + if let [proj_base @ .., elem] = proj { match elem { ProjectionElem::Deref => { if context.is_mutating_use() { @@ -1187,9 +1181,8 @@ fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { if let Rvalue::Ref(_, kind, ref place) = *rvalue { // Special-case reborrows. let mut reborrow_place = None; - if let box [.., elem] = &place.projection { + if let box [proj_base @ .., elem] = &place.projection { if *elem == ProjectionElem::Deref { - let proj_base = &place.projection[..place.projection.len() - 1]; let base_ty = Place::ty_from(&place.base, proj_base, self.body, self.tcx).ty; if let ty::Ref(..) = base_ty.sty { reborrow_place = Some(proj_base); diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 318049a1ce0..2f900f2638f 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -61,9 +61,7 @@ fn visit_assign(&mut self, rvalue: &Rvalue<'tcx>, location: Location) { if let Rvalue::Use(Operand::Move(ref src_place)) = rvalue { - if let box [.., elem] = &src_place.projection { - let proj_base = &src_place.projection[..src_place.projection.len() - 1]; - + if let box [proj_base @ .., elem] = &src_place.projection { if let ProjectionElem::ConstantIndex{offset: _, min_length: _, from_end: false} = elem { @@ -102,10 +100,7 @@ fn uniform(&mut self, proj: &[PlaceElem<'tcx>], item_ty: &'tcx ty::TyS<'tcx>, size: u32) { - if !proj.is_empty() { - let elem = &proj[proj.len() - 1]; - let proj_base = &proj[..proj.len() - 1]; - + if let [proj_base @ .., elem] = proj { match elem { // uniforms statements like_10 = move _2[:-1]; ProjectionElem::Subslice{from, to} => { @@ -314,11 +309,9 @@ fn try_get_item_source<'a, 'tcx>(local_use: &LocalUse, _, box Rvalue::Use(Operand::Move(Place { base, - projection, + projection: box [proj_base @ .., _], })), - ) = &statement.kind { - let proj_base = &projection[..projection.len() - 1]; - + ) = &statement.kind { return Some((*offset, PlaceRef { base, projection: proj_base, -- GitLab