From c3e71f210ed105dc8ef9d104ff6ddec39baa2258 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 27 May 2019 22:47:30 +0200 Subject: [PATCH] Make eval_place iterate instead of recurse --- src/librustc_mir/transform/const_prop.rs | 79 ++++++++++++------------ 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index b2976cd501e7f..24e7fa009b40c 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> { 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> {