From b878ab6a270928fa45850183b82b13eac1e80c39 Mon Sep 17 00:00:00 2001 From: Nadrieril Date: Wed, 28 Feb 2024 22:26:20 +0100 Subject: [PATCH] Don't suggest an arm when suggesting a never pattern --- .../src/thir/pattern/check_match.rs | 14 +++++++-- compiler/rustc_pattern_analysis/src/pat.rs | 8 +++++ .../usefulness/empty-types.never_pats.stderr | 30 +++++++++---------- .../rfcs/rfc-0000-never_patterns/check.stderr | 4 +-- 4 files changed, 36 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 2685bae4d09c8..6a75573dfa071 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1024,6 +1024,14 @@ fn report_non_exhaustive_match<'p, 'tcx>( let mut suggestion = None; let sm = cx.tcx.sess.source_map(); + let suggested_arm = if witnesses.len() < 4 + && witnesses.iter().all(|p| p.is_never_pattern()) + && cx.tcx.features().never_patterns + { + pattern + } else { + format!("{pattern} => todo!()") + }; match arms { [] if sp.eq_ctxt(expr_span) => { // Get the span for the empty match body `{}`. @@ -1034,7 +1042,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( }; suggestion = Some(( sp.shrink_to_hi().with_hi(expr_span.hi()), - format!(" {{{indentation}{more}{pattern} => todo!(),{indentation}}}",), + format!(" {{{indentation}{more}{suggested_arm},{indentation}}}",), )); } [only] => { @@ -1060,7 +1068,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( }; suggestion = Some(( only.span.shrink_to_hi(), - format!("{comma}{pre_indentation}{pattern} => todo!()"), + format!("{comma}{pre_indentation}{suggested_arm}"), )); } [.., prev, last] => { @@ -1083,7 +1091,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( if let Some(spacing) = spacing { suggestion = Some(( last.span.shrink_to_hi(), - format!("{comma}{spacing}{pattern} => todo!()"), + format!("{comma}{spacing}{suggested_arm}"), )); } } diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs index 780a386fe6528..33d2fe89f43a4 100644 --- a/compiler/rustc_pattern_analysis/src/pat.rs +++ b/compiler/rustc_pattern_analysis/src/pat.rs @@ -321,6 +321,14 @@ impl WitnessPat { &self.ty } + pub fn is_never_pattern(&self) -> bool { + match self.ctor() { + Never => true, + Or => self.fields.iter().all(|p| p.is_never_pattern()), + _ => self.fields.iter().any(|p| p.is_never_pattern()), + } + } + pub fn iter_fields(&self) -> impl Iterator> { self.fields.iter() } diff --git a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr index 70d5b266bda35..0ff2472922e4a 100644 --- a/tests/ui/pattern/usefulness/empty-types.never_pats.stderr +++ b/tests/ui/pattern/usefulness/empty-types.never_pats.stderr @@ -111,7 +111,7 @@ note: `Result` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Ok(_) => {}, -LL + Err(!) => todo!() +LL + Err(!) | error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered @@ -192,7 +192,7 @@ note: `Result` 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 ~ match result_never { -LL + Ok(!) | Err(!) => todo!(), +LL + Ok(!) | Err(!), LL + } | @@ -210,8 +210,8 @@ note: `Result` defined here = note: the matched value is of type `Result` help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | -LL | Ok(_) => {}, Err(!) => todo!() - | +++++++++++++++++++ +LL | Ok(_) => {}, Err(!) + | ++++++++ error: unreachable pattern --> $DIR/empty-types.rs:140:13 @@ -240,7 +240,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered @@ -258,7 +258,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error: unreachable pattern @@ -343,7 +343,7 @@ note: `Result` 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 ~ match *x { -LL + Ok(!) | Err(!) => todo!(), +LL + Ok(!) | Err(!), LL ~ } | @@ -385,7 +385,7 @@ LL | match slice_never { help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ [] => {}, -LL + &[!, ..] => todo!() +LL + &[!, ..] | error[E0004]: non-exhaustive patterns: `&[]`, `&[!]` and `&[!, !]` not covered @@ -492,7 +492,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ &None => {}, -LL + &Some(!) => todo!() +LL + &Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered @@ -510,7 +510,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered @@ -528,7 +528,7 @@ note: `Result` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Ok(_) => {}, -LL + Err(!) => todo!() +LL + Err(!) | error[E0004]: non-exhaustive patterns: `Err(!)` not covered @@ -546,7 +546,7 @@ note: `Result` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Ok(_a) => {}, -LL + Err(!) => todo!() +LL + Err(!) | error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty @@ -599,7 +599,7 @@ LL | match ref_never { help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ &_a if false => {}, -LL + &! => todo!() +LL + &! | error[E0004]: non-exhaustive patterns: `Ok(!)` not covered @@ -617,7 +617,7 @@ note: `Result` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ Err(_) => {}, -LL + Ok(!) => todo!() +LL + Ok(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered @@ -635,7 +635,7 @@ note: `Option>` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error: aborting due to 49 previous errors; 1 warning emitted diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr index 82457f8b805ae..25f7343a8a801 100644 --- a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr +++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr @@ -46,7 +46,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error[E0004]: non-exhaustive patterns: `Some(!)` not covered @@ -64,7 +64,7 @@ note: `Option` defined here help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown | LL ~ None => {}, -LL + Some(!) => todo!() +LL + Some(!) | error: aborting due to 6 previous errors