From bfca92ce1ce0747ff0061288196b739a26fbc20d Mon Sep 17 00:00:00 2001 From: NicDevTV <130746231+NicDevTV@users.noreply.github.com> Date: Mon, 17 Aug 2026 17:49:42 +0200 Subject: [PATCH 1/4] fix(lints): avoid method-name false positives in suspicious_operation_groupings --- .../src/suspicious_operation_groupings.rs | 8 +++++- tests/ui/suspicious_operation_groupings.rs | 26 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index 57f5fc903956..568fa9e3adf4 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -580,12 +580,18 @@ fn ident_difference_expr_with_base_location( | (Unary(_, _), Unary(_, _)) | (Binary(_, _, _), Binary(_, _, _)) | (Tup(_), Tup(_)) - | (MethodCall(_), MethodCall(_)) | (Call(_, _), Call(_, _)) | (ConstBlock(_), ConstBlock(_)) | (Array(_), Array(_)) => { // keep going }, + (MethodCall(left, ..), MethodCall(right, ..)) => { + // A method name is part of the expression's structure, not a + // candidate for the identifier swap this lint is looking for. + if !eq_id(left.ident, right.ident) { + return (IdentDifference::NonIdent, base); + } + }, _ => { return (IdentDifference::NonIdent, base); }, diff --git a/tests/ui/suspicious_operation_groupings.rs b/tests/ui/suspicious_operation_groupings.rs index ff77f2e56463..785ebce9ca81 100644 --- a/tests/ui/suspicious_operation_groupings.rs +++ b/tests/ui/suspicious_operation_groupings.rs @@ -38,6 +38,18 @@ impl S { fn a(&self) -> i32 { 0 } + + fn is_special(&self) -> bool { + true + } + + fn is_file(&self) -> bool { + true + } + + fn has_authority(&self) -> bool { + true + } } fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> bool { @@ -46,6 +58,20 @@ fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> boo s1.a < s2.a && s1.a() < s1.b } +fn do_not_suggest_a_different_method(s1: &S, s2: &S) -> bool { + // The different method names are intentional and must not be treated as a + // typo in the receiver. + (s1.is_special() && !s2.is_special()) + || (!s1.is_special() && s2.is_special()) + || (s1.is_file() && s2.has_authority()) +} + +#[expect(clippy::suspicious_operation_groupings)] +fn still_detects_a_receiver_typo_with_the_same_method(s1: &S, s2: &S) -> i32 { + // The method names match, so a receiver mismatch remains suspicious. + s1.a() * s2.a() + s1.a() * s1.a() +} + fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SaOnly) -> bool { macro_rules! s1 { () => { From 11f49c2e8be53ac9d2bd02b4b9fc0a0b42e09aab Mon Sep 17 00:00:00 2001 From: NicDevTV <130746231+NicDevTV@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:36:47 +0200 Subject: [PATCH 2/4] fix(lints): access method name through segment --- clippy_lints/src/suspicious_operation_groupings.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/suspicious_operation_groupings.rs b/clippy_lints/src/suspicious_operation_groupings.rs index 568fa9e3adf4..a50c3a6a34c0 100644 --- a/clippy_lints/src/suspicious_operation_groupings.rs +++ b/clippy_lints/src/suspicious_operation_groupings.rs @@ -588,7 +588,7 @@ fn ident_difference_expr_with_base_location( (MethodCall(left, ..), MethodCall(right, ..)) => { // A method name is part of the expression's structure, not a // candidate for the identifier swap this lint is looking for. - if !eq_id(left.ident, right.ident) { + if !eq_id(left.seg.ident, right.seg.ident) { return (IdentDifference::NonIdent, base); } }, From 911569c1f41cbef9e53fd8daf691a0f5fff8cff4 Mon Sep 17 00:00:00 2001 From: NicDevTV <130746231+NicDevTV@users.noreply.github.com> Date: Mon, 17 Aug 2026 19:45:09 +0200 Subject: [PATCH 3/4] test(ui): update suspicious operation groupings expectations --- tests/ui/suspicious_operation_groupings.fixed | 26 +++++++++++ .../ui/suspicious_operation_groupings.stderr | 45 +++++++++---------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/tests/ui/suspicious_operation_groupings.fixed b/tests/ui/suspicious_operation_groupings.fixed index 1ad3b37a08ae..2b4c291f61fd 100644 --- a/tests/ui/suspicious_operation_groupings.fixed +++ b/tests/ui/suspicious_operation_groupings.fixed @@ -38,6 +38,18 @@ impl S { fn a(&self) -> i32 { 0 } + + fn is_special(&self) -> bool { + true + } + + fn is_file(&self) -> bool { + true + } + + fn has_authority(&self) -> bool { + true + } } fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> bool { @@ -46,6 +58,20 @@ fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> boo s1.a < s2.a && s1.a() < s1.b } +fn do_not_suggest_a_different_method(s1: &S, s2: &S) -> bool { + // The different method names are intentional and must not be treated as a + // typo in the receiver. + (s1.is_special() && !s2.is_special()) + || (!s1.is_special() && s2.is_special()) + || (s1.is_file() && s2.has_authority()) +} + +#[expect(clippy::suspicious_operation_groupings)] +fn still_detects_a_receiver_typo_with_the_same_method(s1: &S, s2: &S) -> i32 { + // The method names match, so a receiver mismatch remains suspicious. + s1.a() * s2.a() + s1.a() * s1.a() +} + fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SaOnly) -> bool { macro_rules! s1 { () => { diff --git a/tests/ui/suspicious_operation_groupings.stderr b/tests/ui/suspicious_operation_groupings.stderr index 0231dbbbb2d1..ef8ecc9e36ff 100644 --- a/tests/ui/suspicious_operation_groupings.stderr +++ b/tests/ui/suspicious_operation_groupings.stderr @@ -14,136 +14,135 @@ LL | s1.a < s2.a && s1.a < s2.b | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:78:33 + --> tests/ui/suspicious_operation_groupings.rs:104:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:84:19 + --> tests/ui/suspicious_operation_groupings.rs:110:19 | LL | s1.a * s2.a + s1.b * s2.c + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:90:19 + --> tests/ui/suspicious_operation_groupings.rs:116:19 | LL | s1.a * s2.a + s2.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:96:19 + --> tests/ui/suspicious_operation_groupings.rs:122:19 | LL | s1.a * s2.a + s1.b * s1.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:102:5 + --> tests/ui/suspicious_operation_groupings.rs:128:5 | LL | s1.a * s1.a + s1.b * s2.b + s1.c * s2.c | ^^^^^^^^^^^ help: did you mean: `s1.a * s2.a` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:108:33 + --> tests/ui/suspicious_operation_groupings.rs:134:33 | LL | s1.a * s2.a + s1.b * s2.b + s1.c * s1.c | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:122:20 + --> tests/ui/suspicious_operation_groupings.rs:148:20 | LL | (s1.a * s2.a + s1.b * s1.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:128:34 + --> tests/ui/suspicious_operation_groupings.rs:154:34 | LL | (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:134:38 + --> tests/ui/suspicious_operation_groupings.rs:160:38 | LL | (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:140:39 + --> tests/ui/suspicious_operation_groupings.rs:166:39 | LL | ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:146:42 + --> tests/ui/suspicious_operation_groupings.rs:172:42 | LL | (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:152:40 + --> tests/ui/suspicious_operation_groupings.rs:178:40 | LL | (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d)) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:158:40 + --> tests/ui/suspicious_operation_groupings.rs:184:40 | LL | ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))) | ^^^^^^^^^^^ help: did you mean: `s1.c * s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:164:20 + --> tests/ui/suspicious_operation_groupings.rs:190:20 | LL | (s1.a * s2.a + s2.b * s2.b) / 2 | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:170:35 + --> tests/ui/suspicious_operation_groupings.rs:196:35 | LL | i32::swap_bytes(s1.a * s2.a + s2.b * s2.b) | ^^^^^^^^^^^ help: did you mean: `s1.b * s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:176:29 + --> tests/ui/suspicious_operation_groupings.rs:202:29 | LL | s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:182:17 + --> tests/ui/suspicious_operation_groupings.rs:208:17 | LL | s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d | ^^^^^^^^^^^^ help: did you mean: `s1.c == s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:192:77 + --> tests/ui/suspicious_operation_groupings.rs:218:77 | LL | (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `(n1.inner.2).0 == (n2.inner.2).0` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:207:25 + --> tests/ui/suspicious_operation_groupings.rs:233:25 | LL | s1.a <= s2.a && s1.a <= s2.b | ^^^^^^^^^^^^ help: did you mean: `s1.b <= s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:214:23 + --> tests/ui/suspicious_operation_groupings.rs:240:23 | LL | if s1.a < s2.a && s1.a < s2.b { | ^^^^^^^^^^^ help: did you mean: `s1.b < s2.b` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:222:48 + --> tests/ui/suspicious_operation_groupings.rs:248:48 | LL | -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d))) | ^^^^^^^^^^^^^ help: did you mean: `-s1.c * -s2.c` error: this sequence of operators looks suspiciously like a bug - --> tests/ui/suspicious_operation_groupings.rs:228:27 + --> tests/ui/suspicious_operation_groupings.rs:254:27 | LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) | ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b` error: aborting due to 24 previous errors - From 7d9f738da62981e9a91827042caf62a9c6cf2911 Mon Sep 17 00:00:00 2001 From: NicDevTV <130746231+NicDevTV@users.noreply.github.com> Date: Mon, 17 Aug 2026 20:00:11 +0200 Subject: [PATCH 4/4] test(ui): preserve expected stderr terminator --- tests/ui/suspicious_operation_groupings.stderr | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/suspicious_operation_groupings.stderr b/tests/ui/suspicious_operation_groupings.stderr index ef8ecc9e36ff..8879f6c8a49f 100644 --- a/tests/ui/suspicious_operation_groupings.stderr +++ b/tests/ui/suspicious_operation_groupings.stderr @@ -146,3 +146,4 @@ LL | -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a }) | ^^^^^^^^^^^^^ help: did you mean: `-s1.b < -s2.b` error: aborting due to 24 previous errors +