about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/mir/visit.rs58
-rw-r--r--src/librustc_mir/transform/check_consts/validation.rs18
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs121
3 files changed, 110 insertions, 87 deletions
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 1e3b9eb29c7..bfbeeebd1e2 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -166,6 +166,15 @@ macro_rules! make_mir_visitor {
                 self.super_projection(base, projection, context, location);
             }
 
+            fn visit_projection_elem(&mut self,
+                                     base: & $($mutability)? PlaceBase<'tcx>,
+                                     proj_base: & $($mutability)? [PlaceElem<'tcx>],
+                                     elem: & $($mutability)? PlaceElem<'tcx>,
+                                     context: PlaceContext,
+                                     location: Location) {
+                self.super_projection_elem(base, proj_base, elem, context, location);
+            }
+
             fn visit_constant(&mut self,
                               constant: & $($mutability)? Constant<'tcx>,
                               location: Location) {
@@ -725,27 +734,36 @@ macro_rules! make_mir_visitor {
                                 projection: & $($mutability)? [PlaceElem<'tcx>],
                                 context: PlaceContext,
                                 location: Location) {
-                if let [proj_base @ .., elem] = projection {
-                    self.visit_projection(base, proj_base, context, location);
+                let mut cursor = projection;
+                while let [proj_base @ .., elem] = cursor {
+                    cursor = proj_base;
+                    self.visit_projection_elem(base, cursor, elem, context, location);
+                }
+            }
 
-                    match elem {
-                        ProjectionElem::Field(_field, ty) => {
-                            self.visit_ty(ty, TyContext::Location(location));
-                        }
-                        ProjectionElem::Index(local) => {
-                            self.visit_local(
-                                local,
-                                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                                location
-                            );
-                        }
-                        ProjectionElem::Deref |
-                        ProjectionElem::Subslice { from: _, to: _ } |
-                        ProjectionElem::ConstantIndex { offset: _,
-                                                        min_length: _,
-                                                        from_end: _ } |
-                        ProjectionElem::Downcast(_, _) => {
-                        }
+            fn super_projection_elem(&mut self,
+                                     _base: & $($mutability)? PlaceBase<'tcx>,
+                                     _proj_base: & $($mutability)? [PlaceElem<'tcx>],
+                                     elem: & $($mutability)? PlaceElem<'tcx>,
+                                     _context: PlaceContext,
+                                     location: Location) {
+                match elem {
+                    ProjectionElem::Field(_field, ty) => {
+                        self.visit_ty(ty, TyContext::Location(location));
+                    }
+                    ProjectionElem::Index(local) => {
+                        self.visit_local(
+                            local,
+                            PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
+                            location
+                        );
+                    }
+                    ProjectionElem::Deref |
+                    ProjectionElem::Subslice { from: _, to: _ } |
+                    ProjectionElem::ConstantIndex { offset: _,
+                                                    min_length: _,
+                                                    from_end: _ } |
+                    ProjectionElem::Downcast(_, _) => {
                     }
                 }
             }
diff --git a/src/librustc_mir/transform/check_consts/validation.rs b/src/librustc_mir/transform/check_consts/validation.rs
index 2d7b215b13c..87cd39b02cd 100644
--- a/src/librustc_mir/transform/check_consts/validation.rs
+++ b/src/librustc_mir/transform/check_consts/validation.rs
@@ -404,25 +404,25 @@ impl Visitor<'tcx> for Validator<'_, 'mir, 'tcx> {
         self.super_assign(dest, rvalue, location);
     }
 
-    fn visit_projection(
+    fn visit_projection_elem(
         &mut self,
         place_base: &PlaceBase<'tcx>,
-        proj: &[PlaceElem<'tcx>],
+        proj_base: &[PlaceElem<'tcx>],
+        elem: &PlaceElem<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
         trace!(
-            "visit_place_projection: proj={:?} context={:?} location={:?}",
-            proj,
+            "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
+            context={:?} location={:?}",
+            place_base,
+            proj_base,
+            elem,
             context,
             location,
         );
-        self.super_projection(place_base, proj, context, location);
 
-        let (elem, proj_base) = match proj.split_last() {
-            Some(x) => x,
-            None => return,
-        };
+        self.super_projection_elem(place_base, proj_base, elem, context, location);
 
         match elem {
             ProjectionElem::Deref => {
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 2fa6b9d1a29..fbcf9c8cb5e 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1156,82 +1156,87 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
         }
     }
 
-    fn visit_projection(
+    fn visit_projection_elem(
         &mut self,
         place_base: &PlaceBase<'tcx>,
-        proj: &[PlaceElem<'tcx>],
+        proj_base: &[PlaceElem<'tcx>],
+        elem: &PlaceElem<'tcx>,
         context: PlaceContext,
         location: Location,
     ) {
         debug!(
-            "visit_place_projection: proj={:?} context={:?} location={:?}",
-            proj, context, location,
+            "visit_projection_elem: place_base={:?} proj_base={:?} elem={:?} \
+            context={:?} location={:?}",
+            place_base,
+            proj_base,
+            elem,
+            context,
+            location,
         );
-        self.super_projection(place_base, proj, context, location);
 
-        if let [proj_base @ .., elem] = proj {
-            match elem {
-                ProjectionElem::Deref => {
-                    if context.is_mutating_use() {
-                        // `not_const` errors out in const contexts
-                        self.not_const(ops::MutDeref)
-                    }
-                    let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
-                    match self.mode {
-                        Mode::NonConstFn => {}
-                        _ if self.suppress_errors => {}
-                        _ => {
-                            if let ty::RawPtr(_) = base_ty.kind {
-                                if !self.tcx.features().const_raw_ptr_deref {
-                                    self.record_error(ops::RawPtrDeref);
-                                    emit_feature_err(
-                                        &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
-                                        self.span, GateIssue::Language,
-                                        &format!(
-                                            "dereferencing raw pointers in {}s is unstable",
-                                            self.mode,
-                                        ),
-                                    );
-                                }
+        self.super_projection_elem(place_base, proj_base, elem, context, location);
+
+        match elem {
+            ProjectionElem::Deref => {
+                if context.is_mutating_use() {
+                    // `not_const` errors out in const contexts
+                    self.not_const(ops::MutDeref)
+                }
+                let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+                match self.mode {
+                    Mode::NonConstFn => {}
+                    _ if self.suppress_errors => {}
+                    _ => {
+                        if let ty::RawPtr(_) = base_ty.kind {
+                            if !self.tcx.features().const_raw_ptr_deref {
+                                self.record_error(ops::RawPtrDeref);
+                                emit_feature_err(
+                                    &self.tcx.sess.parse_sess, sym::const_raw_ptr_deref,
+                                    self.span, GateIssue::Language,
+                                    &format!(
+                                        "dereferencing raw pointers in {}s is unstable",
+                                        self.mode,
+                                    ),
+                                );
                             }
                         }
                     }
                 }
+            }
 
-                ProjectionElem::ConstantIndex {..} |
-                ProjectionElem::Subslice {..} |
-                ProjectionElem::Field(..) |
-                ProjectionElem::Index(_) => {
-                    let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
-                    if let Some(def) = base_ty.ty_adt_def() {
-                        if def.is_union() {
-                            match self.mode {
-                                Mode::ConstFn => {
-                                    if !self.tcx.features().const_fn_union
-                                        && !self.suppress_errors
-                                    {
-                                        self.record_error(ops::UnionAccess);
-                                        emit_feature_err(
-                                            &self.tcx.sess.parse_sess, sym::const_fn_union,
-                                            self.span, GateIssue::Language,
-                                            "unions in const fn are unstable",
-                                        );
-                                    }
-                                },
+            ProjectionElem::ConstantIndex {..} |
+            ProjectionElem::Subslice {..} |
+            ProjectionElem::Field(..) |
+            ProjectionElem::Index(_) => {
+                let base_ty = Place::ty_from(place_base, proj_base, self.body, self.tcx).ty;
+                if let Some(def) = base_ty.ty_adt_def() {
+                    if def.is_union() {
+                        match self.mode {
+                            Mode::ConstFn => {
+                                if !self.tcx.features().const_fn_union
+                                    && !self.suppress_errors
+                                {
+                                    self.record_error(ops::UnionAccess);
+                                    emit_feature_err(
+                                        &self.tcx.sess.parse_sess, sym::const_fn_union,
+                                        self.span, GateIssue::Language,
+                                        "unions in const fn are unstable",
+                                    );
+                                }
+                            },
 
-                                | Mode::NonConstFn
-                                | Mode::Static
-                                | Mode::StaticMut
-                                | Mode::Const
-                                => {},
-                            }
+                            | Mode::NonConstFn
+                            | Mode::Static
+                            | Mode::StaticMut
+                            | Mode::Const
+                            => {},
                         }
                     }
                 }
+            }
 
-                ProjectionElem::Downcast(..) => {
-                    self.not_const(ops::Downcast)
-                }
+            ProjectionElem::Downcast(..) => {
+                self.not_const(ops::Downcast)
             }
         }
     }