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