@@ -103,26 +103,31 @@ declare_clippy_lint! {
103
103
impl_lint_pass ! ( MemReplace =>
104
104
[ MEM_REPLACE_OPTION_WITH_NONE , MEM_REPLACE_WITH_UNINIT , MEM_REPLACE_WITH_DEFAULT ] ) ;
105
105
106
- fn check_replace_option_with_none ( cx : & LateContext < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
107
- // Since this is a late pass (already type-checked),
108
- // and we already know that the second argument is an
109
- // `Option`, we do not need to check the first
110
- // argument's type. All that's left is to get
111
- // the replacee's expr after peeling off the `&mut`
112
- let sugg_expr = peel_ref_operators ( cx, dest) ;
113
- let mut applicability = Applicability :: MachineApplicable ;
114
- span_lint_and_sugg (
115
- cx,
116
- MEM_REPLACE_OPTION_WITH_NONE ,
117
- expr_span,
118
- "replacing an `Option` with `None`" ,
119
- "consider `Option::take()` instead" ,
120
- format ! (
121
- "{}.take()" ,
122
- Sugg :: hir_with_context( cx, sugg_expr, expr_span. ctxt( ) , "" , & mut applicability) . maybe_par( )
123
- ) ,
124
- applicability,
125
- ) ;
106
+ fn check_replace_option_with_none ( cx : & LateContext < ' _ > , src : & Expr < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) -> bool {
107
+ if is_res_lang_ctor ( cx, path_res ( cx, src) , OptionNone ) {
108
+ // Since this is a late pass (already type-checked),
109
+ // and we already know that the second argument is an
110
+ // `Option`, we do not need to check the first
111
+ // argument's type. All that's left is to get
112
+ // the replacee's expr after peeling off the `&mut`
113
+ let sugg_expr = peel_ref_operators ( cx, dest) ;
114
+ let mut applicability = Applicability :: MachineApplicable ;
115
+ span_lint_and_sugg (
116
+ cx,
117
+ MEM_REPLACE_OPTION_WITH_NONE ,
118
+ expr_span,
119
+ "replacing an `Option` with `None`" ,
120
+ "consider `Option::take()` instead" ,
121
+ format ! (
122
+ "{}.take()" ,
123
+ Sugg :: hir_with_context( cx, sugg_expr, expr_span. ctxt( ) , "" , & mut applicability) . maybe_par( )
124
+ ) ,
125
+ applicability,
126
+ ) ;
127
+ true
128
+ } else {
129
+ false
130
+ }
126
131
}
127
132
128
133
fn check_replace_with_uninit ( cx : & LateContext < ' _ > , src : & Expr < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
@@ -181,34 +186,44 @@ fn check_replace_with_uninit(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'
181
186
}
182
187
}
183
188
184
- fn check_replace_with_default ( cx : & LateContext < ' _ > , src : & Expr < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
185
- // disable lint for primitives
186
- let expr_type = cx. typeck_results ( ) . expr_ty_adjusted ( src) ;
187
- if is_non_aggregate_primitive_type ( expr_type) {
188
- return ;
189
- }
190
- if is_default_equivalent ( cx, src) && !expr_span. in_external_macro ( cx. tcx . sess . source_map ( ) ) {
191
- let Some ( top_crate) = std_or_core ( cx) else { return } ;
189
+ fn check_replace_with_default (
190
+ cx : & LateContext < ' _ > ,
191
+ src : & Expr < ' _ > ,
192
+ dest : & Expr < ' _ > ,
193
+ expr : & Expr < ' _ > ,
194
+ msrv : & Msrv ,
195
+ ) -> bool {
196
+ if msrv. meets ( msrvs:: MEM_TAKE ) && is_expr_used_or_unified ( cx. tcx , expr)
197
+ // disable lint for primitives
198
+ && let expr_type = cx. typeck_results ( ) . expr_ty_adjusted ( src)
199
+ && !is_non_aggregate_primitive_type ( expr_type)
200
+ && is_default_equivalent ( cx, src)
201
+ && !expr. span . in_external_macro ( cx. tcx . sess . source_map ( ) )
202
+ && let Some ( top_crate) = std_or_core ( cx)
203
+ {
192
204
span_lint_and_then (
193
205
cx,
194
206
MEM_REPLACE_WITH_DEFAULT ,
195
- expr_span ,
207
+ expr . span ,
196
208
format ! (
197
209
"replacing a value of type `T` with `T::default()` is better expressed using `{top_crate}::mem::take`"
198
210
) ,
199
211
|diag| {
200
- if !expr_span . from_expansion ( ) {
212
+ if !expr . span . from_expansion ( ) {
201
213
let suggestion = format ! ( "{top_crate}::mem::take({})" , snippet( cx, dest. span, "" ) ) ;
202
214
203
215
diag. span_suggestion (
204
- expr_span ,
216
+ expr . span ,
205
217
"consider using" ,
206
218
suggestion,
207
219
Applicability :: MachineApplicable ,
208
220
) ;
209
221
}
210
222
} ,
211
223
) ;
224
+ true
225
+ } else {
226
+ false
212
227
}
213
228
}
214
229
@@ -233,12 +248,11 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
233
248
&& cx. tcx . is_diagnostic_item ( sym:: mem_replace, def_id)
234
249
{
235
250
// Check that second argument is `Option::None`
236
- if is_res_lang_ctor ( cx, path_res ( cx , src ) , OptionNone ) {
237
- check_replace_option_with_none ( cx, dest, expr. span ) ;
238
- } else if self . msrv . meets ( msrvs :: MEM_TAKE ) && is_expr_used_or_unified ( cx . tcx , expr ) {
239
- check_replace_with_default ( cx, src, dest, expr. span ) ;
251
+ if ! check_replace_option_with_none ( cx, src , dest , expr . span )
252
+ && ! check_replace_with_default ( cx, src , dest, expr, & self . msrv )
253
+ {
254
+ check_replace_with_uninit ( cx, src, dest, expr. span ) ;
240
255
}
241
- check_replace_with_uninit ( cx, src, dest, expr. span ) ;
242
256
}
243
257
}
244
258
extract_msrv_attr ! ( LateContext ) ;
0 commit comments