Skip to content

Commit fd74026

Browse files
committed
Add fix
This also explicitly checks that the types are `bool`. `try_eval_bool` also appears to just succeed for `u8`, so this ensures that it actually is a bool before casting.
1 parent c0a811a commit fd74026

6 files changed

+179
-10
lines changed

src/librustc_mir/transform/match_branches.rs

+7-9
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,13 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
4848
(
4949
StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
5050
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
51-
) if lhs_f == lhs_s => {
52-
if let Some(f_c) = f_c.literal.try_eval_bool(tcx, param_env) {
53-
// This should also be a bool because it's writing to the same place
54-
let s_c = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
55-
if f_c != s_c {
56-
// have to check this here because f_c & s_c might have
57-
// different spans.
58-
continue;
59-
}
51+
) if lhs_f == lhs_s && f_c.literal.ty.is_bool() && s_c.literal.ty.is_bool() => {
52+
let f_c = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
53+
let s_c = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
54+
if f_c != s_c {
55+
// have to check this here because f_c & s_c might have
56+
// different spans.
57+
continue;
6058
}
6159
continue 'outer;
6260
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
- // MIR for `exhaustive_match` before MatchBranchSimplification
2+
+ // MIR for `exhaustive_match` after MatchBranchSimplification
3+
4+
fn exhaustive_match(_1: E) -> u8 {
5+
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
6+
let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
7+
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
8+
9+
bb0: {
10+
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
11+
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
12+
}
13+
14+
bb1: {
15+
_0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
16+
// ty::Const
17+
// + ty: u8
18+
// + val: Value(Scalar(0x01))
19+
// mir::Constant
20+
// + span: $DIR/matches_u8.rs:14:17: 14:18
21+
// + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
22+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
23+
}
24+
25+
bb2: {
26+
_0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
27+
// ty::Const
28+
// + ty: u8
29+
// + val: Value(Scalar(0x00))
30+
// mir::Constant
31+
// + span: $DIR/matches_u8.rs:13:17: 13:18
32+
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
33+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
34+
}
35+
36+
bb3: {
37+
return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
- // MIR for `exhaustive_match` before MatchBranchSimplification
2+
+ // MIR for `exhaustive_match` after MatchBranchSimplification
3+
4+
fn exhaustive_match(_1: E) -> u8 {
5+
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
6+
let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
7+
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13
8+
9+
bb0: {
10+
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
11+
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
12+
}
13+
14+
bb1: {
15+
_0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
16+
// ty::Const
17+
// + ty: u8
18+
// + val: Value(Scalar(0x01))
19+
// mir::Constant
20+
// + span: $DIR/matches_u8.rs:14:17: 14:18
21+
// + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
22+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
23+
}
24+
25+
bb2: {
26+
_0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
27+
// ty::Const
28+
// + ty: u8
29+
// + val: Value(Scalar(0x00))
30+
// mir::Constant
31+
// + span: $DIR/matches_u8.rs:13:17: 13:18
32+
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
33+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
34+
}
35+
36+
bb3: {
37+
return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
2+
+ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
3+
4+
fn exhaustive_match_i8(_1: E) -> i8 {
5+
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
6+
let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
7+
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
8+
9+
bb0: {
10+
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
11+
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
12+
}
13+
14+
bb1: {
15+
_0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
16+
// ty::Const
17+
// + ty: i8
18+
// + val: Value(Scalar(0x01))
19+
// mir::Constant
20+
// + span: $DIR/matches_u8.rs:22:17: 22:18
21+
// + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
22+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
23+
}
24+
25+
bb2: {
26+
_0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
27+
// ty::Const
28+
// + ty: i8
29+
// + val: Value(Scalar(0x00))
30+
// mir::Constant
31+
// + span: $DIR/matches_u8.rs:21:17: 21:18
32+
// + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
33+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
34+
}
35+
36+
bb3: {
37+
return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
38+
}
39+
}
40+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
2+
+ // MIR for `exhaustive_match_i8` after MatchBranchSimplification
3+
4+
fn exhaustive_match_i8(_1: E) -> i8 {
5+
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
6+
let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
7+
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13
8+
9+
bb0: {
10+
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
11+
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
12+
}
13+
14+
bb1: {
15+
_0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
16+
// ty::Const
17+
// + ty: i8
18+
// + val: Value(Scalar(0x01))
19+
// mir::Constant
20+
// + span: $DIR/matches_u8.rs:22:17: 22:18
21+
// + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
22+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
23+
}
24+
25+
bb2: {
26+
_0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
27+
// ty::Const
28+
// + ty: i8
29+
// + val: Value(Scalar(0x00))
30+
// mir::Constant
31+
// + span: $DIR/matches_u8.rs:21:17: 21:18
32+
// + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
33+
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
34+
}
35+
36+
bb3: {
37+
return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
38+
}
39+
}
40+

src/test/mir-opt/matches_u8.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// EMIT_MIR_FOR_EACH_BIT_WIDTH
22
// EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
3+
// EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff
34

45
pub enum E {
56
A,
67
B,
78
}
89

9-
// This only breaks on u8's, but probably still have to test i8.
1010
#[no_mangle]
1111
pub fn exhaustive_match(e: E) -> u8 {
1212
match e {
@@ -15,7 +15,18 @@ pub fn exhaustive_match(e: E) -> u8 {
1515
}
1616
}
1717

18+
#[no_mangle]
19+
pub fn exhaustive_match_i8(e: E) -> i8 {
20+
match e {
21+
E::A => 0,
22+
E::B => 1,
23+
}
24+
}
25+
1826
fn main() {
1927
assert_eq!(exhaustive_match(E::A), 0);
2028
assert_eq!(exhaustive_match(E::B), 1);
29+
30+
assert_eq!(exhaustive_match_i8(E::A), 0);
31+
assert_eq!(exhaustive_match_i8(E::B), 1);
2132
}

0 commit comments

Comments
 (0)