Skip to content

Commit 4c934df

Browse files
committed
Properly evaluate non-consts in const prop
1 parent 9f22794 commit 4c934df

File tree

1 file changed

+51
-8
lines changed

1 file changed

+51
-8
lines changed

compiler/rustc_mir/src/transform/const_prop.rs

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
393393
.filter(|ret_layout| {
394394
!ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
395395
})
396-
// hopefully all types will allocate, since large types have already been removed
397-
.and_then(|ret_layout| ecx.allocate(ret_layout, MemoryKind::Stack).ok())
396+
.and_then(|ret_layout| {
397+
let alloc = ecx.allocate(ret_layout, MemoryKind::Stack);
398+
Self::check_interpresult(tcx, &alloc);
399+
alloc.ok()
400+
})
398401
.map(Into::into);
399402

400403
ecx.push_stack_frame(
@@ -418,11 +421,27 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
418421
}
419422
}
420423

424+
/// Some `InterpError`s could be ignored but must not be to ensure that queries are stable.
425+
fn check_interpresult<T>(tcx: TyCtxt<'tcx>, error: &InterpResult<'tcx, T>) {
426+
if let Err(e) = error {
427+
if matches!(
428+
e.kind(),
429+
InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
430+
) {
431+
// Memory errors can't be ignored since otherwise the amount of available
432+
// memory influences the result of optimization and the build. The error
433+
// doesn't need to be fatal since no code will actually be generated anyways.
434+
tcx.sess.fatal("memory exhausted during optimization");
435+
}
436+
}
437+
}
438+
421439
fn get_const(&self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
422440
let op = match self.ecx.eval_place_to_op(place, None) {
423441
Ok(op) => op,
424442
Err(e) => {
425443
trace!("get_const failed: {}", e);
444+
Self::check_interpresult::<()>(self.tcx, &Err(e));
426445
return None;
427446
}
428447
};
@@ -524,7 +543,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
524543
/// Returns the value, if any, of evaluating `place`.
525544
fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
526545
trace!("eval_place(place={:?})", place);
527-
self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
546+
let tcx = self.tcx;
547+
self.use_ecx(|this| {
548+
let val = this.ecx.eval_place_to_op(place, None);
549+
Self::check_interpresult(tcx, &val);
550+
val
551+
})
528552
}
529553

530554
/// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
@@ -585,8 +609,17 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
585609
right: &Operand<'tcx>,
586610
source_info: SourceInfo,
587611
) -> Option<()> {
588-
let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
589-
let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
612+
let tcx = self.tcx;
613+
let r = self.use_ecx(|this| {
614+
let val = this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?);
615+
Self::check_interpresult(tcx, &val);
616+
val
617+
});
618+
let l = self.use_ecx(|this| {
619+
let val = this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?);
620+
Self::check_interpresult(tcx, &val);
621+
val
622+
});
590623
// Check for exceeding shifts *even if* we cannot evaluate the LHS.
591624
if op == BinOp::Shr || op == BinOp::Shl {
592625
let r = r?;
@@ -752,18 +785,24 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
752785
rvalue: &Rvalue<'tcx>,
753786
place: Place<'tcx>,
754787
) -> Option<()> {
788+
let tcx = self.tcx;
755789
self.use_ecx(|this| {
756790
match rvalue {
757791
Rvalue::BinaryOp(op, box (left, right))
758792
| Rvalue::CheckedBinaryOp(op, box (left, right)) => {
759793
let l = this.ecx.eval_operand(left, None);
760794
let r = this.ecx.eval_operand(right, None);
795+
Self::check_interpresult(tcx, &l);
796+
Self::check_interpresult(tcx, &r);
761797

762798
let const_arg = match (l, r) {
763799
(Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
764800
(Err(e), Err(_)) => return Err(e),
765801
(Ok(_), Ok(_)) => {
766-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
802+
Self::check_interpresult(
803+
tcx,
804+
&this.ecx.eval_rvalue_into_place(rvalue, place),
805+
);
767806
return Ok(());
768807
}
769808
};
@@ -799,12 +838,16 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
799838
}
800839
}
801840
_ => {
802-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
841+
let res = this.ecx.eval_rvalue_into_place(rvalue, place);
842+
Self::check_interpresult(tcx, &res);
843+
res?
803844
}
804845
}
805846
}
806847
_ => {
807-
this.ecx.eval_rvalue_into_place(rvalue, place)?;
848+
let res = this.ecx.eval_rvalue_into_place(rvalue, place);
849+
Self::check_interpresult(tcx, &res);
850+
res?
808851
}
809852
}
810853

0 commit comments

Comments
 (0)