@@ -10,59 +10,80 @@ use rustc_hir::{LangItem, QPath};
10
10
use rustc_lint:: LateContext ;
11
11
use rustc_span:: Span ;
12
12
13
- pub ( crate ) struct OptionAndThenSome ;
14
-
15
- impl BindInsteadOfMap for OptionAndThenSome {
16
- const VARIANT_LANG_ITEM : LangItem = LangItem :: OptionSome ;
17
- const BAD_METHOD_NAME : & ' static str = "and_then" ;
18
- const GOOD_METHOD_NAME : & ' static str = "map" ;
13
+ pub ( super ) fn check_and_then_some (
14
+ cx : & LateContext < ' _ > ,
15
+ expr : & hir:: Expr < ' _ > ,
16
+ recv : & hir:: Expr < ' _ > ,
17
+ arg : & hir:: Expr < ' _ > ,
18
+ ) -> bool {
19
+ BindInsteadOfMap {
20
+ variant_lang_item : LangItem :: OptionSome ,
21
+ bad_method_name : "and_then" ,
22
+ good_method_name : "map" ,
23
+ }
24
+ . check ( cx, expr, recv, arg)
19
25
}
20
26
21
- pub ( crate ) struct ResultAndThenOk ;
22
-
23
- impl BindInsteadOfMap for ResultAndThenOk {
24
- const VARIANT_LANG_ITEM : LangItem = LangItem :: ResultOk ;
25
- const BAD_METHOD_NAME : & ' static str = "and_then" ;
26
- const GOOD_METHOD_NAME : & ' static str = "map" ;
27
+ pub ( super ) fn check_and_then_ok (
28
+ cx : & LateContext < ' _ > ,
29
+ expr : & hir:: Expr < ' _ > ,
30
+ recv : & hir:: Expr < ' _ > ,
31
+ arg : & hir:: Expr < ' _ > ,
32
+ ) -> bool {
33
+ BindInsteadOfMap {
34
+ variant_lang_item : LangItem :: ResultOk ,
35
+ bad_method_name : "and_then" ,
36
+ good_method_name : "map" ,
37
+ }
38
+ . check ( cx, expr, recv, arg)
27
39
}
28
40
29
- pub ( crate ) struct ResultOrElseErrInfo ;
30
-
31
- impl BindInsteadOfMap for ResultOrElseErrInfo {
32
- const VARIANT_LANG_ITEM : LangItem = LangItem :: ResultErr ;
33
- const BAD_METHOD_NAME : & ' static str = "or_else" ;
34
- const GOOD_METHOD_NAME : & ' static str = "map_err" ;
41
+ pub ( super ) fn check_or_else_err (
42
+ cx : & LateContext < ' _ > ,
43
+ expr : & hir:: Expr < ' _ > ,
44
+ recv : & hir:: Expr < ' _ > ,
45
+ arg : & hir:: Expr < ' _ > ,
46
+ ) -> bool {
47
+ BindInsteadOfMap {
48
+ variant_lang_item : LangItem :: ResultErr ,
49
+ bad_method_name : "or_else" ,
50
+ good_method_name : "map_err" ,
51
+ }
52
+ . check ( cx, expr, recv, arg)
35
53
}
36
54
37
- pub ( crate ) trait BindInsteadOfMap {
38
- const VARIANT_LANG_ITEM : LangItem ;
39
- const BAD_METHOD_NAME : & ' static str ;
40
- const GOOD_METHOD_NAME : & ' static str ;
55
+ struct BindInsteadOfMap {
56
+ variant_lang_item : LangItem ,
57
+ bad_method_name : & ' static str ,
58
+ good_method_name : & ' static str ,
59
+ }
41
60
42
- fn no_op_msg ( cx : & LateContext < ' _ > ) -> Option < String > {
43
- let variant_id = cx. tcx . lang_items ( ) . get ( Self :: VARIANT_LANG_ITEM ) ?;
61
+ impl BindInsteadOfMap {
62
+ fn no_op_msg ( & self , cx : & LateContext < ' _ > ) -> Option < String > {
63
+ let variant_id = cx. tcx . lang_items ( ) . get ( self . variant_lang_item ) ?;
44
64
let item_id = cx. tcx . parent ( variant_id) ;
45
65
Some ( format ! (
46
66
"using `{}.{}({})`, which is a no-op" ,
47
67
cx. tcx. item_name( item_id) ,
48
- Self :: BAD_METHOD_NAME ,
68
+ self . bad_method_name ,
49
69
cx. tcx. item_name( variant_id) ,
50
70
) )
51
71
}
52
72
53
- fn lint_msg ( cx : & LateContext < ' _ > ) -> Option < String > {
54
- let variant_id = cx. tcx . lang_items ( ) . get ( Self :: VARIANT_LANG_ITEM ) ?;
73
+ fn lint_msg ( & self , cx : & LateContext < ' _ > ) -> Option < String > {
74
+ let variant_id = cx. tcx . lang_items ( ) . get ( self . variant_lang_item ) ?;
55
75
let item_id = cx. tcx . parent ( variant_id) ;
56
76
Some ( format ! (
57
77
"using `{}.{}(|x| {}(y))`, which is more succinctly expressed as `{}(|x| y)`" ,
58
78
cx. tcx. item_name( item_id) ,
59
- Self :: BAD_METHOD_NAME ,
79
+ self . bad_method_name ,
60
80
cx. tcx. item_name( variant_id) ,
61
- Self :: GOOD_METHOD_NAME
81
+ self . good_method_name ,
62
82
) )
63
83
}
64
84
65
85
fn lint_closure_autofixable (
86
+ & self ,
66
87
cx : & LateContext < ' _ > ,
67
88
expr : & hir:: Expr < ' _ > ,
68
89
recv : & hir:: Expr < ' _ > ,
@@ -71,9 +92,9 @@ pub(crate) trait BindInsteadOfMap {
71
92
) -> bool {
72
93
if let hir:: ExprKind :: Call ( some_expr, [ inner_expr] ) = closure_expr. kind
73
94
&& let hir:: ExprKind :: Path ( QPath :: Resolved ( _, path) ) = some_expr. kind
74
- && Self :: is_variant ( cx, path. res )
95
+ && self . is_variant ( cx, path. res )
75
96
&& !contains_return ( inner_expr)
76
- && let Some ( msg) = Self :: lint_msg ( cx)
97
+ && let Some ( msg) = self . lint_msg ( cx)
77
98
{
78
99
let mut app = Applicability :: MachineApplicable ;
79
100
let some_inner_snip = snippet_with_context ( cx, inner_expr. span , closure_expr. span . ctxt ( ) , "_" , & mut app) . 0 ;
@@ -82,7 +103,7 @@ pub(crate) trait BindInsteadOfMap {
82
103
let option_snip = snippet ( cx, recv. span , ".." ) ;
83
104
let note = format ! (
84
105
"{option_snip}.{}({closure_args_snip} {some_inner_snip})" ,
85
- Self :: GOOD_METHOD_NAME
106
+ self . good_method_name
86
107
) ;
87
108
span_lint_and_sugg ( cx, BIND_INSTEAD_OF_MAP , expr. span , msg, "try" , note, app) ;
88
109
true
@@ -91,13 +112,13 @@ pub(crate) trait BindInsteadOfMap {
91
112
}
92
113
}
93
114
94
- fn lint_closure ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , closure_expr : & hir:: Expr < ' _ > ) -> bool {
115
+ fn lint_closure ( & self , cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , closure_expr : & hir:: Expr < ' _ > ) -> bool {
95
116
let mut suggs = Vec :: new ( ) ;
96
117
let can_sugg: bool = find_all_ret_expressions ( cx, closure_expr, |ret_expr| {
97
118
if !ret_expr. span . from_expansion ( )
98
119
&& let hir:: ExprKind :: Call ( func_path, [ arg] ) = ret_expr. kind
99
120
&& let hir:: ExprKind :: Path ( QPath :: Resolved ( _, path) ) = func_path. kind
100
- && Self :: is_variant ( cx, path. res )
121
+ && self . is_variant ( cx, path. res )
101
122
&& !contains_return ( arg)
102
123
{
103
124
suggs. push ( ( ret_expr. span , arg. span . source_callsite ( ) ) ) ;
@@ -108,7 +129,7 @@ pub(crate) trait BindInsteadOfMap {
108
129
} ) ;
109
130
let ( span, msg) = if can_sugg
110
131
&& let hir:: ExprKind :: MethodCall ( segment, ..) = expr. kind
111
- && let Some ( msg) = Self :: lint_msg ( cx)
132
+ && let Some ( msg) = self . lint_msg ( cx)
112
133
{
113
134
( segment. ident . span , msg)
114
135
} else {
@@ -119,7 +140,7 @@ pub(crate) trait BindInsteadOfMap {
119
140
diag,
120
141
"try" ,
121
142
Applicability :: MachineApplicable ,
122
- std:: iter:: once ( ( span, Self :: GOOD_METHOD_NAME . into ( ) ) ) . chain (
143
+ std:: iter:: once ( ( span, self . good_method_name . into ( ) ) ) . chain (
123
144
suggs
124
145
. into_iter ( )
125
146
. map ( |( span1, span2) | ( span1, snippet ( cx, span2, "_" ) . into ( ) ) ) ,
@@ -130,9 +151,9 @@ pub(crate) trait BindInsteadOfMap {
130
151
}
131
152
132
153
/// Lint use of `_.and_then(|x| Some(y))` for `Option`s
133
- fn check ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , recv : & hir:: Expr < ' _ > , arg : & hir:: Expr < ' _ > ) -> bool {
154
+ fn check ( & self , cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , recv : & hir:: Expr < ' _ > , arg : & hir:: Expr < ' _ > ) -> bool {
134
155
if let Some ( adt) = cx. typeck_results ( ) . expr_ty ( recv) . ty_adt_def ( )
135
- && let Some ( vid) = cx. tcx . lang_items ( ) . get ( Self :: VARIANT_LANG_ITEM )
156
+ && let Some ( vid) = cx. tcx . lang_items ( ) . get ( self . variant_lang_item )
136
157
&& adt. did ( ) == cx. tcx . parent ( vid)
137
158
{
138
159
} else {
@@ -144,15 +165,15 @@ pub(crate) trait BindInsteadOfMap {
144
165
let closure_body = cx. tcx . hir ( ) . body ( body) ;
145
166
let closure_expr = peel_blocks ( closure_body. value ) ;
146
167
147
- if Self :: lint_closure_autofixable ( cx, expr, recv, closure_expr, fn_decl_span) {
168
+ if self . lint_closure_autofixable ( cx, expr, recv, closure_expr, fn_decl_span) {
148
169
true
149
170
} else {
150
- Self :: lint_closure ( cx, expr, closure_expr)
171
+ self . lint_closure ( cx, expr, closure_expr)
151
172
}
152
173
} ,
153
174
// `_.and_then(Some)` case, which is no-op.
154
- hir:: ExprKind :: Path ( QPath :: Resolved ( _, path) ) if Self :: is_variant ( cx, path. res ) => {
155
- if let Some ( msg) = Self :: no_op_msg ( cx) {
175
+ hir:: ExprKind :: Path ( QPath :: Resolved ( _, path) ) if self . is_variant ( cx, path. res ) => {
176
+ if let Some ( msg) = self . no_op_msg ( cx) {
156
177
span_lint_and_sugg (
157
178
cx,
158
179
BIND_INSTEAD_OF_MAP ,
@@ -169,9 +190,9 @@ pub(crate) trait BindInsteadOfMap {
169
190
}
170
191
}
171
192
172
- fn is_variant ( cx : & LateContext < ' _ > , res : Res ) -> bool {
193
+ fn is_variant ( & self , cx : & LateContext < ' _ > , res : Res ) -> bool {
173
194
if let Res :: Def ( DefKind :: Ctor ( CtorOf :: Variant , CtorKind :: Fn ) , id) = res {
174
- if let Some ( variant_id) = cx. tcx . lang_items ( ) . get ( Self :: VARIANT_LANG_ITEM ) {
195
+ if let Some ( variant_id) = cx. tcx . lang_items ( ) . get ( self . variant_lang_item ) {
175
196
return cx. tcx . parent ( id) == variant_id;
176
197
}
177
198
}
0 commit comments