@@ -3,10 +3,11 @@ use crate::utils::{
33} ;
44use if_chain:: if_chain;
55use rustc:: declare_lint_pass;
6- use rustc:: hir:: { BorrowKind , Expr , ExprKind , HirVec , Mutability , QPath } ;
6+ use rustc:: hir:: { BorrowKind , Expr , ExprKind , Mutability , QPath } ;
77use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintPass } ;
88use rustc_errors:: Applicability ;
99use rustc_session:: declare_tool_lint;
10+ use syntax:: source_map:: Span ;
1011
1112declare_clippy_lint ! {
1213 /// **What it does:** Checks for `mem::replace()` on an `Option` with
@@ -94,16 +95,16 @@ declare_clippy_lint! {
9495declare_lint_pass ! ( MemReplace =>
9596 [ MEM_REPLACE_OPTION_WITH_NONE , MEM_REPLACE_WITH_UNINIT , MEM_REPLACE_WITH_DEFAULT ] ) ;
9697
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 {
99100 // Check that second argument is `Option::None`
100101 if match_qpath ( replacement_qpath, & paths:: OPTION_NONE ) {
101102 // Since this is a late pass (already type-checked),
102103 // and we already know that the second argument is an
103104 // `Option`, we do not need to check the first
104105 // argument's type. All that's left is to get
105106 // replacee's path.
106- let replaced_path = match args [ 0 ] . kind {
107+ let replaced_path = match dest . kind {
107108 ExprKind :: AddrOf ( BorrowKind :: Ref , Mutability :: Mut , ref replaced) => {
108109 if let ExprKind :: Path ( QPath :: Resolved ( None , ref replaced_path) ) = replaced. kind {
109110 replaced_path
@@ -119,7 +120,7 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, expr: &'_ Expr, args
119120 span_lint_and_sugg (
120121 cx,
121122 MEM_REPLACE_OPTION_WITH_NONE ,
122- expr . span ,
123+ expr_span ,
123124 "replacing an `Option` with `None`" ,
124125 "consider `Option::take()` instead" ,
125126 format ! (
@@ -132,8 +133,8 @@ fn check_replace_option_with_none(cx: &LateContext<'_, '_>, expr: &'_ Expr, args
132133 }
133134}
134135
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 {
137138 if_chain ! {
138139 if repl_args. is_empty( ) ;
139140 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
143144 span_help_and_lint(
144145 cx,
145146 MEM_REPLACE_WITH_UNINIT ,
146- expr . span ,
147+ expr_span ,
147148 "replacing with `mem::uninitialized()`" ,
148149 "consider using the `take_mut` crate instead" ,
149150 ) ;
150151 } 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( ) {
152153 span_help_and_lint(
153154 cx,
154155 MEM_REPLACE_WITH_UNINIT ,
155- expr . span ,
156+ expr_span ,
156157 "replacing with `mem::zeroed()`" ,
157158 "consider using a default value or the `take_mut` crate instead" ,
158159 ) ;
@@ -162,10 +163,10 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, expr: &'_ Expr, args: &Hi
162163 }
163164}
164165
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 {
167168 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 ) ;
169170 if let ExprKind :: Path ( ref repl_func_qpath) = repl_func. kind;
170171 if let Some ( repl_def_id) = cx. tables. qpath_res( repl_func_qpath, repl_func. hir_id) . opt_def_id( ) ;
171172 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
175176 span_lint_and_sugg(
176177 cx,
177178 MEM_REPLACE_WITH_DEFAULT ,
178- expr . span ,
179+ expr_span ,
179180 "replacing a value of type `T` with `T::default()` is better expressed using `std::mem::take`" ,
180181 "consider using" ,
181182 format!(
182183 "std::mem::take({})" ,
183- snippet_with_applicability( cx, args [ 0 ] . span, "" , & mut applicability)
184+ snippet_with_applicability( cx, dest . span, "" , & mut applicability)
184185 ) ,
185186 applicability,
186187 ) ;
@@ -194,15 +195,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MemReplace {
194195 if_chain ! {
195196 // Check that `expr` is a call to `mem::replace()`
196197 if let ExprKind :: Call ( ref func, ref func_args) = expr. kind;
197- if func_args. len( ) == 2 ;
198198 if let ExprKind :: Path ( ref func_qpath) = func. kind;
199199 if let Some ( def_id) = cx. tables. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
200200 if match_def_path( cx, def_id, & paths:: MEM_REPLACE ) ;
201-
201+ if let [ dest , src ] = & * * func_args ;
202202 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 ) ;
206206 }
207207 }
208208 }
0 commit comments