Skip to content

Commit a74b4b9

Browse files
committed
fix: incorrect suggestions when .then and .then_some is used
1 parent 52ae262 commit a74b4b9

File tree

4 files changed

+74
-7
lines changed

4 files changed

+74
-7
lines changed

clippy_lints/src/methods/search_is_some.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg};
22
use clippy_utils::source::{snippet, snippet_with_applicability};
33
use clippy_utils::sugg::deref_closure_args;
44
use clippy_utils::ty::is_type_lang_item;
5-
use clippy_utils::{is_trait_method, strip_pat_refs};
5+
use clippy_utils::{get_parent_expr, is_trait_method, strip_pat_refs};
6+
use hir::ExprKind;
67
use rustc_errors::Applicability;
78
use rustc_hir as hir;
89
use rustc_hir::PatKind;
@@ -72,16 +73,24 @@ pub(super) fn check<'tcx>(
7273
);
7374
} else {
7475
let iter = snippet(cx, search_recv.span, "..");
76+
let sugg = if is_receiver_of_method_call(cx, expr) {
77+
format!(
78+
"(!{iter}.any({}))",
79+
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
80+
)
81+
} else {
82+
format!(
83+
"!{iter}.any({})",
84+
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
85+
)
86+
};
7587
span_lint_and_sugg(
7688
cx,
7789
SEARCH_IS_SOME,
7890
expr.span,
7991
&msg,
8092
"use `!_.any()` instead",
81-
format!(
82-
"!{iter}.any({})",
83-
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
84-
),
93+
sugg,
8594
applicability,
8695
);
8796
}
@@ -127,13 +136,18 @@ pub(super) fn check<'tcx>(
127136
let string = snippet(cx, search_recv.span, "..");
128137
let mut applicability = Applicability::MachineApplicable;
129138
let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
139+
let sugg = if is_receiver_of_method_call(cx, expr) {
140+
format!("(!{string}.contains({find_arg}))")
141+
} else {
142+
format!("!{string}.contains({find_arg})")
143+
};
130144
span_lint_and_sugg(
131145
cx,
132146
SEARCH_IS_SOME,
133147
expr.span,
134148
&msg,
135149
"use `!_.contains()` instead",
136-
format!("!{string}.contains({find_arg})"),
150+
sugg,
137151
applicability,
138152
);
139153
},
@@ -142,3 +156,12 @@ pub(super) fn check<'tcx>(
142156
}
143157
}
144158
}
159+
160+
fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
161+
if let Some(parent_expr) = get_parent_expr(cx, expr)
162+
&& let ExprKind::MethodCall(..) = parent_expr.kind
163+
{
164+
return true;
165+
}
166+
false
167+
}

tests/ui/search_is_some_fixable_none.fixed

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,19 @@ mod issue7392 {
213213
let _ = !v.iter().any(|fp| test_u32_2(*fp.field));
214214
}
215215
}
216+
217+
mod issue_11910 {
218+
fn computations() -> u32 {
219+
0
220+
}
221+
222+
fn test_then() {
223+
let v = vec![3, 2, 1, 0, -1, -2, -3];
224+
(!v.iter().any(|x| *x == 42)).then(computations);
225+
}
226+
227+
fn test_then_some() {
228+
let v = vec![3, 2, 1, 0, -1, -2, -3];
229+
(!v.iter().any(|x| *x == 42)).then_some(0);
230+
}
231+
}

tests/ui/search_is_some_fixable_none.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,19 @@ mod issue7392 {
219219
let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
220220
}
221221
}
222+
223+
mod issue_11910 {
224+
fn computations() -> u32 {
225+
0
226+
}
227+
228+
fn test_then() {
229+
let v = vec![3, 2, 1, 0, -1, -2, -3];
230+
v.iter().find(|x| **x == 42).is_none().then(computations);
231+
}
232+
233+
fn test_then_some() {
234+
let v = vec![3, 2, 1, 0, -1, -2, -3];
235+
v.iter().find(|x| **x == 42).is_none().then_some(0);
236+
}
237+
}

tests/ui/search_is_some_fixable_none.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,5 +282,17 @@ error: called `is_none()` after searching an `Iterator` with `find`
282282
LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
283283
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `!v.iter().any(|fp| test_u32_2(*fp.field))`
284284

285-
error: aborting due to 43 previous errors
285+
error: called `is_none()` after searching an `Iterator` with `find`
286+
--> $DIR/search_is_some_fixable_none.rs:230:9
287+
|
288+
LL | v.iter().find(|x| **x == 42).is_none().then(computations);
289+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
290+
291+
error: called `is_none()` after searching an `Iterator` with `find`
292+
--> $DIR/search_is_some_fixable_none.rs:235:9
293+
|
294+
LL | v.iter().find(|x| **x == 42).is_none().then_some(0);
295+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
296+
297+
error: aborting due to 45 previous errors
286298

0 commit comments

Comments
 (0)