]> git.lizzy.rs Git - rust.git/commitdiff
allow for failure of subst_normalize_erasing_regions in const_eval
authorb-naber <bn263@gmx.de>
Sun, 5 Dec 2021 10:13:51 +0000 (11:13 +0100)
committerb-naber <bn263@gmx.de>
Sun, 5 Dec 2021 11:43:39 +0000 (12:43 +0100)
compiler/rustc_const_eval/src/interpret/eval_context.rs
compiler/rustc_const_eval/src/interpret/operand.rs
compiler/rustc_const_eval/src/interpret/place.rs
compiler/rustc_const_eval/src/interpret/step.rs
compiler/rustc_middle/src/ty/instance.rs
compiler/rustc_middle/src/ty/normalize_erasing_regions.rs

index cf084faade8cc6c69e8e5cabbe3fc13f7cc63b73..d46950ed90315c24f2d87d7c7fa6ecabbe7ac0ec 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_index::vec::IndexVec;
 use rustc_macros::HashStable;
 use rustc_middle::mir;
+use rustc_middle::mir::interpret::{InterpError, InvalidProgramInfo};
 use rustc_middle::ty::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::{
     self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
@@ -14,7 +15,7 @@
 use rustc_mir_dataflow::storage::AlwaysLiveLocals;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::Limit;
-use rustc_span::{Pos, Span};
+use rustc_span::{Pos, Span, DUMMY_SP};
 use rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
 
 use super::{
@@ -508,7 +509,7 @@ pub fn load_mir(
     pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
         &self,
         value: T,
-    ) -> T {
+    ) -> Result<T, InterpError<'tcx>> {
         self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
     }
 
@@ -518,8 +519,18 @@ pub(super) fn subst_from_frame_and_normalize_erasing_regions<T: TypeFoldable<'tc
         &self,
         frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
         value: T,
-    ) -> T {
-        frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
+    ) -> Result<T, InterpError<'tcx>> {
+        frame
+            .instance
+            .try_subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
+            .or_else(|e| {
+                self.tcx.sess.delay_span_bug(
+                    DUMMY_SP,
+                    format!("failed to normalize {}", e.get_type_for_failure()).as_str(),
+                );
+
+                Err(InterpError::InvalidProgram(InvalidProgramInfo::TooGeneric))
+            })
     }
 
     /// The `substs` are assumed to already be in our interpreter "universe" (param_env).
@@ -554,7 +565,7 @@ pub fn layout_of_local(
                 let layout = from_known_layout(self.tcx, self.param_env, layout, || {
                     let local_ty = frame.body.local_decls[local].ty;
                     let local_ty =
-                        self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty);
+                        self.subst_from_frame_and_normalize_erasing_regions(frame, local_ty)?;
                     self.layout_of(local_ty)
                 })?;
                 if let Some(state) = frame.locals.get(local) {
@@ -702,7 +713,7 @@ pub fn push_stack_frame(
         for const_ in &body.required_consts {
             let span = const_.span;
             let const_ =
-                self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal);
+                self.subst_from_current_frame_and_normalize_erasing_regions(const_.literal)?;
             self.mir_const_to_op(&const_, None).map_err(|err| {
                 // If there was an error, set the span of the current frame to this constant.
                 // Avoiding doing this when evaluation succeeds.
index de9e94ce2ac0c820137e5edcb9c3f68ce20f848e..e82ce73c814ff1a65f9aae47b180b1f61c1d326d 100644 (file)
@@ -512,7 +512,7 @@ pub fn eval_place_to_op(
             self.param_env,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
                 place.ty(&self.frame().body.local_decls, *self.tcx).ty
-            ))?,
+            )?)?,
             op.layout,
         ));
         Ok(op)
@@ -534,7 +534,7 @@ pub fn eval_operand(
 
             Constant(ref constant) => {
                 let val =
-                    self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal);
+                    self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?;
                 // This can still fail:
                 // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
                 //   checked yet.
index d7f2853fc86f508a26d70aa3b61580c97db0a2f6..4c95da896a2230a11d6793e3bf18e468d12a0173 100644 (file)
@@ -643,7 +643,7 @@ pub fn eval_place(
             self.param_env,
             self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
                 place.ty(&self.frame().body.local_decls, *self.tcx).ty
-            ))?,
+            )?)?,
             place_ty.layout,
         ));
         Ok(place_ty)
