From 05156f4e8b1c0e0ef6eedcf99cfedf142c8f56fb Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Mon, 8 Sep 2025 21:59:03 +0200 Subject: [PATCH] clean-up `single_match` a bit --- clippy_lints/src/matches/single_match.rs | 27 +++++++++++++----------- tests/ui/single_match.fixed | 5 +++-- tests/ui/single_match.rs | 5 +++-- tests/ui/single_match.stderr | 20 +++++++++--------- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index bcf079b70070..0470b5443d18 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -24,17 +24,16 @@ use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; /// span, e.g. a string literal `"//"`, but we know that this isn't the case for empty /// match arms. fn empty_arm_has_comment(cx: &LateContext<'_>, span: Span) -> bool { - if let Some(ff) = span.get_source_range(cx) - && let Some(text) = ff.as_str() - { - text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*") - } else { - false - } + span.check_source_text(cx, |text| text.as_bytes().windows(2).any(|w| w == b"//" || w == b"/*")) } -#[rustfmt::skip] -pub(crate) fn check<'tcx>(cx: &LateContext<'tcx>, ex: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>], expr: &'tcx Expr<'_>, contains_comments: bool) { +pub(crate) fn check<'tcx>( + cx: &LateContext<'tcx>, + ex: &'tcx Expr<'_>, + arms: &'tcx [Arm<'_>], + expr: &'tcx Expr<'_>, + contains_comments: bool, +) { if let [arm1, arm2] = arms && !arms.iter().any(|arm| arm.guard.is_some() || arm.pat.span.from_expansion()) && !expr.span.from_expansion() @@ -226,13 +225,13 @@ enum PatState<'a> { Wild, /// A std enum we know won't be extended. Tracks the states of each variant separately. /// - /// This is not used for `Option` since it uses the current pattern to track it's state. + /// This is not used for `Option` since it uses the current pattern to track its state. StdEnum(&'a mut [PatState<'a>]), /// Either the initial state for a pattern or a non-std enum. There is currently no need to /// distinguish these cases. /// /// For non-std enums there's no need to track the state of sub-patterns as the state of just - /// this pattern on it's own is enough for linting. Consider two cases: + /// this pattern on its own is enough for linting. Consider two cases: /// * This enum has no wild match. This case alone is enough to determine we can lint. /// * This enum has a wild match and therefore all sub-patterns also have a wild match. /// @@ -380,7 +379,11 @@ impl<'a> PatState<'a> { self.add_pat(cx, pat) }, PatKind::Tuple([sub_pat], pos) - if pos.as_opt_usize().is_none() || cx.typeck.pat_ty(pat).tuple_fields().len() == 1 => + // `pat` looks like `(sub_pat)`, without a `..` -- has only one sub-pattern + if pos.as_opt_usize().is_none() + // `pat` looks like `(sub_pat, ..)` or `(.., sub_pat)`, but its type is a unary tuple, + // so it still only has one sub-pattern + || cx.typeck.pat_ty(pat).tuple_fields().len() == 1 => { self.add_pat(cx, sub_pat) }, diff --git a/tests/ui/single_match.fixed b/tests/ui/single_match.fixed index db5107600ee6..03982b069e67 100644 --- a/tests/ui/single_match.fixed +++ b/tests/ui/single_match.fixed @@ -218,7 +218,7 @@ fn main() { }; } -fn issue_10808(bar: Option) { +fn issue10808(bar: Option) { if let Some(v) = bar { unsafe { let r = &v as *const i32; println!("{}", *r); @@ -330,6 +330,7 @@ pub struct Data([u8; 4]); const DATA: Data = Data([1, 2, 3, 4]); const CONST_I32: i32 = 1; +// https://github.com/rust-lang/rust-clippy/issues/13012 fn irrefutable_match() { println!(); //~^^^^ single_match @@ -367,7 +368,7 @@ fn irrefutable_match() { //~| NOTE: you might want to preserve the comments from inside the `match` } -fn issue_14493() { +fn issue14493() { macro_rules! mac { (some) => { Some(42) diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index a367b94c4ca6..e28128e35ada 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -269,7 +269,7 @@ fn main() { }; } -fn issue_10808(bar: Option) { +fn issue10808(bar: Option) { match bar { Some(v) => unsafe { let r = &v as *const i32; @@ -397,6 +397,7 @@ pub struct Data([u8; 4]); const DATA: Data = Data([1, 2, 3, 4]); const CONST_I32: i32 = 1; +// https://github.com/rust-lang/rust-clippy/issues/13012 fn irrefutable_match() { match DATA { DATA => println!(), @@ -462,7 +463,7 @@ fn irrefutable_match() { //~| NOTE: you might want to preserve the comments from inside the `match` } -fn issue_14493() { +fn issue14493() { macro_rules! mac { (some) => { Some(42) diff --git a/tests/ui/single_match.stderr b/tests/ui/single_match.stderr index 1a4edc45c928..ba8bc5af5a60 100644 --- a/tests/ui/single_match.stderr +++ b/tests/ui/single_match.stderr @@ -225,7 +225,7 @@ LL | | } | |_____^ help: try: `if &s[0..3] == b"foo" { println!() }` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:401:5 + --> tests/ui/single_match.rs:402:5 | LL | / match DATA { LL | | DATA => println!(), @@ -234,7 +234,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:407:5 + --> tests/ui/single_match.rs:408:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), @@ -243,7 +243,7 @@ LL | | } | |_____^ help: try: `println!();` error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:414:5 + --> tests/ui/single_match.rs:415:5 | LL | / match i { LL | | i => { @@ -263,7 +263,7 @@ LL + } | error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:423:5 + --> tests/ui/single_match.rs:424:5 | LL | / match i { LL | | i => {}, @@ -272,7 +272,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:429:5 + --> tests/ui/single_match.rs:430:5 | LL | / match i { LL | | i => (), @@ -281,7 +281,7 @@ LL | | } | |_____^ help: `match` expression can be removed error: this pattern is irrefutable, `match` is useless - --> tests/ui/single_match.rs:435:5 + --> tests/ui/single_match.rs:436:5 | LL | / match CONST_I32 { LL | | CONST_I32 => println!(), @@ -290,7 +290,7 @@ LL | | } | |_____^ help: try: `println!();` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:443:5 + --> tests/ui/single_match.rs:444:5 | LL | / match x.pop() { LL | | // bla @@ -302,7 +302,7 @@ LL | | } = note: you might want to preserve the comments from inside the `match` error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:452:5 + --> tests/ui/single_match.rs:453:5 | LL | / match x.pop() { LL | | // bla @@ -322,7 +322,7 @@ LL + } | error: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let` - --> tests/ui/single_match.rs:478:5 + --> tests/ui/single_match.rs:479:5 | LL | / match mac!(some) { LL | | Some(u) => println!("{u}"), @@ -331,7 +331,7 @@ LL | | } | |_____^ help: try: `if let Some(u) = mac!(some) { println!("{u}") }` error: you seem to be trying to use `match` for an equality check. Consider using `if` - --> tests/ui/single_match.rs:486:5 + --> tests/ui/single_match.rs:487:5 | LL | / match mac!(str) { LL | | "foo" => println!("eq"),