@@ -2,11 +2,11 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lin
2
2
use clippy_utils:: msrvs:: { self , Msrv } ;
3
3
use clippy_utils:: source:: { snippet, snippet_with_applicability} ;
4
4
use clippy_utils:: ty:: is_non_aggregate_primitive_type;
5
- use clippy_utils:: { is_default_equivalent, is_res_lang_ctor, path_res} ;
5
+ use clippy_utils:: { is_default_equivalent, is_res_lang_ctor, path_res, peel_ref_operators } ;
6
6
use if_chain:: if_chain;
7
7
use rustc_errors:: Applicability ;
8
8
use rustc_hir:: LangItem :: OptionNone ;
9
- use rustc_hir:: { BorrowKind , Expr , ExprKind , Mutability , QPath } ;
9
+ use rustc_hir:: { Expr , ExprKind } ;
10
10
use rustc_lint:: { LateContext , LateLintPass } ;
11
11
use rustc_middle:: lint:: in_external_macro;
12
12
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
@@ -101,40 +101,26 @@ declare_clippy_lint! {
101
101
impl_lint_pass ! ( MemReplace =>
102
102
[ MEM_REPLACE_OPTION_WITH_NONE , MEM_REPLACE_WITH_UNINIT , MEM_REPLACE_WITH_DEFAULT ] ) ;
103
103
104
- fn check_replace_option_with_none ( cx : & LateContext < ' _ > , src : & Expr < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
105
- // Check that second argument is `Option::None`
106
- if is_res_lang_ctor ( cx, path_res ( cx, src) , OptionNone ) {
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
- // replacee's path.
112
- let replaced_path = match dest. kind {
113
- ExprKind :: AddrOf ( BorrowKind :: Ref , Mutability :: Mut , replaced) => {
114
- if let ExprKind :: Path ( QPath :: Resolved ( None , replaced_path) ) = replaced. kind {
115
- replaced_path
116
- } else {
117
- return ;
118
- }
119
- } ,
120
- ExprKind :: Path ( QPath :: Resolved ( None , replaced_path) ) => replaced_path,
121
- _ => return ,
122
- } ;
123
-
124
- let mut applicability = Applicability :: MachineApplicable ;
125
- span_lint_and_sugg (
126
- cx,
127
- MEM_REPLACE_OPTION_WITH_NONE ,
128
- expr_span,
129
- "replacing an `Option` with `None`" ,
130
- "consider `Option::take()` instead" ,
131
- format ! (
132
- "{}.take()" ,
133
- snippet_with_applicability( cx, replaced_path. span, "" , & mut applicability)
134
- ) ,
135
- applicability,
136
- ) ;
137
- }
104
+ fn check_replace_option_with_none ( cx : & LateContext < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
105
+ // Since this is a late pass (already type-checked),
106
+ // and we already know that the second argument is an
107
+ // `Option`, we do not need to check the first
108
+ // argument's type. All that's left is to get
109
+ // the span to replacee's expr after peeling off the `&mut`
110
+ let sugg_expr_span = peel_ref_operators ( cx, dest) . span ;
111
+ let mut applicability = Applicability :: MachineApplicable ;
112
+ span_lint_and_sugg (
113
+ cx,
114
+ MEM_REPLACE_OPTION_WITH_NONE ,
115
+ expr_span,
116
+ "replacing an `Option` with `None`" ,
117
+ "consider `Option::take()` instead" ,
118
+ format ! (
119
+ "{}.take()" ,
120
+ snippet_with_applicability( cx, sugg_expr_span, "" , & mut applicability)
121
+ ) ,
122
+ applicability,
123
+ ) ;
138
124
}
139
125
140
126
fn check_replace_with_uninit ( cx : & LateContext < ' _ > , src : & Expr < ' _ > , dest : & Expr < ' _ > , expr_span : Span ) {
@@ -200,10 +186,6 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
200
186
if is_non_aggregate_primitive_type ( expr_type) {
201
187
return ;
202
188
}
203
- // disable lint for Option since it is covered in another lint
204
- if is_res_lang_ctor ( cx, path_res ( cx, src) , OptionNone ) {
205
- return ;
206
- }
207
189
if is_default_equivalent ( cx, src) && !in_external_macro ( cx. tcx . sess , expr_span) {
208
190
span_lint_and_then (
209
191
cx,
@@ -246,11 +228,13 @@ impl<'tcx> LateLintPass<'tcx> for MemReplace {
246
228
if let Some ( def_id) = cx. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
247
229
if cx. tcx. is_diagnostic_item( sym:: mem_replace, def_id) ;
248
230
then {
249
- check_replace_option_with_none( cx, src, dest, expr. span) ;
250
- check_replace_with_uninit( cx, src, dest, expr. span) ;
251
- if self . msrv. meets( msrvs:: MEM_TAKE ) {
231
+ // Check that second argument is `Option::None`
232
+ if is_res_lang_ctor( cx, path_res( cx, src) , OptionNone ) {
233
+ check_replace_option_with_none( cx, dest, expr. span) ;
234
+ } else if self . msrv. meets( msrvs:: MEM_TAKE ) {
252
235
check_replace_with_default( cx, src, dest, expr. span) ;
253
236
}
237
+ check_replace_with_uninit( cx, src, dest, expr. span) ;
254
238
}
255
239
}
256
240
}
0 commit comments