about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/visit.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/analyze.rs5
-rw-r--r--src/librustc_codegen_ssa/mir/place.rs8
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs10
-rw-r--r--src/librustc_mir/borrow_check/mod.rs4
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs7
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs8
-rw-r--r--src/librustc_mir/borrow_check/prefixes.rs4
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs3
-rw-r--r--src/librustc_mir/transform/instcombine.rs17
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs99
-rw-r--r--src/librustc_mir/transform/uniform_array_move_out.rs15
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 @@ macro_rules! make_mir_visitor {
                                 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 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
     ) {
         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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             },
             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 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
             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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 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 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
             }
             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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
 
             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 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             // 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 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
                 }
                 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 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
 
         // 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 @@ impl 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 @@ trait Qualif {
         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 @@ trait Qualif {
 
             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 @@ impl Qualif for IsNotPromotable {
         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 @@ impl<'a, 'tcx> Checker<'a, 'tcx> {
                 // 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 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         );
         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 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         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 @@ impl<'a, 'tcx> Visitor<'tcx> for UniformArrayMoveOutVisitor<'a, 'tcx> {
                     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 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> {
                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 @@ impl RestoreSubsliceArrayMoveOut {
                         _,
                         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,