about summary refs log tree commit diff
path: root/src/librustc_mir/transform
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2019-05-27 22:47:30 +0200
committerSantiago Pastorino <spastorino@gmail.com>2019-05-27 22:52:03 +0200
commitc3e71f210ed105dc8ef9d104ff6ddec39baa2258 (patch)
treede1b52dbd3ba148994dac8a3a1dc150b23ff2d57 /src/librustc_mir/transform
parent4dbc7f96d6438b93c9274675b276cfe934164704 (diff)
downloadrust-c3e71f210ed105dc8ef9d104ff6ddec39baa2258.tar.gz
rust-c3e71f210ed105dc8ef9d104ff6ddec39baa2258.zip
Make eval_place iterate instead of recurse
Diffstat (limited to 'src/librustc_mir/transform')
-rw-r--r--src/librustc_mir/transform/const_prop.rs79
1 files changed, 41 insertions, 38 deletions
diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs
index b2976cd501e..24e7fa009b4 100644
--- a/src/librustc_mir/transform/const_prop.rs
+++ b/src/librustc_mir/transform/const_prop.rs
@@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
 
     fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        match *place {
-            Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
-            Place::Projection(ref proj) => match proj.elem {
-                ProjectionElem::Field(field, _) => {
-                    trace!("field proj on {:?}", proj.base);
-                    let base = self.eval_place(&proj.base, source_info)?;
+        place.iterate(|place_base, place_projection| {
+            let mut eval = match place_base {
+                PlaceBase::Local(loc) => self.places[*loc].clone()?,
+                PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => {
+                    let generics = self.tcx.generics_of(self.source.def_id());
+                    if generics.requires_monomorphization(self.tcx) {
+                        // FIXME: can't handle code with generics
+                        return None;
+                    }
+                    let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
+                    let instance = Instance::new(self.source.def_id(), substs);
+                    let cid = GlobalId {
+                        instance,
+                        promoted: Some(*promoted),
+                    };
+                    // cannot use `const_eval` here, because that would require having the MIR
+                    // for the current function available, but we're producing said MIR right now
                     let res = self.use_ecx(source_info, |this| {
-                        this.ecx.operand_field(base, field.index() as u64)
+                        let mir = &this.promoted[*promoted];
+                        eval_promoted(this.tcx, cid, mir, this.param_env)
                     })?;
-                    Some(res)
-                },
-                // We could get more projections by using e.g., `operand_projection`,
-                // but we do not even have the stack frame set up properly so
-                // an `Index` projection would throw us off-track.
-                _ => None,
-            },
-            Place::Base(
-                PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
-            ) => {
-                let generics = self.tcx.generics_of(self.source.def_id());
-                if generics.requires_monomorphization(self.tcx) {
-                    // FIXME: can't handle code with generics
-                    return None;
+                    trace!("evaluated promoted {:?} to {:?}", promoted, res);
+                    res.into()
                 }
-                let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
-                let instance = Instance::new(self.source.def_id(), substs);
-                let cid = GlobalId {
-                    instance,
-                    promoted: Some(promoted),
-                };
-                // cannot use `const_eval` here, because that would require having the MIR
-                // for the current function available, but we're producing said MIR right now
-                let res = self.use_ecx(source_info, |this| {
-                    let mir = &this.promoted[promoted];
-                    eval_promoted(this.tcx, cid, mir, this.param_env)
-                })?;
-                trace!("evaluated promoted {:?} to {:?}", promoted, res);
-                Some(res.into())
-            },
-            _ => None,
-        }
+                _ => return None,
+            };
+
+            for proj in place_projection {
+                match proj.elem {
+                    ProjectionElem::Field(field, _) => {
+                        trace!("field proj on {:?}", proj.base);
+                        eval = self.use_ecx(source_info, |this| {
+                            this.ecx.operand_field(eval, field.index() as u64)
+                        })?;
+                    },
+                    // We could get more projections by using e.g., `operand_projection`,
+                    // but we do not even have the stack frame set up properly so
+                    // an `Index` projection would throw us off-track.
+                    _ => return None,
+                }
+            }
+
+            Some(eval)
+        })
     }
 
     fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {