@@ -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 , Param , Body } ;
6
+ use rustc_hir:: { Block , Body , Closure , Expr , ExprKind , FnDecl , HirId , Node , Param , Pat , Path , QPath , Ty } ;
7
7
use rustc_lint:: { LateContext , LateLintPass } ;
8
8
use rustc_session:: declare_lint_pass;
9
9
use rustc_span:: Span ;
@@ -65,11 +65,19 @@ fn then_some_closure_arg<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>) -> Opt
65
65
body,
66
66
..
67
67
} ) => {
68
- if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id ) &&
69
- let Body { params : [ Param { hir_id : arg_id, pat : Pat { span, .. } , .. } ] , .. } =
70
- cx. tcx . hir ( ) . body ( * body)
71
- {
72
-
68
+ if let Node :: Expr ( expr) = cx. tcx . hir_node ( body. hir_id )
69
+ && let Body {
70
+ params :
71
+ [
72
+ Param {
73
+ hir_id : arg_id,
74
+ pat : Pat { span, .. } ,
75
+ ..
76
+ } ,
77
+ ] ,
78
+ ..
79
+ } = cx. tcx . hir ( ) . body ( * body)
80
+ {
73
81
( peel_closure_body ( cx, expr, * arg_id) ) . map ( |body| ( * span, body) )
74
82
} else {
75
83
None
@@ -85,10 +93,12 @@ fn peel_closure_body<'tcx>(
85
93
closure_arg_id : HirId ,
86
94
) -> Option < & ' tcx Expr < ' tcx > > {
87
95
match expr. kind {
88
- ExprKind :: Ret ( Some ( wrapped_expr) ) =>
89
- // duplicated blocks because 2023 reference statements are awkward.
90
- // "&" peels multiple layers of indirection instead of just one like we want.
91
- peel_closure_body ( cx, wrapped_expr, closure_arg_id) ,
96
+ ExprKind :: Ret ( Some ( wrapped_expr) ) =>
97
+ // duplicated blocks because 2023 reference statements are awkward.
98
+ // "&" peels multiple layers of indirection instead of just one like we want.
99
+ {
100
+ peel_closure_body ( cx, wrapped_expr, closure_arg_id)
101
+ } ,
92
102
// it would be nice if we could lift { x; y.a() } into { x; y }.a()
93
103
ExprKind :: Block (
94
104
Block {
@@ -110,13 +120,14 @@ fn peel_closure_body<'tcx>(
110
120
}
111
121
112
122
fn get_pat_hid ( node : Node < ' _ > ) -> Option < HirId > {
113
- match node {
114
- Node :: Param ( Param { pat : Pat { hir_id, .. } , .. } ) |
115
- Node :: Pat ( Pat { hir_id, .. } ) => Some ( * hir_id) ,
116
- _ => {
117
- None
118
- } ,
119
- }
123
+ match node {
124
+ Node :: Param ( Param {
125
+ pat : Pat { hir_id, .. } ,
126
+ ..
127
+ } )
128
+ | Node :: Pat ( Pat { hir_id, .. } ) => Some ( * hir_id) ,
129
+ _ => None ,
130
+ }
120
131
}
121
132
122
133
fn is_local_defined_at ( cx : & LateContext < ' _ > , local : & Expr < ' _ > , arg_hid : HirId ) -> bool {
@@ -128,9 +139,8 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
128
139
..
129
140
} ,
130
141
) ) => {
131
- let local_pat_id = get_pat_hid ( cx. tcx . hir_node ( * local_hid) ) ;
132
- local_pat_id. is_some ( ) &&
133
- local_pat_id == get_pat_hid ( cx. tcx . hir_node ( arg_hid) )
142
+ let local_pat_id = get_pat_hid ( cx. tcx . hir_node ( * local_hid) ) ;
143
+ local_pat_id. is_some ( ) && local_pat_id == get_pat_hid ( cx. tcx . hir_node ( arg_hid) )
134
144
} ,
135
145
// is not local at all, so definitly isn't a local defined at the given position
136
146
_ => false ,
@@ -139,10 +149,10 @@ fn is_local_defined_at(cx: &LateContext<'_>, local: &Expr<'_>, arg_hid: HirId) -
139
149
140
150
fn show_sugg ( cx : & LateContext < ' _ > , span : Span , selfarg : & Expr < ' _ > , closure_args : Span , predicate : & Expr < ' _ > ) {
141
151
let mut appl = Applicability :: MachineApplicable ;
142
- // FIXME: this relies on deref coertion, which won't work correctly if the predicate involves something
143
- // other than a method call. this is because `and_then` takes an argument by
144
- // value, while `filter` takes an argument by reference.
145
-
152
+ // FIXME: this relies on deref coertion, which won't work correctly if the predicate involves
153
+ // something other than a method call. this is because `and_then` takes an argument by
154
+ // value, while `filter` takes an argument by reference.
155
+
146
156
let sugg = format ! (
147
157
"{}.filter(|{}| {})" ,
148
158
snippet_with_applicability( cx, selfarg. span, "<OPTION>" , & mut appl) ,
0 commit comments