summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs
diff options
context:
space:
mode:
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.rs42
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))
},