about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSmitty <me@smitop.com>2021-06-30 15:38:31 -0400
committerSmitty <me@smitop.com>2021-06-30 15:38:31 -0400
commit3e20129a18b34ba3aa13efaa53ddfa09dfb1fb7b (patch)
tree9783c788b4733dbde082c05fac0624ba14f10869
parent12a8d106f6a38f45ec01c1b7d3b2c4bfe62d741d (diff)
downloadrust-3e20129a18b34ba3aa13efaa53ddfa09dfb1fb7b.tar.gz
rust-3e20129a18b34ba3aa13efaa53ddfa09dfb1fb7b.zip
Delay ICE on evaluation fail
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs5
-rw-r--r--compiler/rustc_mir/src/transform/const_prop.rs83
2 files changed, 20 insertions, 68 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index 273609c639c..49e0af9a3a4 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -8,6 +8,7 @@ use std::ptr;
 
 use rustc_ast::Mutability;
 use rustc_data_structures::sorted_map::SortedMap;
+use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Align, HasDataLayout, Size};
 
 use super::{
@@ -15,6 +16,7 @@ use super::{
     ResourceExhaustionInfo, Scalar, ScalarMaybeUninit, UndefinedBehaviorInfo, UninitBytesAccess,
     UnsupportedOpInfo,
 };
+use crate::ty;
 
 /// This type represents an Allocation in the Miri/CTFE core engine.
 ///
@@ -132,6 +134,9 @@ impl<Tag> Allocation<Tag> {
             // deterministic. However, we can be non-determinstic here because all uses of const
             // evaluation (including ConstProp!) will make compilation fail (via hard error
             // or ICE) upon encountering a `MemoryExhausted` error.
+            ty::tls::with(|tcx| {
+                tcx.sess.delay_span_bug(DUMMY_SP, "exhausted memory during interpreation")
+            });
             InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
         })?;
         bytes.resize(size.bytes_usize(), 0);
diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs
index c6a193ba446..2a6924d354a 100644
--- a/compiler/rustc_mir/src/transform/const_prop.rs
+++ b/compiler/rustc_mir/src/transform/const_prop.rs
@@ -31,9 +31,9 @@ use rustc_trait_selection::traits;
 use crate::const_eval::ConstEvalErr;
 use crate::interpret::{
     self, compile_time_machine, AllocId, Allocation, ConstValue, CtfeValidationMode, Frame, ImmTy,
-    Immediate, InterpCx, InterpError, InterpResult, LocalState, LocalValue, MemPlace, Memory,
-    MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, ResourceExhaustionInfo, Scalar,
-    ScalarMaybeUninit, StackPopCleanup, StackPopUnwind,
+    Immediate, InterpCx, InterpResult, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy,
+    Operand as InterpOperand, PlaceTy, Pointer, Scalar, ScalarMaybeUninit, StackPopCleanup,
+    StackPopUnwind,
 };
 use crate::transform::MirPass;
 
@@ -393,12 +393,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
             .filter(|ret_layout| {
                 !ret_layout.is_zst() && ret_layout.size < Size::from_bytes(MAX_ALLOC_LIMIT)
             })
-            .and_then(|ret_layout| {
-                let alloc = ecx.allocate(ret_layout, MemoryKind::Stack);
-                Self::check_interpresult(tcx, &alloc);
-                alloc.ok()
-            })
-            .map(Into::into);
+            .map(|ret_layout| {
+                ecx.allocate(ret_layout, MemoryKind::Stack)
+                    .expect("couldn't perform small allocation")
+                    .into()
+            });
 
         ecx.push_stack_frame(
             Instance::new(def_id, substs),
@@ -421,27 +420,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         }
     }
 
-    /// Some `InterpError`s could be ignored but must not be to ensure that queries are stable.
-    fn check_interpresult<T>(tcx: TyCtxt<'tcx>, error: &InterpResult<'tcx, T>) {
-        if let Err(e) = error {
-            if matches!(
-                e.kind(),
-                InterpError::ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted)
-            ) {
-                // Memory errors can't be ignored since otherwise the amount of available
-                // memory influences the result of optimization and the build. The error
-                // doesn't need to be fatal since no code will actually be generated anyways.
-                tcx.sess.fatal("memory exhausted during optimization");
-            }
-        }
-    }
-
     fn get_const(&self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
         let op = match self.ecx.eval_place_to_op(place, None) {
             Ok(op) => op,
             Err(e) => {
                 trace!("get_const failed: {}", e);
-                Self::check_interpresult::<()>(self.tcx, &Err(e));
                 return None;
             }
         };
@@ -513,19 +496,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                         },
                         ConstantKind::Val(_, ty) => ty.needs_subst(),
                     };
