@@ -12,6 +12,7 @@ use rustc_middle::hir::map::Map;
12
12
use rustc_span:: Span ;
13
13
14
14
pub ( crate ) struct OptionAndThenSome ;
15
+
15
16
impl BindInsteadOfMap for OptionAndThenSome {
16
17
const TYPE_NAME : & ' static str = "Option" ;
17
18
const TYPE_QPATH : & ' static [ & ' static str ] = & paths:: OPTION ;
@@ -24,6 +25,7 @@ impl BindInsteadOfMap for OptionAndThenSome {
24
25
}
25
26
26
27
pub ( crate ) struct ResultAndThenOk ;
28
+
27
29
impl BindInsteadOfMap for ResultAndThenOk {
28
30
const TYPE_NAME : & ' static str = "Result" ;
29
31
const TYPE_QPATH : & ' static [ & ' static str ] = & paths:: RESULT ;
@@ -36,6 +38,7 @@ impl BindInsteadOfMap for ResultAndThenOk {
36
38
}
37
39
38
40
pub ( crate ) struct ResultOrElseErrInfo ;
41
+
39
42
impl BindInsteadOfMap for ResultOrElseErrInfo {
40
43
const TYPE_NAME : & ' static str = "Result" ;
41
44
const TYPE_QPATH : & ' static [ & ' static str ] = & paths:: RESULT ;
@@ -57,6 +60,10 @@ pub(crate) trait BindInsteadOfMap {
57
60
58
61
const GOOD_METHOD_NAME : & ' static str ;
59
62
63
+ fn is_applicable ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , args : & [ hir:: Expr < ' _ > ] , dry_run : bool ) -> bool {
64
+ Self :: lint ( cx, expr, args, dry_run)
65
+ }
66
+
60
67
fn no_op_msg ( ) -> String {
61
68
format ! (
62
69
"using `{}.{}({})`, which is a no-op" ,
@@ -82,6 +89,7 @@ pub(crate) trait BindInsteadOfMap {
82
89
args : & [ hir:: Expr < ' _ > ] ,
83
90
closure_expr : & hir:: Expr < ' _ > ,
84
91
closure_args_span : Span ,
92
+ dry_run : bool ,
85
93
) -> bool {
86
94
if_chain ! {
87
95
if let hir:: ExprKind :: Call ( ref some_expr, ref some_args) = closure_expr. kind;
@@ -104,6 +112,7 @@ pub(crate) trait BindInsteadOfMap {
104
112
let closure_args_snip = snippet( cx, closure_args_span, ".." ) ;
105
113
let option_snip = snippet( cx, args[ 0 ] . span, ".." ) ;
106
114
let note = format!( "{}.{}({} {})" , option_snip, Self :: GOOD_METHOD_NAME , closure_args_snip, some_inner_snip) ;
115
+ if !dry_run{
107
116
span_lint_and_sugg(
108
117
cx,
109
118
BIND_INSTEAD_OF_MAP ,
@@ -113,16 +122,17 @@ pub(crate) trait BindInsteadOfMap {
113
122
note,
114
123
Applicability :: MachineApplicable ,
115
124
) ;
125
+ }
116
126
true
117
127
} else {
118
128
false
119
129
}
120
130
}
121
131
}
122
132
123
- fn lint_closure ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , closure_expr : & hir:: Expr < ' _ > ) {
133
+ fn lint_closure ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , closure_expr : & hir:: Expr < ' _ > , dry_run : bool ) -> bool {
124
134
let mut suggs = Vec :: new ( ) ;
125
- let can_sugg = find_all_ret_expressions ( cx, closure_expr, |ret_expr| {
135
+ let can_sugg: bool = find_all_ret_expressions ( cx, closure_expr, |ret_expr| {
126
136
if_chain ! {
127
137
if !in_macro( ret_expr. span) ;
128
138
if let hir:: ExprKind :: Call ( ref func_path, ref args) = ret_expr. kind;
@@ -139,7 +149,7 @@ pub(crate) trait BindInsteadOfMap {
139
149
}
140
150
} ) ;
141
151
142
- if can_sugg {
152
+ if can_sugg && !dry_run {
143
153
span_lint_and_then ( cx, BIND_INSTEAD_OF_MAP , expr. span , Self :: lint_msg ( ) . as_ref ( ) , |diag| {
144
154
multispan_sugg_with_applicability (
145
155
diag,
@@ -153,36 +163,42 @@ pub(crate) trait BindInsteadOfMap {
153
163
)
154
164
} ) ;
155
165
}
166
+ can_sugg
156
167
}
157
168
158
169
/// Lint use of `_.and_then(|x| Some(y))` for `Option`s
159
- fn lint ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , args : & [ hir:: Expr < ' _ > ] ) {
170
+ fn lint ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , args : & [ hir:: Expr < ' _ > ] , dry_run : bool ) -> bool {
160
171
if !match_type ( cx, cx. typeck_results ( ) . expr_ty ( & args[ 0 ] ) , Self :: TYPE_QPATH ) {
161
- return ;
172
+ return false ;
162
173
}
163
174
164
175
match args[ 1 ] . kind {
165
176
hir:: ExprKind :: Closure ( _, _, body_id, closure_args_span, _) => {
166
177
let closure_body = cx. tcx . hir ( ) . body ( body_id) ;
167
178
let closure_expr = remove_blocks ( & closure_body. value ) ;
168
179
169
- if !Self :: lint_closure_autofixable ( cx, expr, args, closure_expr, closure_args_span) {
170
- Self :: lint_closure ( cx, expr, closure_expr) ;
180
+ if Self :: lint_closure_autofixable ( cx, expr, args, closure_expr, closure_args_span, dry_run) {
181
+ true
182
+ } else {
183
+ Self :: lint_closure ( cx, expr, closure_expr, dry_run)
171
184
}
172
185
} ,
173
186
// `_.and_then(Some)` case, which is no-op.
174
187
hir:: ExprKind :: Path ( ref qpath) if match_qpath ( qpath, Self :: BAD_VARIANT_QPATH ) => {
175
- span_lint_and_sugg (
176
- cx,
177
- BIND_INSTEAD_OF_MAP ,
178
- expr. span ,
179
- Self :: no_op_msg ( ) . as_ref ( ) ,
180
- "use the expression directly" ,
181
- snippet ( cx, args[ 0 ] . span , ".." ) . into ( ) ,
182
- Applicability :: MachineApplicable ,
183
- ) ;
188
+ if !dry_run {
189
+ span_lint_and_sugg (
190
+ cx,
191
+ BIND_INSTEAD_OF_MAP ,
192
+ expr. span ,
193
+ Self :: no_op_msg ( ) . as_ref ( ) ,
194
+ "use the expression directly" ,
195
+ snippet ( cx, args[ 0 ] . span , ".." ) . into ( ) ,
196
+ Applicability :: MachineApplicable ,
197
+ ) ;
198
+ }
199
+ true
184
200
} ,
185
- _ => { } ,
201
+ _ => false ,
186
202
}
187
203
}
188
204
}
0 commit comments