Skip to content

Commit f2d4ffe

Browse files
authored
Rollup merge of #94093 - tmiasko:pp-no-variants, r=oli-obk
Fix pretty printing of enums without variants 92d20c4 removed no-variants special case from `try_destructure_const` with expectation that this case would be handled gracefully when `read_discriminant` returns an error. Alas in that case `read_discriminant` succeeds while returning a non-existing variant, so the special case is still necessary. Fixes #94073. r? ````@oli-obk````
2 parents 9e9cc66 + c2da477 commit f2d4ffe

File tree

3 files changed

+75
-65
lines changed

3 files changed

+75
-65
lines changed

compiler/rustc_const_eval/src/const_eval/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ pub(crate) fn try_destructure_const<'tcx>(
147147
// We go to `usize` as we cannot allocate anything bigger anyway.
148148
let (field_count, variant, down) = match val.ty().kind() {
149149
ty::Array(_, len) => (usize::try_from(len.eval_usize(tcx, param_env)).unwrap(), None, op),
150+
// Checks if we have any variants, to avoid downcasting to a non-existing variant (when
151+
// there are no variants `read_discriminant` successfully returns a non-existing variant
152+
// index).
153+
ty::Adt(def, _) if def.variants.is_empty() => throw_ub!(Unreachable),
150154
ty::Adt(def, _) => {
151155
let variant = ecx.read_discriminant(&op)?.1;
152156
let down = ecx.operand_downcast(&op, variant)?;

src/test/mir-opt/const_prop/invalid_constant.main.ConstProp.diff

+45-50
Original file line numberDiff line numberDiff line change
@@ -2,68 +2,63 @@
22
+ // MIR for `main` after ConstProp
33

44
fn main() -> () {
5-
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:15:11: 15:11
6-
let _1: std::option::Option<()>; // in scope 0 at $DIR/invalid_constant.rs:16:5: 16:12
7-
let mut _2: std::option::Option<std::option::Option<()>>; // in scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
8-
let _3: main::Union; // in scope 0 at $DIR/invalid_constant.rs:22:9: 22:22
5+
let mut _0: (); // return place in scope 0 at $DIR/invalid_constant.rs:13:11: 13:11
6+
let _1: main::InvalidChar; // in scope 0 at $DIR/invalid_constant.rs:19:9: 19:22
7+
let mut _3: main::InvalidTag; // in scope 0 at $DIR/invalid_constant.rs:26:25: 26:46
8+
let mut _5: main::NoVariants; // in scope 0 at $DIR/invalid_constant.rs:33:35: 33:56
99
scope 1 {
10-
debug _invalid_char => _3; // in scope 1 at $DIR/invalid_constant.rs:22:9: 22:22
11-
}
12-
scope 2 (inlined f) { // at $DIR/invalid_constant.rs:16:5: 16:12
13-
debug x => _2; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
14-
let mut _4: isize; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
15-
let _5: std::option::Option<()>; // in scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
16-
scope 3 {
17-
debug y => _5; // in scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
10+
debug _invalid_char => _1; // in scope 1 at $DIR/invalid_constant.rs:19:9: 19:22
11+
let _2: [main::InvalidTag; 1]; // in scope 1 at $DIR/invalid_constant.rs:26:9: 26:21
12+
scope 2 {
13+
debug _invalid_tag => _2; // in scope 2 at $DIR/invalid_constant.rs:26:9: 26:21
14+
let _4: [main::NoVariants; 1]; // in scope 2 at $DIR/invalid_constant.rs:33:9: 33:31
15+
scope 3 {
16+
debug _enum_without_variants => _4; // in scope 3 at $DIR/invalid_constant.rs:33:9: 33:31
17+
}
1818
}
1919
}
2020

2121
bb0: {
22-
discriminant(_2) = 0; // scope 0 at $DIR/invalid_constant.rs:16:7: 16:11
23-
- _4 = discriminant(_2); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
24-
- switchInt(move _4) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
25-
+ _4 = const 0_isize; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
26-
+ switchInt(const 0_isize) -> [0_isize: bb3, otherwise: bb2]; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
27-
}
28-
29-
bb1: {
30-
- _3 = const { Union { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
31-
+ _3 = const main::Union { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:22:25: 22:58
22+
StorageLive(_1); // scope 0 at $DIR/invalid_constant.rs:19:9: 19:22
23+
- _1 = const { InvalidChar { int: 0x110001 } }; // scope 0 at $DIR/invalid_constant.rs:19:25: 19:64
24+
+ _1 = const InvalidChar { int: 1114113_u32, chr: {transmute(0x00110001): char} }; // scope 0 at $DIR/invalid_constant.rs:19:25: 19:64
3225
// ty::Const
33-
// + ty: main::Union
34-
- // + val: Unevaluated(main::{constant#0}, [main::Union], None)
26+
// + ty: main::InvalidChar
27+
- // + val: Unevaluated(main::{constant#0}, [main::InvalidChar], None)
3528
+ // + val: Value(Scalar(0x00110001))
3629
// mir::Constant
37-
// + span: $DIR/invalid_constant.rs:22:25: 22:58
38-
- // + literal: Const { ty: main::Union, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:8 ~ invalid_constant[726d]::main::{constant#0}), const_param_did: None }, substs: [main::Union], promoted: None }) }
39-
+ // + literal: Const { ty: main::Union, val: Value(Scalar(0x00110001)) }
40-
nop; // scope 0 at $DIR/invalid_constant.rs:15:11: 23:2
41-
return; // scope 0 at $DIR/invalid_constant.rs:23:2: 23:2
42-
}
43-
44-
bb2: {
45-
- _5 = ((_2 as Some).0: std::option::Option<()>); // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
46-
- _1 = _5; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
47-
+ _5 = const Scalar(0x02): Option::<()>; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
30+
// + span: $DIR/invalid_constant.rs:19:25: 19:64
31+
- // + literal: Const { ty: main::InvalidChar, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ invalid_constant[726d]::main::{constant#0}), const_param_did: None }, substs: [main::InvalidChar], promoted: None }) }
32+
+ // + literal: Const { ty: main::InvalidChar, val: Value(Scalar(0x00110001)) }
33+
StorageLive(_2); // scope 1 at $DIR/invalid_constant.rs:26:9: 26:21
34+
StorageLive(_3); // scope 1 at $DIR/invalid_constant.rs:26:25: 26:46
35+
(_3.0: u32) = const 4_u32; // scope 1 at $DIR/invalid_constant.rs:26:25: 26:46
36+
- _2 = [move _3]; // scope 1 at $DIR/invalid_constant.rs:26:24: 26:47
37+
+ _2 = [const InvalidTag { int: 4_u32, e: Scalar(0x00000004): E }]; // scope 1 at $DIR/invalid_constant.rs:26:24: 26:47
4838
+ // ty::Const
49-
+ // + ty: std::option::Option<()>
50-
+ // + val: Value(Scalar(0x02))
39+
+ // + ty: main::InvalidTag
40+
+ // + val: Value(Scalar(0x00000004))
5141
+ // mir::Constant
52-
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
53-
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
54-
+ _1 = const Scalar(0x02): Option::<()>; // scope 3 at $DIR/invalid_constant.rs:16:5: 16:12
42+
+ // + span: $DIR/invalid_constant.rs:26:24: 26:47
43+
+ // + literal: Const { ty: main::InvalidTag, val: Value(Scalar(0x00000004)) }
44+
StorageDead(_3); // scope 1 at $DIR/invalid_constant.rs:26:46: 26:47
45+
StorageLive(_4); // scope 2 at $DIR/invalid_constant.rs:33:9: 33:31
46+
StorageLive(_5); // scope 2 at $DIR/invalid_constant.rs:33:35: 33:56
47+
(_5.0: u32) = const 0_u32; // scope 2 at $DIR/invalid_constant.rs:33:35: 33:56
48+
- _4 = [move _5]; // scope 2 at $DIR/invalid_constant.rs:33:34: 33:57
49+
+ _4 = [const NoVariants { int: 0_u32, empty: Scalar(<ZST>): Empty }]; // scope 2 at $DIR/invalid_constant.rs:33:34: 33:57
5550
+ // ty::Const
56-
+ // + ty: std::option::Option<()>
57-
+ // + val: Value(Scalar(0x02))
51+
+ // + ty: main::NoVariants
52+
+ // + val: Value(Scalar(0x00000000))
5853
+ // mir::Constant
59-
+ // + span: $DIR/invalid_constant.rs:16:5: 16:12
60-
+ // + literal: Const { ty: std::option::Option<()>, val: Value(Scalar(0x02)) }
61-
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:10:20: 10:21
62-
}
63-
64-
bb3: {
65-
discriminant(_1) = 0; // scope 2 at $DIR/invalid_constant.rs:16:5: 16:12
66-
goto -> bb1; // scope 0 at $DIR/invalid_constant.rs:9:17: 9:21
54+
+ // + span: $DIR/invalid_constant.rs:33:34: 33:57
55+
+ // + literal: Const { ty: main::NoVariants, val: Value(Scalar(0x00000000)) }
56+
StorageDead(_5); // scope 2 at $DIR/invalid_constant.rs:33:56: 33:57
57+
nop; // scope 0 at $DIR/invalid_constant.rs:13:11: 34:2
58+
StorageDead(_4); // scope 2 at $DIR/invalid_constant.rs:34:1: 34:2
59+
StorageDead(_2); // scope 1 at $DIR/invalid_constant.rs:34:1: 34:2
60+
StorageDead(_1); // scope 0 at $DIR/invalid_constant.rs:34:1: 34:2
61+
return; // scope 0 at $DIR/invalid_constant.rs:34:2: 34:2
6762
}
6863
}
6964

Original file line numberDiff line numberDiff line change
@@ -1,23 +1,34 @@
1-
// Verify that we can pretty print invalid constant introduced
2-
// by constant propagation. Regression test for issue #93688.
3-
//
4-
// compile-flags: -Copt-level=0 -Zinline-mir
1+
// Verify that we can pretty print invalid constants.
2+
53
#![feature(inline_const)]
6-
#[inline(always)]
7-
pub fn f(x: Option<Option<()>>) -> Option<()> {
8-
match x {
9-
None => None,
10-
Some(y) => y,
11-
}
12-
}
4+
5+
#[derive(Copy, Clone)]
6+
#[repr(u32)]
7+
enum E { A, B, C }
8+
9+
#[derive(Copy, Clone)]
10+
enum Empty {}
1311

1412
// EMIT_MIR invalid_constant.main.ConstProp.diff
1513
fn main() {
16-
f(None);
17-
18-
union Union {
14+
// An invalid char.
15+
union InvalidChar {
1916
int: u32,
2017
chr: char,
2118
}
22-
let _invalid_char = const { Union { int: 0x110001 } };
19+
let _invalid_char = const { InvalidChar { int: 0x110001 } };
20+
21+
// An enum with an invalid tag. Regression test for #93688.
22+
union InvalidTag {
23+
int: u32,
24+
e: E,
25+
}
26+
let _invalid_tag = [InvalidTag { int: 4 }];
27+
28+
// An enum without variants. Regression test for #94073.
29+
union NoVariants {
30+
int: u32,
31+
empty: Empty,
32+
}
33+
let _enum_without_variants = [NoVariants { int: 0 }];
2334
}

0 commit comments

Comments
 (0)