Auto merge of #11016 - y21:issue10029, r=blyxyas,dswij
[`filter_next`]: suggest making binding mutable if it needs to be Fixes #10029 changelog: [`filter_next`]: suggest making binding mutable if it needs to be and adjust applicability
This commit is contained in:
commit
3be3fb7231
@ -1,6 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
|
use clippy_utils::diagnostics::{span_lint, span_lint_and_then};
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::ty::implements_trait;
|
use clippy_utils::ty::implements_trait;
|
||||||
|
use rustc_ast::{BindingAnnotation, Mutability};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -8,6 +9,21 @@
|
|||||||
|
|
||||||
use super::FILTER_NEXT;
|
use super::FILTER_NEXT;
|
||||||
|
|
||||||
|
fn path_to_local(expr: &hir::Expr<'_>) -> Option<hir::HirId> {
|
||||||
|
match expr.kind {
|
||||||
|
hir::ExprKind::Field(f, _) => path_to_local(f),
|
||||||
|
hir::ExprKind::Index(recv, _) => path_to_local(recv),
|
||||||
|
hir::ExprKind::Path(hir::QPath::Resolved(
|
||||||
|
_,
|
||||||
|
hir::Path {
|
||||||
|
res: rustc_hir::def::Res::Local(local),
|
||||||
|
..
|
||||||
|
},
|
||||||
|
)) => Some(*local),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// lint use of `filter().next()` for `Iterators`
|
/// lint use of `filter().next()` for `Iterators`
|
||||||
pub(super) fn check<'tcx>(
|
pub(super) fn check<'tcx>(
|
||||||
cx: &LateContext<'tcx>,
|
cx: &LateContext<'tcx>,
|
||||||
@ -26,15 +42,30 @@ pub(super) fn check<'tcx>(
|
|||||||
if filter_snippet.lines().count() <= 1 {
|
if filter_snippet.lines().count() <= 1 {
|
||||||
let iter_snippet = snippet(cx, recv.span, "..");
|
let iter_snippet = snippet(cx, recv.span, "..");
|
||||||
// add note if not multi-line
|
// add note if not multi-line
|
||||||
span_lint_and_sugg(
|
span_lint_and_then(cx, FILTER_NEXT, expr.span, msg, |diag| {
|
||||||
cx,
|
let (applicability, pat) = if let Some(id) = path_to_local(recv)
|
||||||
FILTER_NEXT,
|
&& let Some(hir::Node::Pat(pat)) = cx.tcx.hir().find(id)
|
||||||
expr.span,
|
&& let hir::PatKind::Binding(BindingAnnotation(_, Mutability::Not), _, ident, _) = pat.kind
|
||||||
msg,
|
{
|
||||||
"try",
|
(Applicability::Unspecified, Some((pat.span, ident)))
|
||||||
format!("{iter_snippet}.find({filter_snippet})"),
|
} else {
|
||||||
Applicability::MachineApplicable,
|
(Applicability::MachineApplicable, None)
|
||||||
);
|
};
|
||||||
|
|
||||||
|
diag.span_suggestion(
|
||||||
|
expr.span,
|
||||||
|
"try",
|
||||||
|
format!("{iter_snippet}.find({filter_snippet})"),
|
||||||
|
applicability,
|
||||||
|
);
|
||||||
|
|
||||||
|
if let Some((pat_span, ident)) = pat {
|
||||||
|
diag.span_help(
|
||||||
|
pat_span,
|
||||||
|
format!("you will also need to make `{ident}` mutable, because `find` takes `&mut self`"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
span_lint(cx, FILTER_NEXT, expr.span, msg);
|
span_lint(cx, FILTER_NEXT, expr.span, msg);
|
||||||
}
|
}
|
||||||
|
10
tests/ui/methods_unfixable.rs
Normal file
10
tests/ui/methods_unfixable.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#![warn(clippy::filter_next)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
issue10029();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn issue10029() {
|
||||||
|
let iter = (0..10);
|
||||||
|
let _ = iter.filter(|_| true).next();
|
||||||
|
}
|
15
tests/ui/methods_unfixable.stderr
Normal file
15
tests/ui/methods_unfixable.stderr
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error: called `filter(..).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(..)` instead
|
||||||
|
--> $DIR/methods_unfixable.rs:9:13
|
||||||
|
|
|
||||||
|
LL | let _ = iter.filter(|_| true).next();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `iter.find(|_| true)`
|
||||||
|
|
|
||||||
|
help: you will also need to make `iter` mutable, because `find` takes `&mut self`
|
||||||
|
--> $DIR/methods_unfixable.rs:8:9
|
||||||
|
|
|
||||||
|
LL | let iter = (0..10);
|
||||||
|
| ^^^^
|
||||||
|
= note: `-D clippy::filter-next` implied by `-D warnings`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user