2024-02-28 13:17:14 +00:00
|
|
|
//@compile-flags: -Zdeduplicate-diagnostics=yes
|
|
|
|
|
2020-12-06 14:01:03 +00:00
|
|
|
#![warn(clippy::suspicious_operation_groupings)]
|
2022-05-19 13:03:38 +00:00
|
|
|
#![allow(dead_code, unused_parens, clippy::eq_op)]
|
2020-12-06 14:01:03 +00:00
|
|
|
|
|
|
|
struct Vec3 {
|
|
|
|
x: f64,
|
|
|
|
y: f64,
|
|
|
|
z: f64,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Eq for Vec3 {}
|
|
|
|
|
|
|
|
impl PartialEq for Vec3 {
|
|
|
|
fn eq(&self, other: &Self) -> bool {
|
|
|
|
// This should trigger the lint because `self.x` is compared to `other.y`
|
|
|
|
self.x == other.y && self.y == other.y && self.z == other.z
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct S {
|
|
|
|
a: i32,
|
|
|
|
b: i32,
|
|
|
|
c: i32,
|
|
|
|
d: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn buggy_ab_cmp(s1: &S, s2: &S) -> bool {
|
|
|
|
// There's no `s1.b`
|
|
|
|
s1.a < s2.a && s1.a < s2.b
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:06:34 +00:00
|
|
|
struct SaOnly {
|
2020-12-06 14:01:03 +00:00
|
|
|
a: i32,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl S {
|
|
|
|
fn a(&self) -> i32 {
|
|
|
|
0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:06:34 +00:00
|
|
|
fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SaOnly) -> bool {
|
2020-12-06 14:01:03 +00:00
|
|
|
// This is superficially similar to `buggy_ab_cmp`, but we should not suggest
|
|
|
|
// `s2.b` since that is invalid.
|
|
|
|
s1.a < s2.a && s1.a() < s1.b
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:06:34 +00:00
|
|
|
fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SaOnly) -> bool {
|
2020-12-06 14:01:03 +00:00
|
|
|
macro_rules! s1 {
|
|
|
|
() => {
|
|
|
|
S {
|
|
|
|
a: 1,
|
|
|
|
b: 1,
|
|
|
|
c: 1,
|
|
|
|
d: 1,
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is superficially similar to `buggy_ab_cmp`, but we should not suggest
|
|
|
|
// `s2.b` since that is invalid.
|
|
|
|
s1.a < s2.a && s1!().a < s1.b
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:06:34 +00:00
|
|
|
fn do_not_give_bad_suggestions_for_this_incorrect_expr(s1: &S, s2: &SaOnly) -> bool {
|
2020-12-06 14:01:03 +00:00
|
|
|
// There's two `s1.b`, but we should not suggest `s2.b` since that is invalid
|
|
|
|
s1.a < s2.a && s1.b < s1.b
|
|
|
|
}
|
|
|
|
|
|
|
|
fn permissable(s1: &S, s2: &S) -> bool {
|
|
|
|
// Something like this seems like it might actually be what is desired.
|
|
|
|
s1.a == s2.b
|
|
|
|
}
|
|
|
|
|
|
|
|
fn non_boolean_operators(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
|
|
|
|
}
|
|
|
|
|
|
|
|
fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.b`
|
|
|
|
s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s1.b`
|
|
|
|
s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.b`
|
|
|
|
s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.a`
|
|
|
|
s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
|
|
|
|
}
|
|
|
|
|
|
|
|
fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) {
|
|
|
|
(
|
|
|
|
s1.b * s2.c - s1.c * s2.b,
|
|
|
|
s1.c * s2.a - s1.a * s2.c,
|
|
|
|
s1.a * s2.b - s1.b * s2.a,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn outer_parens_simple(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.b`
|
|
|
|
(s1.a * s2.a + s1.b * s1.b)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn outer_parens(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
(s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inner_parens(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
(s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
(((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_parens_left_tree(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
(((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all_parens_right_tree(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s1.b`
|
|
|
|
(s1.a * s2.a + s2.b * s2.b) / 2
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inside_function_call(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s1.b`
|
|
|
|
i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool {
|
|
|
|
// There's no `s1.c`
|
|
|
|
s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool {
|
|
|
|
// There's no `s1.c`
|
|
|
|
s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
|
|
|
|
}
|
|
|
|
|
|
|
|
struct Nested {
|
|
|
|
inner: ((i32,), (i32,), (i32,)),
|
|
|
|
}
|
|
|
|
|
|
|
|
fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool {
|
|
|
|
// There's no `n2.inner.2.0`
|
|
|
|
(n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
|
|
|
|
}
|
|
|
|
|
|
|
|
// `eq_op` should catch this one.
|
|
|
|
fn changed_initial_ident(n1: &Nested, n2: &Nested) -> bool {
|
|
|
|
// There's no `n2.inner.0.0`
|
|
|
|
(n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
|
|
|
|
}
|
|
|
|
|
|
|
|
fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
|
|
|
|
if strict {
|
|
|
|
s1.a < s2.a && s1.b < s2.b
|
|
|
|
} else {
|
|
|
|
// There's no `s1.b` in this subexpression
|
|
|
|
s1.a <= s2.a && s1.a <= s2.b
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-21 03:23:22 +00:00
|
|
|
fn inside_an_if_statement(s1: &mut S, s2: &S) {
|
2020-12-06 14:01:03 +00:00
|
|
|
// There's no `s1.b`
|
|
|
|
if s1.a < s2.a && s1.a < s2.b {
|
|
|
|
s1.c = s2.c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s2.c`
|
|
|
|
-(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 {
|
|
|
|
// There's no `s1.b`
|
|
|
|
-(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
|
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {}
|