Skip to content

Commit

Permalink
Make eval_place iterate instead of recurse
Browse files Browse the repository at this point in the history
  • Loading branch information
spastorino committed May 27, 2019
1 parent 4dbc7f9 commit c3e71f2
Showing 1 changed file with 41 additions and 38 deletions.
79 changes: 41 additions & 38 deletions src/librustc_mir/transform/const_prop.rs
Expand Up @@ -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>> {
Expand Down

0 comments on commit c3e71f2

Please sign in to comment.