diff options
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs')
-rw-r--r-- | src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs | 42 |
1 files changed, 22 insertions, 20 deletions
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 6fc79fadd..c823d07e2 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; use clippy_utils::{is_lint_allowed, path_to_local, search_same, SpanlessEq, SpanlessHash}; use core::cmp::Ordering; @@ -66,25 +66,23 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { let mut local_map: HirIdMap<HirId> = HirIdMap::default(); let eq_fallback = |a: &Expr<'_>, b: &Expr<'_>| { - if_chain! { - if let Some(a_id) = path_to_local(a); - if let Some(b_id) = path_to_local(b); - let entry = match local_map.entry(a_id) { + if let Some(a_id) = path_to_local(a) + && let Some(b_id) = path_to_local(b) + && let entry = match local_map.entry(a_id) { HirIdMapEntry::Vacant(entry) => entry, // check if using the same bindings as before HirIdMapEntry::Occupied(entry) => return *entry.get() == b_id, - }; - // the names technically don't have to match; this makes the lint more conservative - if cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id); - if cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b); - if pat_contains_local(lhs.pat, a_id); - if pat_contains_local(rhs.pat, b_id); - then { - entry.insert(b_id); - true - } else { - false } + // the names technically don't have to match; this makes the lint more conservative + && cx.tcx.hir().name(a_id) == cx.tcx.hir().name(b_id) + && cx.typeck_results().expr_ty(a) == cx.typeck_results().expr_ty(b) + && pat_contains_local(lhs.pat, a_id) + && pat_contains_local(rhs.pat, b_id) + { + entry.insert(b_id); + true + } else { + false } }; // Arms with a guard are ignored, those can’t always be merged together @@ -106,9 +104,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { if !cx.tcx.features().non_exhaustive_omitted_patterns_lint || is_lint_allowed(cx, NON_EXHAUSTIVE_OMITTED_PATTERNS, arm2.hir_id) { - span_lint_and_then( + span_lint_hir_and_then( cx, MATCH_SAME_ARMS, + arm1.hir_id, arm1.span, "this match arm has an identical body to the `_` wildcard arm", |diag| { @@ -126,9 +125,10 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { (arm2, arm1) }; - span_lint_and_then( + span_lint_hir_and_then( cx, MATCH_SAME_ARMS, + keep_arm.hir_id, keep_arm.span, "this match arm has an identical body to another arm", |diag| { @@ -152,6 +152,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>]) { #[derive(Clone, Copy)] enum NormalizedPat<'a> { Wild, + Never, Struct(Option<DefId>, &'a [(Symbol, Self)]), Tuple(Option<DefId>, &'a [Self]), Or(&'a [Self]), @@ -223,7 +224,7 @@ fn iter_matching_struct_fields<'a>( Iter(left.iter(), right.iter()) } -#[expect(clippy::similar_names)] +#[expect(clippy::similar_names, clippy::too_many_lines)] impl<'a> NormalizedPat<'a> { fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> Self { match pat.kind { @@ -231,6 +232,7 @@ impl<'a> NormalizedPat<'a> { PatKind::Binding(.., Some(pat)) | PatKind::Box(pat) | PatKind::Ref(pat, _) => { Self::from_pat(cx, arena, pat) }, + PatKind::Never => Self::Never, PatKind::Struct(ref path, fields, _) => { let fields = arena.alloc_from_iter(fields.iter().map(|f| (f.ident.name, Self::from_pat(cx, arena, f.pat)))); @@ -334,7 +336,7 @@ impl<'a> NormalizedPat<'a> { /// type. fn has_overlapping_values(&self, other: &Self) -> bool { match (*self, *other) { - (Self::Wild, _) | (_, Self::Wild) => true, + (Self::Wild, _) | (_, Self::Wild) | (Self::Never, Self::Never) => true, (Self::Or(pats), ref other) | (ref other, Self::Or(pats)) => { pats.iter().any(|pat| pat.has_overlapping_values(other)) }, |