From 6bf3cbe39e09f4d9187a0b1f6a7bd45101f7aad8 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Mon, 28 Jul 2025 00:01:28 +0300 Subject: [PATCH] In rustc_pattern_analysis, put `true` witnesses before `false` witnesses In rustc it doesn't really matter what the order of the witnesses is, but I'm planning to use the witnesses for implementing the "add missing match arms" assist in rust-analyzer, and there `true` before `false` is the natural order (like `Some` before `None`), and also what the current assist does. The current order doesn't seem to be intentional; the code was created when bool ctors became their own thing, not just int ctors, but for integer, 0 before 1 is indeed the natural order. --- compiler/rustc_pattern_analysis/src/constructor.rs | 10 +++++----- .../rustc_pattern_analysis/tests/exhaustiveness.rs | 3 +++ .../deref-patterns/usefulness/non-exhaustive.rs | 2 +- .../deref-patterns/usefulness/non-exhaustive.stderr | 6 +++--- tests/ui/pattern/usefulness/unions.rs | 2 +- tests/ui/pattern/usefulness/unions.stderr | 4 ++-- 6 files changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 9a9e0db964c9..12f653a13371 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -1130,16 +1130,16 @@ impl ConstructorSet { seen_false = true; } } - if seen_false { - present.push(Bool(false)); - } else { - missing.push(Bool(false)); - } if seen_true { present.push(Bool(true)); } else { missing.push(Bool(true)); } + if seen_false { + present.push(Bool(false)); + } else { + missing.push(Bool(false)); + } } ConstructorSet::Integers { range_1, range_2 } => { let seen_ranges: Vec<_> = diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs index 14ca0d057f06..4ad64f81560a 100644 --- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs +++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs @@ -176,6 +176,9 @@ fn test_witnesses() { ), vec!["Enum::Variant1(_)", "Enum::Variant2(_)", "_"], ); + + // Assert we put `true` before `false`. + assert_witnesses(AllOfThem, Ty::Bool, Vec::new(), vec!["true", "false"]); } #[test] diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs index 704cae8bdbc4..bab6308223e5 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs @@ -15,7 +15,7 @@ fn main() { } match Box::new((true, Box::new(false))) { - //~^ ERROR non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered + //~^ ERROR non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered (true, false) => {} (false, true) => {} } diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr index 55fa84bafde2..a1abd5f0e3f4 100644 --- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr +++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr @@ -28,11 +28,11 @@ LL ~ true => {}, LL + deref!(deref!(false)) => todo!() | -error[E0004]: non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered +error[E0004]: non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered --> $DIR/non-exhaustive.rs:17:11 | LL | match Box::new((true, Box::new(false))) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered | note: `Box<(bool, Box)>` defined here --> $SRC_DIR/alloc/src/boxed.rs:LL:COL @@ -40,7 +40,7 @@ note: `Box<(bool, Box)>` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms | LL ~ (false, true) => {}, -LL + deref!((false, deref!(false))) | deref!((true, deref!(true))) => todo!() +LL + deref!((true, deref!(true))) | deref!((false, deref!(false))) => todo!() | error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered diff --git a/tests/ui/pattern/usefulness/unions.rs b/tests/ui/pattern/usefulness/unions.rs index 80a7f36a09a2..3de79c6f8495 100644 --- a/tests/ui/pattern/usefulness/unions.rs +++ b/tests/ui/pattern/usefulness/unions.rs @@ -26,7 +26,7 @@ fn main() { } // Our approach can report duplicate witnesses sometimes. match (x, true) { - //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered + //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered (U8AsBool { b: true }, true) => {} (U8AsBool { b: false }, true) => {} (U8AsBool { n: 1.. }, true) => {} diff --git a/tests/ui/pattern/usefulness/unions.stderr b/tests/ui/pattern/usefulness/unions.stderr index 4b397dc25db8..98fb6a33ae41 100644 --- a/tests/ui/pattern/usefulness/unions.stderr +++ b/tests/ui/pattern/usefulness/unions.stderr @@ -16,11 +16,11 @@ LL ~ U8AsBool { n: 1.. } => {}, LL + U8AsBool { n: 0_u8 } | U8AsBool { b: false } => todo!() | -error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered +error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered --> $DIR/unions.rs:28:15 | LL | match (x, true) { - | ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered + | ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered | = note: the matched value is of type `(U8AsBool, bool)` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms