fix: incorrect suggestions when .then and .then_some is used

This commit is contained in:
Yuxiang Qiu 2024-01-04 14:41:38 -05:00
parent 2b30a5924e
commit b2ea5eef44
No known key found for this signature in database
4 changed files with 74 additions and 7 deletions

View File

@ -2,7 +2,8 @@
use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::source::{snippet, snippet_with_applicability};
use clippy_utils::sugg::deref_closure_args; use clippy_utils::sugg::deref_closure_args;
use clippy_utils::ty::is_type_lang_item; use clippy_utils::ty::is_type_lang_item;
use clippy_utils::{is_trait_method, strip_pat_refs}; use clippy_utils::{get_parent_expr, is_trait_method, strip_pat_refs};
use hir::ExprKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::PatKind; use rustc_hir::PatKind;
@ -72,16 +73,24 @@ pub(super) fn check<'tcx>(
); );
} else { } else {
let iter = snippet(cx, search_recv.span, ".."); let iter = snippet(cx, search_recv.span, "..");
let sugg = if is_receiver_of_method_call(cx, expr) {
format!(
"(!{iter}.any({}))",
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
)
} else {
format!(
"!{iter}.any({})",
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
)
};
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
SEARCH_IS_SOME, SEARCH_IS_SOME,
expr.span, expr.span,
msg, msg,
"consider using", "consider using",
format!( sugg,
"!{iter}.any({})",
any_search_snippet.as_ref().map_or(&*search_snippet, String::as_str)
),
applicability, applicability,
); );
} }
@ -127,13 +136,18 @@ pub(super) fn check<'tcx>(
let string = snippet(cx, search_recv.span, ".."); let string = snippet(cx, search_recv.span, "..");
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability); let find_arg = snippet_with_applicability(cx, search_arg.span, "..", &mut applicability);
let sugg = if is_receiver_of_method_call(cx, expr) {
format!("(!{string}.contains({find_arg}))")
} else {
format!("!{string}.contains({find_arg})")
};
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
SEARCH_IS_SOME, SEARCH_IS_SOME,
expr.span, expr.span,
msg, msg,
"consider using", "consider using",
format!("!{string}.contains({find_arg})"), sugg,
applicability, applicability,
); );
}, },
@ -142,3 +156,12 @@ pub(super) fn check<'tcx>(
} }
} }
} }
fn is_receiver_of_method_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
if let Some(parent_expr) = get_parent_expr(cx, expr)
&& let ExprKind::MethodCall(..) = parent_expr.kind
{
return true;
}
false
}

View File

@ -213,3 +213,19 @@ mod issue7392 {
let _ = !v.iter().any(|fp| test_u32_2(*fp.field)); let _ = !v.iter().any(|fp| test_u32_2(*fp.field));
} }
} }
mod issue_11910 {
fn computations() -> u32 {
0
}
fn test_then() {
let v = vec![3, 2, 1, 0, -1, -2, -3];
(!v.iter().any(|x| *x == 42)).then(computations);
}
fn test_then_some() {
let v = vec![3, 2, 1, 0, -1, -2, -3];
(!v.iter().any(|x| *x == 42)).then_some(0);
}
}

View File

@ -219,3 +219,19 @@ struct FieldProjection<'a> {
let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none(); let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
} }
} }
mod issue_11910 {
fn computations() -> u32 {
0
}
fn test_then() {
let v = vec![3, 2, 1, 0, -1, -2, -3];
v.iter().find(|x| **x == 42).is_none().then(computations);
}
fn test_then_some() {
let v = vec![3, 2, 1, 0, -1, -2, -3];
v.iter().find(|x| **x == 42).is_none().then_some(0);
}
}

View File

@ -282,5 +282,17 @@ error: called `is_none()` after searching an `Iterator` with `find`
LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none(); LL | let _ = v.iter().find(|fp| test_u32_2(*fp.field)).is_none();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!v.iter().any(|fp| test_u32_2(*fp.field))`
error: aborting due to 43 previous errors error: called `is_none()` after searching an `Iterator` with `find`
--> $DIR/search_is_some_fixable_none.rs:230:9
|
LL | v.iter().find(|x| **x == 42).is_none().then(computations);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
error: called `is_none()` after searching an `Iterator` with `find`
--> $DIR/search_is_some_fixable_none.rs:235:9
|
LL | v.iter().find(|x| **x == 42).is_none().then_some(0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `!_.any()` instead: `(!v.iter().any(|x| *x == 42))`
error: aborting due to 45 previous errors