From e8beea701955dcce855d1ac72ccd4c9d54f8382c Mon Sep 17 00:00:00 2001
From: Santiago Pastorino <spastorino@gmail.com>
Date: Fri, 24 May 2019 15:38:42 +0200
Subject: [PATCH] Make eval_place iterate instead of recurse

---
 src/librustc_mir/interpret/place.rs | 58 ++++++++++++++---------------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index 65e5e23e38424..57d5ab71ecafd 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -607,42 +607,42 @@ where
     /// place; for reading, a more efficient alternative is `eval_place_for_read`.
     pub fn eval_place(
         &mut self,
-        mir_place: &mir::Place<'tcx>
+        mir_place: &mir::Place<'tcx>,
     ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
-        use rustc::mir::Place::*;
         use rustc::mir::PlaceBase;
-        let place = match mir_place {
-            Base(PlaceBase::Local(mir::RETURN_PLACE)) => match self.frame().return_place {
-                Some(return_place) =>
-                    // We use our layout to verify our assumption; caller will validate
-                    // their layout on return.
-                    PlaceTy {
-                        place: *return_place,
-                        layout: self.layout_of(self.monomorphize(self.frame().mir.return_ty())?)?,
+
+        mir_place.iterate(|place_base, place_projection| {
+            let mut place = match place_base {
+                PlaceBase::Local(mir::RETURN_PLACE) => match self.frame().return_place {
+                    Some(return_place) => {
+                        // We use our layout to verify our assumption; caller will validate
+                        // their layout on return.
+                        PlaceTy {
+                            place: *return_place,
+                            layout: self
+                                .layout_of(self.monomorphize(self.frame().mir.return_ty())?)?,
+                        }
+                    }
+                    None => return err!(InvalidNullPointerUsage),
+                },
+                PlaceBase::Local(local) => PlaceTy {
+                    // This works even for dead/uninitialized locals; we check further when writing
+                    place: Place::Local {
+                        frame: self.cur_frame(),
+                        local: *local,
                     },
-                None => return err!(InvalidNullPointerUsage),
-            },
-            Base(PlaceBase::Local(local)) => PlaceTy {
-                // This works even for dead/uninitialized locals; we check further when writing
-                place: Place::Local {
-                    frame: self.cur_frame(),
-                    local: *local,
+                    layout: self.layout_of_local(self.frame(), *local, None)?,
                 },
-                layout: self.layout_of_local(self.frame(), *local, None)?,
-            },
-
-            Projection(proj) => {
-                let place = self.eval_place(&proj.base)?;
-                self.place_projection(place, &proj.elem)?
-            }
+                PlaceBase::Static(place_static) => self.eval_static_to_mplace(place_static)?.into(),
+            };
 
-            Base(PlaceBase::Static(place_static)) => {
-                self.eval_static_to_mplace(place_static)?.into()
+            for proj in place_projection {
+                place = self.place_projection(place, &proj.elem)?
             }
-        };
 
-        self.dump_place(place.place);
-        Ok(place)
+            self.dump_place(place.place);
+            Ok(place)
+        })
     }
 
     /// Write a scalar to a place