-                    // Memory errors can't be ignored since otherwise the amount of available
-                    // memory influences the result of optimization and the build. The error
-                    // doesn't need to be fatal since no code will actually be generated anyways.
-                    // FIXME(#86255): use err.error.is_hard_err(), but beware of backwards
-                    // compatibility and interactions with promoteds
-                    if lint_only
-                        && !matches!(
-                            err.error,
-                            InterpError::ResourceExhaustion(
-                                ResourceExhaustionInfo::MemoryExhausted,
-                            ),
-                        )
-                    {
+                    if lint_only {
                         // Out of backwards compatibility we cannot report hard errors in unused
                         // generic functions using associated constants of the generic parameters.
                         err.report_as_lint(tcx, "erroneous constant used", lint_root, Some(c.span));
@@ -543,12 +514,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
     /// Returns the value, if any, of evaluating `place`.
     fn eval_place(&mut self, place: Place<'tcx>) -> Option<OpTy<'tcx>> {
         trace!("eval_place(place={:?})", place);
-        let tcx = self.tcx;
-        self.use_ecx(|this| {
-            let val = this.ecx.eval_place_to_op(place, None);
-            Self::check_interpresult(tcx, &val);
-            val
-        })
+        self.use_ecx(|this| this.ecx.eval_place_to_op(place, None))
     }
 
     /// Returns the value, if any, of evaluating `op`. Calls upon `eval_constant`
@@ -609,17 +575,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         right: &Operand<'tcx>,
         source_info: SourceInfo,
     ) -> Option<()> {
-        let tcx = self.tcx;
-        let r = self.use_ecx(|this| {
-            let val = this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?);
-            Self::check_interpresult(tcx, &val);
-            val
-        });
-        let l = self.use_ecx(|this| {
-            let val = this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?);
-            Self::check_interpresult(tcx, &val);
-            val
-        });
+        let r = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(right, None)?));
+        let l = self.use_ecx(|this| this.ecx.read_immediate(&this.ecx.eval_operand(left, None)?));
         // Check for exceeding shifts *even if* we cannot evaluate the LHS.
         if op == BinOp::Shr || op == BinOp::Shl {
             let r = r?;
@@ -785,24 +742,18 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
         rvalue: &Rvalue<'tcx>,
         place: Place<'tcx>,
     ) -> Option<()> {
-        let tcx = self.tcx;
         self.use_ecx(|this| {
             match rvalue {
                 Rvalue::BinaryOp(op, box (left, right))
                 | Rvalue::CheckedBinaryOp(op, box (left, right)) => {
                     let l = this.ecx.eval_operand(left, None);
                     let r = this.ecx.eval_operand(right, None);
-                    Self::check_interpresult(tcx, &l);
-                    Self::check_interpresult(tcx, &r);
 
                     let const_arg = match (l, r) {
                         (Ok(ref x), Err(_)) | (Err(_), Ok(ref x)) => this.ecx.read_immediate(x)?,
                         (Err(e), Err(_)) => return Err(e),
                         (Ok(_), Ok(_)) => {
-                            Self::check_interpresult(
-                                tcx,
-                                &this.ecx.eval_rvalue_into_place(rvalue, place),
-                            );
+                            this.ecx.eval_rvalue_into_place(rvalue, place)?;
                             return Ok(());
                         }
                     };
@@ -838,16 +789,12 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
                             }
                         }
                         _ => {
-                            let res = this.ecx.eval_rvalue_into_place(rvalue, place);
-                            Self::check_interpresult(tcx, &res);
-                            res?
+                            this.ecx.eval_rvalue_into_place(rvalue, place)?;
                         }
                     }
                 }
                 _ => {
-                    let res = this.ecx.eval_rvalue_into_place(rvalue, place);
-                    Self::check_interpresult(tcx, &res);
-                    res?
+                    this.ecx.eval_rvalue_into_place(rvalue, place)?;
                 }
             }