Skip to content

Commit ded9885

Browse files
authored
Rollup merge of #66960 - wesleywiser:fix_66787_take2, r=oli-obk,RalfJung
[const-prop] Fix ICE calculating enum discriminant Fixes #66787 Different approach than #66857 r? @oli-obk cc @RalfJung @eddyb
2 parents 69f1323 + 0be80f2 commit ded9885

File tree

2 files changed

+52
-10
lines changed

2 files changed

+52
-10
lines changed

src/librustc_mir/interpret/place.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -1065,23 +1065,26 @@ where
10651065
variant_index: VariantIdx,
10661066
dest: PlaceTy<'tcx, M::PointerTag>,
10671067
) -> InterpResult<'tcx> {
1068-
let variant_scalar = Scalar::from_u32(variant_index.as_u32()).into();
1068+
1069+
// Layout computation excludes uninhabited variants from consideration
1070+
// therefore there's no way to represent those variants in the given layout.
1071+
if dest.layout.for_variant(self, variant_index).abi.is_uninhabited() {
1072+
throw_ub!(Unreachable);
1073+
}
10691074

10701075
match dest.layout.variants {
10711076
layout::Variants::Single { index } => {
1072-
if index != variant_index {
1073-
throw_ub!(InvalidDiscriminant(variant_scalar));
1074-
}
1077+
assert_eq!(index, variant_index);
10751078
}
10761079
layout::Variants::Multiple {
10771080
discr_kind: layout::DiscriminantKind::Tag,
10781081
discr: ref discr_layout,
10791082
discr_index,
10801083
..
10811084
} => {
1082-
if !dest.layout.ty.variant_range(*self.tcx).unwrap().contains(&variant_index) {
1083-
throw_ub!(InvalidDiscriminant(variant_scalar));
1084-
}
1085+
// No need to validate that the discriminant here because the
1086+
// `TyLayout::for_variant()` call earlier already checks the variant is valid.
1087+
10851088
let discr_val =
10861089
dest.layout.ty.discriminant_for_variant(*self.tcx, variant_index).unwrap().val;
10871090

@@ -1104,9 +1107,9 @@ where
11041107
discr_index,
11051108
..
11061109
} => {
1107-
if !variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len() {
1108-
throw_ub!(InvalidDiscriminant(variant_scalar));
1109-
}
1110+
// No need to validate that the discriminant here because the
1111+
// `TyLayout::for_variant()` call earlier already checks the variant is valid.
1112+
11101113
if variant_index != dataful_variant {
11111114
let variants_start = niche_variants.start().as_u32();
11121115
let variant_index_relative = variant_index.as_u32()

src/test/ui/consts/issue-66787.rs

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// build-pass
2+
// compile-flags: --crate-type lib
3+
4+
// Regression test for ICE which occurred when const propagating an enum with three variants
5+
// one of which is uninhabited.
6+
7+
pub enum ApiError {}
8+
#[allow(dead_code)]
9+
pub struct TokioError {
10+
b: bool,
11+
}
12+
pub enum Error {
13+
Api {
14+
source: ApiError,
15+
},
16+
Ethereum,
17+
Tokio {
18+
source: TokioError,
19+
},
20+
}
21+
struct Api;
22+
impl IntoError<Error> for Api
23+
{
24+
type Source = ApiError;
25+
fn into_error(self, error: Self::Source) -> Error {
26+
Error::Api {
27+
source: (|v| v)(error),
28+
}
29+
}
30+
}
31+
32+
pub trait IntoError<E>
33+
{
34+
/// The underlying error
35+
type Source;
36+
37+
/// Combine the information to produce the error
38+
fn into_error(self, source: Self::Source) -> E;
39+
}

0 commit comments

Comments
 (0)