@@ -3,10 +3,11 @@ use crate::utils::{
3
3
} ;
4
4
use if_chain:: if_chain;
5
5
use rustc:: declare_lint_pass;
6
- use rustc:: hir:: { BorrowKind , Expr , ExprKind , HirVec , Mutability , QPath } ;
6
+ use rustc:: hir:: { BorrowKind , Expr , ExprKind , Mutability , QPath } ;
7
7
use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintPass } ;
8
8
use rustc_errors:: Applicability ;
9
9
use rustc_session:: declare_tool_lint;
10
+ use syntax:: source_map:: Span ;
10
11
11
12
declare_clippy_lint ! {
12
13
/// **What it does:** Checks for `mem::replace()` on an `Option` with
@@ -94,16 +95,16 @@ declare_clippy_lint! {
94
95
declare_lint_pass ! ( MemReplace =>
95
96
[ MEM_REPLACE_OPTION_WITH_NONE , MEM_REPLACE_WITH_UNINIT , MEM_REPLACE_WITH_DEFAULT ] ) ;
96
97
97
- fn check_replace_option_with_none ( cx : & LateContext < ' _ , ' _ > , expr : & ' _ Expr , args : & HirVec < Expr > ) {
98
- if let ExprKind :: Path ( ref replacement_qpath) = args [ 1 ] . kind {
98
+ fn check_replace_option_with_none ( cx : & LateContext < ' _ , ' _ > , src : & Expr , dest : & Expr , expr_span : Span ) {
99
+ if let ExprKind :: Path ( ref replacement_qpath) = src . kind {
99
100
// Check that second argument is `Option::None`
100
101
if match_qpath ( replacement_qpath, & paths:: OPTION_NONE ) {
101
102
// Since this is a late pass (already type-checked),
102
103
// and we already know that the second argument is an
103
104
// `Option`, we do not need to check the first
104
105
// argument's type. All that's left is to get
105
106
// replacee's path.
106
- let replaced_path = match args [ 0 ] . kind {
107
+ let replaced_path = match dest . kind {
107
108
ExprKind :: AddrOf ( BorrowKind :: Ref , Mutability :: Mut , ref replaced) => {
108
109
if let ExprKind :: Path ( QPath :: Resolved ( None , ref replaced_path) ) = replaced. kind {
109
110
replaced_path
@@ -119,7 +120,7 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, expr: &'_ Expr, args
119
120
span_lint_and_sugg (
120
121
cx,
121
122
MEM_REPLACE_OPTION_WITH_NONE ,
122
- expr . span ,
123
+ expr_span ,
123
124
"replacing an `Option` with `None`" ,
124
125
"consider `Option::take()` instead" ,
125
126
format ! (
@@ -132,8 +133,8 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, expr: &'_ Expr, args
132
133
}
133
134
}
134
135
135
- fn check_replace_with_uninit ( cx : & LateContext < ' _ , ' _ > , expr : & ' _ Expr , args : & HirVec < Expr > ) {
136
- if let ExprKind :: Call ( ref repl_func, ref repl_args) = args [ 1 ] . kind {
136
+ fn check_replace_with_uninit ( cx : & LateContext < ' _ , ' _ > , src : & Expr , expr_span : Span ) {
137
+ if let ExprKind :: Call ( ref repl_func, ref repl_args) = src . kind {
137
138
if_chain ! {
138
139
if repl_args. is_empty( ) ;
139
140
if let ExprKind :: Path ( ref repl_func_qpath) = repl_func. kind;
@@ -143,16 +144,16 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, expr: &'_ Expr, args: &Hi
143
144
span_help_and_lint(
144
145
cx,
145
146
MEM_REPLACE_WITH_UNINIT ,
146
- expr . span ,
147
+ expr_span ,
147
148
"replacing with `mem::uninitialized()`" ,
148
149
"consider using the `take_mut` crate instead" ,
149
150
) ;
150
151
} else if match_def_path( cx, repl_def_id, & paths:: MEM_ZEROED ) &&
151
- !cx. tables. expr_ty( & args [ 1 ] ) . is_primitive( ) {
152
+ !cx. tables. expr_ty( src ) . is_primitive( ) {
152
153
span_help_and_lint(
153
154
cx,
154
155
MEM_REPLACE_WITH_UNINIT ,
155
- expr . span ,
156
+ expr_span ,
156
157
"replacing with `mem::zeroed()`" ,
157
158
"consider using a default value or the `take_mut` crate instead" ,
158
159
) ;
@@ -162,10 +163,10 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, expr: &'_ Expr, args: &Hi
162
163
}
163
164
}
164
165
165
- fn check_replace_with_default ( cx : & LateContext < ' _ , ' _ > , expr : & ' _ Expr , args : & HirVec < Expr > ) {
166
- if let ExprKind :: Call ( ref repl_func, _) = args [ 1 ] . kind {
166
+ fn check_replace_with_default ( cx : & LateContext < ' _ , ' _ > , src : & Expr , dest : & Expr , expr_span : Span ) {
167
+ if let ExprKind :: Call ( ref repl_func, _) = src . kind {
167
168
if_chain ! {
168
- if !in_macro( expr . span ) && !in_external_macro( cx. tcx. sess, expr . span ) ;
169
+ if !in_macro( expr_span ) && !in_external_macro( cx. tcx. sess, expr_span ) ;
169
170
if let ExprKind :: Path ( ref repl_func_qpath) = repl_func. kind;
170
171
if let Some ( repl_def_id) = cx. tables. qpath_res( repl_func_qpath, repl_func. hir_id) . opt_def_id( ) ;
171
172
if match_def_path( cx, repl_def_id, & paths:: DEFAULT_TRAIT_METHOD ) ;
@@ -175,12 +176,12 @@ fn check_replace_with_default(cx: &LateContext<'_, '_>, expr: &'_ Expr, args: &H
175
176
span_lint_and_sugg(
176
177
cx,
177
178
MEM_REPLACE_WITH_DEFAULT ,
178
- expr . span ,
179
+ expr_span ,
179
180
"replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" ,
180
181
"consider using" ,
181
182
format!(
182
183
"std::mem::take({})" ,
183
- snippet_with_applicability( cx, args [ 0 ] . span, "" , & mut applicability)
184
+ snippet_with_applicability( cx, dest . span, "" , & mut applicability)
184
185
) ,
185
186
applicability,
186
187
) ;
@@ -194,15 +195,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
194
195
if_chain ! {
195
196
// Check that `expr` is a call to `mem::replace()`
196
197
if let ExprKind :: Call ( ref func, ref func_args) = expr. kind;
197
- if func_args. len( ) == 2 ;
198
198
if let ExprKind :: Path ( ref func_qpath) = func. kind;
199
199
if let Some ( def_id) = cx. tables. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
200
200
if match_def_path( cx, def_id, & paths:: MEM_REPLACE ) ;
201
-
201
+ if let [ dest , src ] = & * * func_args ;
202
202
then {
203
- check_replace_option_with_none( cx, expr , & func_args ) ;
204
- check_replace_with_uninit( cx, expr , & func_args ) ;
205
- check_replace_with_default( cx, expr , & func_args ) ;
203
+ check_replace_option_with_none( cx, src , dest , expr . span ) ;
204
+ check_replace_with_uninit( cx, src , expr . span ) ;
205
+ check_replace_with_default( cx, src , dest , expr . span ) ;
206
206
}
207
207
}
208
208
}
0 commit comments