@@ -3,7 +3,7 @@ use clippy_utils::source::snippet_with_applicability;
3
3
use clippy_utils:: { fn_def_id, match_def_path} ;
4
4
use rustc_errors:: Applicability ;
5
5
use rustc_hir:: def:: Res ;
6
- use rustc_hir:: { Block , Closure , Expr , ExprKind , FnDecl , HirId , Node , Pat , Path , QPath , Ty } ;
6
+ use rustc_hir:: { Block , Closure , Expr , ExprKind , FnDecl , HirId , Node , Pat , Path , QPath , Ty , Param , Body } ;
7
7
use rustc_lint:: { LateContext , LateLintPass } ;
8
8
use rustc_session:: declare_lint_pass;
9
9
use rustc_span:: Span ;
@@ -58,14 +58,18 @@ impl<'tcx> LateLintPass<'tcx> for AndThenThenSome {
58
58
fn then_some_closure_arg < ' tcx > ( cx : & LateContext < ' tcx > , expr : & Expr < ' tcx > ) -> Option < ( Span , & ' tcx Expr < ' tcx > ) > {
59
59
match expr. kind {
60
60
ExprKind :: Closure ( Closure {
61
- fn_decl : FnDecl {
61
+ /* fn_decl: FnDecl {
62
62
inputs: [Ty { hir_id: arg_id, .. }],
63
63
..
64
- } ,
64
+ },*/
65
65
body,
66
66
..
67
67
} ) => {
68
- if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id ) {
68
+ if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id ) &&
69
+ let Body { params : [ Param { hir_id : arg_id, .. } ] , .. } =
70
+ cx. tcx . hir ( ) . body ( * body)
71
+ {
72
+
69
73
( peel_closure_body ( cx, expr, * arg_id) ) . map ( |body| ( cx. tcx . hir ( ) . span ( * arg_id) , body) )
70
74
} else {
71
75
None
@@ -101,6 +105,16 @@ fn peel_closure_body<'tcx>(
101
105
}
102
106
}
103
107
108
+ fn get_pat_hid ( node : Node < ' _ > ) -> Option < HirId > {
109
+ match node {
110
+ Node :: Param ( Param { pat : Pat { hir_id, .. } , .. } ) |
111
+ Node :: Pat ( Pat { hir_id, .. } ) => Some ( * hir_id) ,
112
+ _ => {
113
+ None
114
+ } ,
115
+ }
116
+ }
117
+
104
118
fn is_local_defined_at ( cx : & LateContext < ' _ > , local : & Expr < ' _ > , arg_hid : HirId ) -> bool {
105
119
match local. kind {
106
120
ExprKind :: Path ( QPath :: Resolved (
@@ -110,19 +124,9 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
110
124
..
111
125
} ,
112
126
) ) => {
113
- // FIXME: this is the best way i could find to compare if
114
- // a local refers to a specific closure argument.
115
- //
116
- // it breaks if the closure argument has an explicitly declared type,
117
- // since the spans only align for TyKind::Infer
118
- if let Node :: Pat ( Pat { span : local_span, .. } ) = ( cx. tcx . hir_node ( * local_hid) )
119
- && let Node :: Ty ( Ty { span : arg_span, .. } ) = ( cx. tcx . hir_node ( arg_hid) )
120
- && local_span == arg_span
121
- {
122
- true
123
- } else {
124
- false
125
- }
127
+ let local_pat_id = get_pat_hid ( cx. tcx . hir_node ( * local_hid) ) ;
128
+ local_pat_id. is_some ( ) &&
129
+ local_pat_id == get_pat_hid ( cx. tcx . hir_node ( arg_hid) )
126
130
} ,
127
131
// is not local at all, so definitly isn't a local defined at the given position
128
132
_ => false ,
@@ -132,7 +136,7 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
132
136
fn show_sugg ( cx : & LateContext < ' _ > , span : Span , selfarg : & Expr < ' _ > , closure_args : Span , predicate : & Expr < ' _ > ) {
133
137
let mut appl = Applicability :: MachineApplicable ;
134
138
let sugg = format ! (
135
- "{}.filter(|{}| {})" ,
139
+ "{}.filter(|& {}| {})" ,
136
140
snippet_with_applicability( cx, selfarg. span, "<OPTION>" , & mut appl) ,
137
141
snippet_with_applicability( cx, closure_args, "<ARGS>" , & mut appl) ,
138
142
snippet_with_applicability( cx, predicate. span, "<PREDICATE>" , & mut appl)
0 commit comments