提交 0be80f29 编写于 作者: W Wesley Wiser

[const-prop] Fix ICE calculating enum discriminant

Fixes #66787
上级 4007d4ef
......@@ -1038,13 +1038,16 @@ pub fn write_discriminant_index(
variant_index: VariantIdx,
dest: PlaceTy<'tcx, M::PointerTag>,
) -> InterpResult<'tcx> {
let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into();
// Layout computation excludes uninhabited variants from consideration
// therefore there's no way to represent those variants in the given layout.
if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
throw_ub!(Unreachable);
}
match dest.layout.variants {
layout::Variants::Single { index } => {
if index != variant_index {
throw_ub!(InvalidDiscriminant(variant_scalar));
}
assert_eq!(index, variant_index);
}
layout::Variants::Multiple {
discr_kind: layout::DiscriminantKind::Tag,
......@@ -1052,9 +1055,9 @@ pub fn write_discriminant_index(
discr_index,
..
} => {
if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) {
throw_ub!(InvalidDiscriminant(variant_scalar));
}
// No need to validate that the discriminant here because the
// `TyLayout::for_variant()` call earlier already checks the variant is valid.
let discr_val =
dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
......@@ -1077,9 +1080,9 @@ pub fn write_discriminant_index(
discr_index,
..
} => {
if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() {
throw_ub!(InvalidDiscriminant(variant_scalar));
}
// No need to validate that the discriminant here because the
// `TyLayout::for_variant()` call earlier already checks the variant is valid.
if variant_index != dataful_variant {
let variants_start = niche_variants.start().as_u32();
let variant_index_relative = variant_index.as_u32()
......
// build-pass
// compile-flags: --crate-type lib
// Regression test for ICE which occurred when const propagating an enum with three variants
// one of which is uninhabited.
pub enum ApiError {}
#[allow(dead_code)]
pub struct TokioError {
b: bool,
}
pub enum Error {
Api {
source: ApiError,
},
Ethereum,
Tokio {
source: TokioError,
},
}
struct Api;
impl IntoError<Error> for Api
{
type Source = ApiError;
fn into_error(self, error: Self::Source) -> Error {
Error::Api {
source: (|v| v)(error),
}
}
}
pub trait IntoError<E>
{
/// The underlying error
type Source;
/// Combine the information to produce the error
fn into_error(self, source: Self::Source) -> E;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册