@@ -59,59 +59,65 @@ declare_lint_pass!(LinesFilterMapOk => [LINES_FILTER_MAP_OK]);
5959
6060impl LateLintPass < ' _ > for LinesFilterMapOk {
6161 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)
6768 {
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
88116 }
89- }
117+ } ,
90118 _ => 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- ) ;
114119 }
115- }
120+ } ,
121+ _ => false ,
116122 }
117123}
0 commit comments