Skip to content

Commit 1dc9bbb

Browse files
authored
Rollup merge of rust-lang#61247 - spastorino:eval-place-iterate, r=wesleywiser
Make eval_place iterate instead of recurse r? @oli-obk
2 parents ffb4ceb + c3e71f2 commit 1dc9bbb

File tree

1 file changed

+41
-38
lines changed

1 file changed

+41
-38
lines changed

src/librustc_mir/transform/const_prop.rs

+41-38
Original file line numberDiff line numberDiff line change
@@ -296,47 +296,50 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
296296

297297
fn eval_place(&mut self, place: &Place<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {
298298
trace!("eval_place(place={:?})", place);
299-
match *place {
300-
Place::Base(PlaceBase::Local(loc)) => self.places[loc].clone(),
301-
Place::Projection(ref proj) => match proj.elem {
302-
ProjectionElem::Field(field, _) => {
303-
trace!("field proj on {:?}", proj.base);
304-
let base = self.eval_place(&proj.base, source_info)?;
299+
place.iterate(|place_base, place_projection| {
300+
let mut eval = match place_base {
301+
PlaceBase::Local(loc) => self.places[*loc].clone()?,
302+
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => {
303+
let generics = self.tcx.generics_of(self.source.def_id());
304+
if generics.requires_monomorphization(self.tcx) {
305+
// FIXME: can't handle code with generics
306+
return None;
307+
}
308+
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
309+
let instance = Instance::new(self.source.def_id(), substs);
310+
let cid = GlobalId {
311+
instance,
312+
promoted: Some(*promoted),
313+
};
314+
// cannot use `const_eval` here, because that would require having the MIR
315+
// for the current function available, but we're producing said MIR right now
305316
let res = self.use_ecx(source_info, |this| {
306-
this.ecx.operand_field(base, field.index() as u64)
317+
let mir = &this.promoted[*promoted];
318+
eval_promoted(this.tcx, cid, mir, this.param_env)
307319
})?;
308-
Some(res)
309-
},
310-
// We could get more projections by using e.g., `operand_projection`,
311-
// but we do not even have the stack frame set up properly so
312-
// an `Index` projection would throw us off-track.
313-
_ => None,
314-
},
315-
Place::Base(
316-
PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..})
317-
) => {
318-
let generics = self.tcx.generics_of(self.source.def_id());
319-
if generics.requires_monomorphization(self.tcx) {
320-
// FIXME: can't handle code with generics
321-
return None;
320+
trace!("evaluated promoted {:?} to {:?}", promoted, res);
321+
res.into()
322322
}
323-
let substs = InternalSubsts::identity_for_item(self.tcx, self.source.def_id());
324-
let instance = Instance::new(self.source.def_id(), substs);
325-
let cid = GlobalId {
326-
instance,
327-
promoted: Some(promoted),
328-
};
329-
// cannot use `const_eval` here, because that would require having the MIR
330-
// for the current function available, but we're producing said MIR right now
331-
let res = self.use_ecx(source_info, |this| {
332-
let mir = &this.promoted[promoted];
333-
eval_promoted(this.tcx, cid, mir, this.param_env)
334-
})?;
335-
trace!("evaluated promoted {:?} to {:?}", promoted, res);
336-
Some(res.into())
337-
},
338-
_ => None,
339-
}
323+
_ => return None,
324+
};
325+
326+
for proj in place_projection {
327+
match proj.elem {
328+
ProjectionElem::Field(field, _) => {
329+
trace!("field proj on {:?}", proj.base);
330+
eval = self.use_ecx(source_info, |this| {
331+
this.ecx.operand_field(eval, field.index() as u64)
332+
})?;
333+
},
334+
// We could get more projections by using e.g., `operand_projection`,
335+
// but we do not even have the stack frame set up properly so
336+
// an `Index` projection would throw us off-track.
337+
_ => return None,
338+
}
339+
}
340+
341+
Some(eval)
342+
})
340343
}
341344

342345
fn eval_operand(&mut self, op: &Operand<'tcx>, source_info: SourceInfo) -> Option<Const<'tcx>> {

0 commit comments

Comments
 (0)