index 9299ae2b2b9f8f6708f9a1a1646e23818a96f260..992cef1cb6aa0cb8151138beeea64c094f4b4839 100644 (file)
@@ -276,7 +276,7 @@ pub fn eval_rvalue_into_place(
             }
 
             NullaryOp(null_op, ty) => {
-                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty);
+                let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty)?;
                 let layout = self.layout_of(ty)?;
                 if layout.is_unsized() {
                     // FIXME: This should be a span_bug (#80742)
@@ -302,7 +302,8 @@ pub fn eval_rvalue_into_place(
 
             Cast(cast_kind, ref operand, cast_ty) => {
                 let src = self.eval_operand(operand, None)?;
-                let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty);
+                let cast_ty =
+                    self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty)?;
                 self.cast(&src, cast_kind, cast_ty, &dest)?;
             }
 
index 4b38105e44717e52300e5b6f9e789e58f8093d12..2d301262730642aeaefefc3a59f290a82ba507f8 100644 (file)
@@ -7,6 +7,7 @@
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::lang_items::LangItem;
 use rustc_macros::HashStable;
+use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
 
 use std::fmt;
 
@@ -575,6 +576,23 @@ pub fn subst_mir_and_normalize_erasing_regions<T>(
         }
     }
 
+    #[inline(always)]
+    pub fn try_subst_mir_and_normalize_erasing_regions<T>(
+        &self,
+        tcx: TyCtxt<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        v: T,
+    ) -> Result<T, NormalizationError<'tcx>>
+    where
+        T: TypeFoldable<'tcx> + Clone,
+    {
+        if let Some(substs) = self.substs_for_mir_body() {
+            tcx.try_subst_and_normalize_erasing_regions(substs, param_env, v)
+        } else {
+            tcx.try_normalize_erasing_regions(param_env, v)
+        }
+    }
+
     /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by
     /// identity parameters if they are determined to be unused in `instance.def`.
     pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
index c0e1360640fd2647227c8a9946ef0d0d1eecdfbc..c472d4a5a4dc2524762c8dc55076edbd4dd7f9f5 100644 (file)
@@ -115,6 +115,8 @@ pub fn normalize_erasing_late_bound_regions<T>(
     /// Monomorphizes a type from the AST by first applying the
     /// in-scope substitutions and then normalizing any associated
     /// types.
+    /// Panics if normalization fails. In case normalization might fail
+    /// use `try_subst_and_normalize_erasing_regions` instead.
     pub fn subst_and_normalize_erasing_regions<T>(
         self,
         param_substs: SubstsRef<'tcx>,
@@ -134,6 +136,30 @@ pub fn subst_and_normalize_erasing_regions<T>(
         let substituted = value.subst(self, param_substs);
         self.normalize_erasing_regions(param_env, substituted)
     }
+
+    /// Monomorphizes a type from the AST by first applying the
+    /// in-scope substitutions and then trying to normalize any associated
+    /// types. Contrary to `subst_and_normalize_erasing_regions` this does
+    /// not assume that normalization succeeds.
+    pub fn try_subst_and_normalize_erasing_regions<T>(
+        self,
+        param_substs: SubstsRef<'tcx>,
+        param_env: ty::ParamEnv<'tcx>,
+        value: T,
+    ) -> Result<T, NormalizationError<'tcx>>
+    where
+        T: TypeFoldable<'tcx>,
+    {
+        debug!(
+            "subst_and_normalize_erasing_regions(\
+             param_substs={:?}, \
+             value={:?}, \
+             param_env={:?})",
+            param_substs, value, param_env,
+        );
+        let substituted = value.subst(self, param_substs);
+        self.try_normalize_erasing_regions(param_env, substituted)
+    }
 }
 
 struct NormalizeAfterErasingRegionsFolder<'tcx> {