Make eval_place iterate instead of recurse
This commit is contained in:
parent
4dbc7f96d6
commit
c3e71f210e
@ -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>> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user