From c0a811a24ee926431f6e8fea6984430138a5fee0 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 13 Aug 2020 23:46:27 +0000 Subject: [PATCH 1/2] Add regression test for matching on u8 --- src/test/mir-opt/matches_u8.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/mir-opt/matches_u8.rs diff --git a/src/test/mir-opt/matches_u8.rs b/src/test/mir-opt/matches_u8.rs new file mode 100644 index 0000000000000..15de01fa963e0 --- /dev/null +++ b/src/test/mir-opt/matches_u8.rs @@ -0,0 +1,21 @@ +// EMIT_MIR_FOR_EACH_BIT_WIDTH +// EMIT_MIR matches_u8.exhaustive_match.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 { + E::A => 0, + E::B => 1, + } +} + +fn main() { + assert_eq!(exhaustive_match(E::A), 0); + assert_eq!(exhaustive_match(E::B), 1); +} From fd740266de93f89195eee78a0feaa770bf90a47e Mon Sep 17 00:00:00 2001 From: kadmin Date: Fri, 14 Aug 2020 00:11:36 +0000 Subject: [PATCH 2/2] 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. --- src/librustc_mir/transform/match_branches.rs | 16 ++++---- ...match.MatchBranchSimplification.diff.32bit | 40 +++++++++++++++++++ ...match.MatchBranchSimplification.diff.64bit | 40 +++++++++++++++++++ ...ch_i8.MatchBranchSimplification.diff.32bit | 40 +++++++++++++++++++ ...ch_i8.MatchBranchSimplification.diff.64bit | 40 +++++++++++++++++++ src/test/mir-opt/matches_u8.rs | 13 +++++- 6 files changed, 179 insertions(+), 10 deletions(-) create mode 100644 src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit create mode 100644 src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit create mode 100644 src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit create mode 100644 src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit diff --git a/src/librustc_mir/transform/match_branches.rs b/src/librustc_mir/transform/match_branches.rs index 74da6d5e629b3..67021ae512b65 100644 --- a/src/librustc_mir/transform/match_branches.rs +++ b/src/librustc_mir/transform/match_branches.rs @@ -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; } diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit new file mode 100644 index 0000000000000..c41bd999dc9fc --- /dev/null +++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.32bit @@ -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 + } + } + diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit new file mode 100644 index 0000000000000..c41bd999dc9fc --- /dev/null +++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.diff.64bit @@ -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 + } + } + diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit new file mode 100644 index 0000000000000..2c4bbc8095e9a --- /dev/null +++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.32bit @@ -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 + } + } + diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit new file mode 100644 index 0000000000000..2c4bbc8095e9a --- /dev/null +++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.diff.64bit @@ -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 + } + } + diff --git a/src/test/mir-opt/matches_u8.rs b/src/test/mir-opt/matches_u8.rs index 15de01fa963e0..78373be48b685 100644 --- a/src/test/mir-opt/matches_u8.rs +++ b/src/test/mir-opt/matches_u8.rs @@ -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 { @@ -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); }