@@ -63,55 +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
- } ;
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
+ } ) ;
79
+ }
80
+ }
81
+ }
92
82
93
- if lint {
94
- span_lint_and_then (
95
- cx ,
96
- LINES_FILTER_MAP_OK ,
97
- fm_span ,
98
- & format ! (
99
- "`{}()` will run forever if the iterator repeatedly produces an `Err`" ,
100
- fm_method . ident
101
- ) ,
102
- |diag| {
103
- diag . span_note (
104
- fm_receiver . span ,
105
- "this expression returning a `std::io::Lines` may produce an infinite number of `Err` in case of a read error" ) ;
106
- diag . span_suggestion (
107
- fm_span ,
108
- "replace with" ,
109
- "map_while(Result::ok)" ,
110
- Applicability :: MaybeIncorrect ,
111
- ) ;
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
112
102
} ,
113
- ) ;
103
+ _ => false ,
114
104
}
115
- }
105
+ } ,
106
+ _ => false ,
116
107
}
117
108
}
0 commit comments