mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Rollup merge of #91551 - b-naber:const-eval-normalization-ice, r=oli-obk
Allow for failure of subst_normalize_erasing_regions in const_eval Fixes https://github.com/rust-lang/rust/issues/72845 Using associated types that cannot be normalized previously resulted in an ICE. We now allow for normalization failure and return a "TooGeneric" error in that case. r? ```@RalfJung``` maybe?
This commit is contained in:
commit
317f750ff7
@ -7,6 +7,7 @@ use rustc_hir::{self as hir, def_id::DefId, definitions::DefPathData};
|
|||||||
use rustc_index::vec::IndexVec;
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_middle::mir;
|
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::layout::{self, LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
self, query::TyCtxtAt, subst::SubstsRef, ParamEnv, Ty, TyCtxt, TypeFoldable,
|
||||||
@ -14,7 +15,7 @@ use rustc_middle::ty::{
|
|||||||
use rustc_mir_dataflow::storage::AlwaysLiveLocals;
|
use rustc_mir_dataflow::storage::AlwaysLiveLocals;
|
||||||
use rustc_query_system::ich::StableHashingContext;
|
use rustc_query_system::ich::StableHashingContext;
|
||||||
use rustc_session::Limit;
|
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 rustc_target::abi::{Align, HasDataLayout, Size, TargetDataLayout};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -508,7 +509,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
|
pub(super) fn subst_from_current_frame_and_normalize_erasing_regions<T: TypeFoldable<'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
value: T,
|
value: T,
|
||||||
) -> T {
|
) -> Result<T, InterpError<'tcx>> {
|
||||||
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
self.subst_from_frame_and_normalize_erasing_regions(self.frame(), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -518,8 +519,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
&self,
|
&self,
|
||||||
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
frame: &Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>,
|
||||||
value: T,
|
value: T,
|
||||||
) -> T {
|
) -> Result<T, InterpError<'tcx>> {
|
||||||
frame.instance.subst_mir_and_normalize_erasing_regions(*self.tcx, self.param_env, value)
|
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).
|
/// The `substs` are assumed to already be in our interpreter "universe" (param_env).
|
||||||
@ -554,7 +565,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
let layout = from_known_layout(self.tcx, self.param_env, layout, || {
|
||||||
let local_ty = frame.body.local_decls[local].ty;
|
let local_ty = frame.body.local_decls[local].ty;
|
||||||
let 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)
|
self.layout_of(local_ty)
|
||||||
})?;
|
})?;
|
||||||
if let Some(state) = frame.locals.get(local) {
|
if let Some(state) = frame.locals.get(local) {
|
||||||
@ -702,7 +713,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
for const_ in &body.required_consts {
|
for const_ in &body.required_consts {
|
||||||
let span = const_.span;
|
let span = const_.span;
|
||||||
let const_ =
|
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| {
|
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.
|
// If there was an error, set the span of the current frame to this constant.
|
||||||
// Avoiding doing this when evaluation succeeds.
|
// Avoiding doing this when evaluation succeeds.
|
||||||
|
@ -512,7 +512,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
self.param_env,
|
self.param_env,
|
||||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||||
))?,
|
)?)?,
|
||||||
op.layout,
|
op.layout,
|
||||||
));
|
));
|
||||||
Ok(op)
|
Ok(op)
|
||||||
@ -534,7 +534,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
Constant(ref constant) => {
|
Constant(ref constant) => {
|
||||||
let val =
|
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:
|
// This can still fail:
|
||||||
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
// * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all
|
||||||
// checked yet.
|
// checked yet.
|
||||||
|
@ -643,7 +643,7 @@ where
|
|||||||
self.param_env,
|
self.param_env,
|
||||||
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
|
||||||
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
place.ty(&self.frame().body.local_decls, *self.tcx).ty
|
||||||
))?,
|
)?)?,
|
||||||
place_ty.layout,
|
place_ty.layout,
|
||||||
));
|
));
|
||||||
Ok(place_ty)
|
Ok(place_ty)
|
||||||
|
@ -276,7 +276,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NullaryOp(null_op, 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)?;
|
let layout = self.layout_of(ty)?;
|
||||||
if layout.is_unsized() {
|
if layout.is_unsized() {
|
||||||
// FIXME: This should be a span_bug (#80742)
|
// FIXME: This should be a span_bug (#80742)
|
||||||
@ -302,7 +302,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
|||||||
|
|
||||||
Cast(cast_kind, ref operand, cast_ty) => {
|
Cast(cast_kind, ref operand, cast_ty) => {
|
||||||
let src = self.eval_operand(operand, None)?;
|
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)?;
|
self.cast(&src, cast_kind, cast_ty, &dest)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ use rustc_hir::def::Namespace;
|
|||||||
use rustc_hir::def_id::{CrateNum, DefId};
|
use rustc_hir::def_id::{CrateNum, DefId};
|
||||||
use rustc_hir::lang_items::LangItem;
|
use rustc_hir::lang_items::LangItem;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
|
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
@ -575,6 +576,23 @@ impl<'tcx> Instance<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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
|
/// 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`.
|
/// identity parameters if they are determined to be unused in `instance.def`.
|
||||||
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
|
pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
@ -115,6 +115,8 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
/// Monomorphizes a type from the AST by first applying the
|
/// Monomorphizes a type from the AST by first applying the
|
||||||
/// in-scope substitutions and then normalizing any associated
|
/// in-scope substitutions and then normalizing any associated
|
||||||
/// types.
|
/// 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>(
|
pub fn subst_and_normalize_erasing_regions<T>(
|
||||||
self,
|
self,
|
||||||
param_substs: SubstsRef<'tcx>,
|
param_substs: SubstsRef<'tcx>,
|
||||||
@ -134,6 +136,30 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
let substituted = value.subst(self, param_substs);
|
let substituted = value.subst(self, param_substs);
|
||||||
self.normalize_erasing_regions(param_env, substituted)
|
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> {
|
struct NormalizeAfterErasingRegionsFolder<'tcx> {
|
||||||
|
49
src/test/ui/const-generics/issues/issue-72845.rs
Normal file
49
src/test/ui/const-generics/issues/issue-72845.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#![feature(generic_const_exprs)]
|
||||||
|
#![feature(specialization)]
|
||||||
|
#![allow(incomplete_features)]
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
trait Depth {
|
||||||
|
const C: usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Type {
|
||||||
|
type AT: Depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
enum Predicate<const B: bool> {}
|
||||||
|
|
||||||
|
trait Satisfied {}
|
||||||
|
|
||||||
|
impl Satisfied for Predicate<true> {}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
trait Spec1 {}
|
||||||
|
|
||||||
|
impl<T: Type> Spec1 for T where Predicate<{T::AT::C > 0}>: Satisfied {}
|
||||||
|
|
||||||
|
trait Spec2 {}
|
||||||
|
|
||||||
|
//impl<T: Type > Spec2 for T where Predicate<{T::AT::C > 1}>: Satisfied {}
|
||||||
|
impl<T: Type > Spec2 for T where Predicate<true>: Satisfied {}
|
||||||
|
|
||||||
|
//--------------------------------------------------
|
||||||
|
|
||||||
|
trait Foo {
|
||||||
|
fn Bar();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Spec1> Foo for T {
|
||||||
|
default fn Bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Spec2> Foo for T {
|
||||||
|
//~^ ERROR conflicting implementations of trait
|
||||||
|
fn Bar() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
12
src/test/ui/const-generics/issues/issue-72845.stderr
Normal file
12
src/test/ui/const-generics/issues/issue-72845.stderr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
error[E0119]: conflicting implementations of trait `Foo`
|
||||||
|
--> $DIR/issue-72845.rs:44:1
|
||||||
|
|
|
||||||
|
LL | impl<T: Spec1> Foo for T {
|
||||||
|
| ------------------------ first implementation here
|
||||||
|
...
|
||||||
|
LL | impl<T: Spec2> Foo for T {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
@ -20,7 +20,7 @@ error[E0080]: evaluation of constant value failed
|
|||||||
LL | let x: &'static i32 = &X;
|
LL | let x: &'static i32 = &X;
|
||||||
| ^ referenced constant has errors
|
| ^ referenced constant has errors
|
||||||
query stack during panic:
|
query stack during panic:
|
||||||
#0 [normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
|
#0 [try_normalize_mir_const_after_erasing_regions] normalizing `main::promoted[1]`
|
||||||
#1 [optimized_mir] optimizing MIR for `main`
|
#1 [optimized_mir] optimizing MIR for `main`
|
||||||
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
#2 [collect_and_partition_mono_items] collect_and_partition_mono_items
|
||||||
end of query stack
|
end of query stack
|
||||||
|
Loading…
Reference in New Issue
Block a user