@@ -53,40 +53,41 @@ declare_clippy_lint! {
53
53
#[ clippy:: version = "1.70.0" ]
54
54
pub LINES_FILTER_MAP_OK ,
55
55
suspicious,
56
- "filtering `std::io::Lines` with `filter_map()` or `flat_map ()` might cause an infinite loop"
56
+ "filtering `std::io::Lines` with `filter_map()`, `flat_map()`, or `flatten ()` might cause an infinite loop"
57
57
}
58
58
declare_lint_pass ! ( LinesFilterMapOk => [ LINES_FILTER_MAP_OK ] ) ;
59
59
60
60
impl LateLintPass < ' _ > for LinesFilterMapOk {
61
61
fn check_expr ( & mut self , cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
62
- if let ExprKind :: MethodCall ( fm_method, fm_receiver, [ fm_arg] , fm_span) = expr. kind
63
- && is_trait_method ( cx, expr, sym:: Iterator )
64
- && ( fm_method. ident . as_str ( ) == "filter_map" || fm_method. ident . as_str ( ) == "flat_map" )
65
- && is_type_diagnostic_item ( cx, cx. typeck_results ( ) . expr_ty_adjusted ( fm_receiver) , sym:: IoLines )
62
+ if let ExprKind :: MethodCall ( fm_method, fm_receiver, fm_args, fm_span) = expr. kind &&
63
+ is_trait_method ( cx, expr, sym:: Iterator ) &&
64
+ let fm_method_str = fm_method. ident . as_str ( ) &&
65
+ matches ! ( fm_method_str, "filter_map" | "flat_map" | "flatten" ) &&
66
+ is_type_diagnostic_item ( cx, cx. typeck_results ( ) . expr_ty_adjusted ( fm_receiver) , sym:: IoLines )
66
67
{
67
- let lint = match & fm_arg. kind {
68
- // Detect `Result::ok`
69
- ExprKind :: Path ( qpath) => cx
70
- . qpath_res ( qpath, fm_arg. hir_id )
71
- . opt_def_id ( )
72
- . map ( |did| match_def_path ( cx, did, & paths:: CORE_RESULT_OK_METHOD ) )
73
- . unwrap_or_default ( ) ,
74
- // Detect `|x| x.ok()`
75
- ExprKind :: Closure ( Closure { body, .. } ) => {
76
- if let Body {
77
- params : [ param] , value, ..
78
- } = cx. tcx . hir ( ) . body ( * body)
79
- && let ExprKind :: MethodCall ( method, receiver, [ ] , _) = value. kind
80
- && path_to_local_id ( receiver, param. pat . hir_id )
81
- && let Some ( method_did) = cx. typeck_results ( ) . type_dependent_def_id ( value. hir_id )
82
- {
83
- is_diag_item_method ( cx, method_did, sym:: Result ) && method. ident . as_str ( ) == "ok"
84
- } else {
85
- false
86
- }
87
- } ,
88
- _ => false ,
68
+ let lint = if let [ fm_arg] = fm_args {
69
+ match & fm_arg. kind {
70
+ // Detect `Result::ok`
71
+ ExprKind :: Path ( qpath) =>
72
+ cx. qpath_res ( qpath, fm_arg. hir_id ) . opt_def_id ( ) . map ( |did|
73
+ match_def_path ( cx, did, & paths:: CORE_RESULT_OK_METHOD ) ) . unwrap_or_default ( ) ,
74
+ // Detect `|x| x.ok()`
75
+ ExprKind :: Closure ( Closure { body, .. } ) =>
76
+ if let Body { params : [ param] , value, .. } = cx. tcx . hir ( ) . body ( * body) &&
77
+ let ExprKind :: MethodCall ( method, receiver, [ ] , _) = value. kind &&
78
+ path_to_local_id ( receiver, param. pat . hir_id ) &&
79
+ let Some ( method_did) = cx. typeck_results ( ) . type_dependent_def_id ( value. hir_id )
80
+ {
81
+ is_diag_item_method ( cx, method_did, sym:: Result ) && method. ident . as_str ( ) == "ok"
82
+ } else {
83
+ false
84
+ } ,
85
+ _ => false ,
86
+ }
87
+ } else {
88
+ fm_method_str == "flatten"
89
89
} ;
90
+
90
91
if lint {
91
92
span_lint_and_then (
92
93
cx,
0 commit comments