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,
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::{
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)
}
&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).
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) {
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.
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)
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.
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)
}
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)
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)?;
}
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;
}
}
+ #[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 {
/// 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>,
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> {