@@ -63,45 +63,46 @@ impl LateLintPass<'_> for LinesFilterMapOk {
63
63
is_trait_method ( cx, expr, sym:: Iterator ) &&
64
64
let fm_method_str = fm_method. ident . as_str ( ) &&
65
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
+ is_type_diagnostic_item ( cx, cx. typeck_results ( ) . expr_ty_adjusted ( fm_receiver) , sym:: IoLines ) &&
67
+ should_lint ( cx, fm_args, fm_method_str)
67
68
{
68
- let lint = match fm_args {
69
- [ ] => fm_method_str == "flatten" ,
70
- [ fm_arg] => {
71
- match & fm_arg. kind {
72
- // Detect `Result::ok`
73
- ExprKind :: Path ( qpath) =>
74
- cx. qpath_res ( qpath, fm_arg. hir_id ) . opt_def_id ( ) . map ( |did|
75
- match_def_path ( cx, did, & paths:: CORE_RESULT_OK_METHOD ) ) . unwrap_or_default ( ) ,
76
- // Detect `|x| x.ok()`
77
- ExprKind :: Closure ( Closure { body, .. } ) =>
78
- if let Body { params : [ param] , value, .. } = 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
- _ => false ,
88
- }
89
- }
90
- _ => false ,
91
- } ;
92
-
93
- if lint {
94
- span_lint_and_then ( cx,
95
- LINES_FILTER_MAP_OK ,
96
- fm_span,
97
- & format ! ( "`{}()` will run forever if the iterator repeatedly produces an `Err`" , fm_method. ident) ,
98
- |diag| {
99
- diag. span_note (
100
- fm_receiver. span ,
101
- "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error" ) ;
102
- diag. span_suggestion ( fm_span, "replace with" , "map_while(Result::ok)" , Applicability :: MaybeIncorrect ) ;
103
- } ) ;
104
- }
69
+ span_lint_and_then ( cx,
70
+ LINES_FILTER_MAP_OK ,
71
+ fm_span,
72
+ & format ! ( "`{}()` will run forever if the iterator repeatedly produces an `Err`" , fm_method. ident) ,
73
+ |diag| {
74
+ diag. span_note (
75
+ fm_receiver. span ,
76
+ "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error" ) ;
77
+ diag. span_suggestion ( fm_span, "replace with" , "map_while(Result::ok)" , Applicability :: MaybeIncorrect ) ;
78
+ } ) ;
105
79
}
106
80
}
107
81
}
82
+
83
+ fn should_lint ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] , method_str : & str ) -> bool {
84
+ match args {
85
+ [ ] => method_str == "flatten" ,
86
+ [ fm_arg] => {
87
+ match & fm_arg. kind {
88
+ // Detect `Result::ok`
89
+ ExprKind :: Path ( qpath) =>
90
+ cx. qpath_res ( qpath, fm_arg. hir_id ) . opt_def_id ( ) . map ( |did|
91
+ match_def_path ( cx, did, & paths:: CORE_RESULT_OK_METHOD ) ) . unwrap_or_default ( ) ,
92
+ // Detect `|x| x.ok()`
93
+ ExprKind :: Closure ( Closure { body, .. } ) =>
94
+ if let Body { params : [ param] , value, .. } = cx. tcx . hir ( ) . body ( * body) &&
95
+ let ExprKind :: MethodCall ( method, receiver, [ ] , _) = value. kind &&
96
+ path_to_local_id ( receiver, param. pat . hir_id ) &&
97
+ let Some ( method_did) = cx. typeck_results ( ) . type_dependent_def_id ( value. hir_id )
98
+ {
99
+ is_diag_item_method ( cx, method_did, sym:: Result ) && method. ident . as_str ( ) == "ok"
100
+ } else {
101
+ false
102
+ } ,
103
+ _ => false ,
104
+ }
105
+ } ,
106
+ _ => false ,
107
+ }
108
+ }
0 commit comments