Skip to content

Commit

Permalink
Add fix
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
JulianKnodt committed Aug 14, 2020
1 parent c0a811a commit fd74026
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 10 deletions.
16 changes: 7 additions & 9 deletions src/librustc_mir/transform/match_branches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,13 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
(
StatementKind::Assign(box (lhs_f, Rvalue::Use(Operand::Constant(f_c)))),
StatementKind::Assign(box (lhs_s, Rvalue::Use(Operand::Constant(s_c)))),
) if lhs_f == lhs_s => {
if let Some(f_c) = f_c.literal.try_eval_bool(tcx, param_env) {
// This should also be a bool because it's writing to the same place
let s_c = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
if f_c != s_c {
// have to check this here because f_c & s_c might have
// different spans.
continue;
}
) if lhs_f == lhs_s && f_c.literal.ty.is_bool() && s_c.literal.ty.is_bool() => {
let f_c = f_c.literal.try_eval_bool(tcx, param_env).unwrap();
let s_c = s_c.literal.try_eval_bool(tcx, param_env).unwrap();
if f_c != s_c {
// have to check this here because f_c & s_c might have
// different spans.
continue;
}
continue 'outer;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- // MIR for `exhaustive_match` before MatchBranchSimplification
+ // MIR for `exhaustive_match` after MatchBranchSimplification

fn exhaustive_match(_1: E) -> u8 {
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
}

bb1: {
_0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
// ty::Const
// + ty: u8
// + val: Value(Scalar(0x01))
// mir::Constant
// + span: $DIR/matches_u8.rs:14:17: 14:18
// + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
}

bb2: {
_0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
// ty::Const
// + ty: u8
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $DIR/matches_u8.rs:13:17: 13:18
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
}

bb3: {
return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- // MIR for `exhaustive_match` before MatchBranchSimplification
+ // MIR for `exhaustive_match` after MatchBranchSimplification

fn exhaustive_match(_1: E) -> u8 {
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:11:25: 11:26
let mut _0: u8; // return place in scope 0 at $DIR/matches_u8.rs:11:34: 11:36
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:13:9: 13:13

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:13:9: 13:13
}

bb1: {
_0 = const 1_u8; // scope 0 at $DIR/matches_u8.rs:14:17: 14:18
// ty::Const
// + ty: u8
// + val: Value(Scalar(0x01))
// mir::Constant
// + span: $DIR/matches_u8.rs:14:17: 14:18
// + literal: Const { ty: u8, val: Value(Scalar(0x01)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
}

bb2: {
_0 = const 0_u8; // scope 0 at $DIR/matches_u8.rs:13:17: 13:18
// ty::Const
// + ty: u8
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $DIR/matches_u8.rs:13:17: 13:18
// + literal: Const { ty: u8, val: Value(Scalar(0x00)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:12:5: 15:6
}

bb3: {
return; // scope 0 at $DIR/matches_u8.rs:16:2: 16:2
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
+ // MIR for `exhaustive_match_i8` after MatchBranchSimplification

fn exhaustive_match_i8(_1: E) -> i8 {
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
}

bb1: {
_0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
// ty::Const
// + ty: i8
// + val: Value(Scalar(0x01))
// mir::Constant
// + span: $DIR/matches_u8.rs:22:17: 22:18
// + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
}

bb2: {
_0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
// ty::Const
// + ty: i8
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $DIR/matches_u8.rs:21:17: 21:18
// + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
}

bb3: {
return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
- // MIR for `exhaustive_match_i8` before MatchBranchSimplification
+ // MIR for `exhaustive_match_i8` after MatchBranchSimplification

fn exhaustive_match_i8(_1: E) -> i8 {
debug e => _1; // in scope 0 at $DIR/matches_u8.rs:19:28: 19:29
let mut _0: i8; // return place in scope 0 at $DIR/matches_u8.rs:19:37: 19:39
let mut _2: isize; // in scope 0 at $DIR/matches_u8.rs:21:9: 21:13

bb0: {
_2 = discriminant(_1); // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:21:9: 21:13
}

bb1: {
_0 = const 1_i8; // scope 0 at $DIR/matches_u8.rs:22:17: 22:18
// ty::Const
// + ty: i8
// + val: Value(Scalar(0x01))
// mir::Constant
// + span: $DIR/matches_u8.rs:22:17: 22:18
// + literal: Const { ty: i8, val: Value(Scalar(0x01)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
}

bb2: {
_0 = const 0_i8; // scope 0 at $DIR/matches_u8.rs:21:17: 21:18
// ty::Const
// + ty: i8
// + val: Value(Scalar(0x00))
// mir::Constant
// + span: $DIR/matches_u8.rs:21:17: 21:18
// + literal: Const { ty: i8, val: Value(Scalar(0x00)) }
goto -> bb3; // scope 0 at $DIR/matches_u8.rs:20:5: 23:6
}

bb3: {
return; // scope 0 at $DIR/matches_u8.rs:24:2: 24:2
}
}

13 changes: 12 additions & 1 deletion src/test/mir-opt/matches_u8.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR matches_u8.exhaustive_match.MatchBranchSimplification.diff
// EMIT_MIR matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff

pub enum E {
A,
B,
}

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

#[no_mangle]
pub fn exhaustive_match_i8(e: E) -> i8 {
match e {
E::A => 0,
E::B => 1,
}
}

fn main() {
assert_eq!(exhaustive_match(E::A), 0);
assert_eq!(exhaustive_match(E::B), 1);

assert_eq!(exhaustive_match_i8(E::A), 0);
assert_eq!(exhaustive_match_i8(E::B), 1);
}

0 comments on commit fd74026

Please sign in to comment.