-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: unnecessary_filter_map return of Some arg #12766
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,11 +3,12 @@ use clippy_utils::diagnostics::span_lint; | |
use clippy_utils::ty::is_copy; | ||
use clippy_utils::usage::mutated_variables; | ||
use clippy_utils::visitors::{for_each_expr, Descend}; | ||
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id}; | ||
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id, MaybePath}; | ||
use core::ops::ControlFlow; | ||
use rustc_hir as hir; | ||
use rustc_hir::LangItem::{OptionNone, OptionSome}; | ||
use rustc_lint::LateContext; | ||
use rustc_middle::query::Key; | ||
use rustc_middle::ty; | ||
use rustc_span::sym; | ||
|
||
|
@@ -17,7 +18,6 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a | |
if !is_trait_method(cx, expr, sym::Iterator) { | ||
return; | ||
} | ||
|
||
if let hir::ExprKind::Closure(&hir::Closure { body, .. }) = arg.kind { | ||
let body = cx.tcx.hir().body(body); | ||
let arg_id = body.params[0].pat.hir_id; | ||
|
@@ -36,9 +36,20 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>, a | |
ControlFlow::Continue(Descend::Yes) | ||
} | ||
}); | ||
|
||
let in_ty = cx.typeck_results().node_type(body.params[0].hir_id); | ||
let sugg = if !found_filtering { | ||
// Check if the closure is .filter_map(|x| Some(x)) | ||
if name == "filter_map" | ||
&& let hir::ExprKind::Call(expr, args) = body.value.kind | ||
{ | ||
if is_res_lang_ctor(cx, path_res(cx, expr), OptionSome) | ||
&& arg_id.ty_def_id() == args[0].hir_id().ty_def_id() | ||
{ | ||
if let hir::ExprKind::Path(_) = args[0].kind { | ||
span_lint(cx, UNNECESSARY_FILTER_MAP, arg.span, &format!("{name} is unnecessary")) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it just occurs to me that... could this be same thing applies here, while suggest replacing the method call, with |
||
} | ||
} | ||
} | ||
if name == "filter_map" { "map" } else { "map(..).next()" } | ||
} else if !found_mapping && !mutates_arg && (!clone_or_copy_needed || is_copy(cx, in_ty)) { | ||
match cx.typeck_results().expr_ty(body.value).kind() { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
//@no-rustfix | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the whole test rustfix-incompatible? If not, could we split our a |
||
#![allow(dead_code)] | ||
|
||
fn main() { | ||
|
@@ -21,6 +22,8 @@ fn main() { | |
//~^ ERROR: this `.filter_map` can be written more simply using `.map` | ||
|
||
let _ = (0..4).filter_map(i32::checked_abs); | ||
|
||
let _ = vec![Some(10), None].into_iter().filter_map(|x| Some(x)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The linked issue also mentions passing a path to let _ = (0..4).filter_map(Some); There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The more tests the merrier 😎 |
||
} | ||
|
||
fn filter_map_none_changes_item_type() -> impl Iterator<Item = bool> { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let chains for the win!