@@ -11,7 +11,7 @@ use rustc_hir::Path;
11
11
use rustc_hir:: QPath ;
12
12
use rustc_lint:: LateContext ;
13
13
use rustc_middle:: query:: Key ;
14
- use rustc_middle:: ty:: Ty ;
14
+ use rustc_middle:: ty;
15
15
use rustc_span:: sym;
16
16
use rustc_span:: Symbol ;
17
17
@@ -21,7 +21,7 @@ use rustc_span::Symbol;
21
21
/// ^^^^^^^^^ ^^^^^^ true
22
22
/// `vec![1,2].drain(..).collect::<HashSet<_>>()`
23
23
/// ^^^^^^^^^ ^^^^^^^^^^ false
24
- fn types_match_diagnostic_item ( cx : & LateContext < ' _ > , expr : Ty < ' _ > , recv : Ty < ' _ > , sym : Symbol ) -> bool {
24
+ fn types_match_diagnostic_item ( cx : & LateContext < ' _ > , expr : ty :: Ty < ' _ > , recv : ty :: Ty < ' _ > , sym : Symbol ) -> bool {
25
25
if let Some ( expr_adt_did) = expr. ty_adt_id ( )
26
26
&& let Some ( recv_adt_did) = recv. ty_adt_id ( )
27
27
{
@@ -32,21 +32,33 @@ fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>,
32
32
}
33
33
34
34
/// Checks `std::{vec::Vec, collections::VecDeque}`.
35
- fn check_vec ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] , expr : Ty < ' _ > , recv : Ty < ' _ > , recv_path : & Path < ' _ > ) -> bool {
35
+ fn check_vec (
36
+ cx : & LateContext < ' _ > ,
37
+ args : & [ Expr < ' _ > ] ,
38
+ expr : ty:: Ty < ' _ > ,
39
+ recv : ty:: Ty < ' _ > ,
40
+ recv_path : & Path < ' _ > ,
41
+ ) -> bool {
36
42
( types_match_diagnostic_item ( cx, expr, recv, sym:: Vec )
37
43
|| types_match_diagnostic_item ( cx, expr, recv, sym:: VecDeque ) )
38
44
&& matches ! ( args, [ arg] if is_range_full( cx, arg, Some ( recv_path) ) )
39
45
}
40
46
41
47
/// Checks `std::string::String`
42
- fn check_string ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] , expr : Ty < ' _ > , recv : Ty < ' _ > , recv_path : & Path < ' _ > ) -> bool {
48
+ fn check_string (
49
+ cx : & LateContext < ' _ > ,
50
+ args : & [ Expr < ' _ > ] ,
51
+ expr : ty:: Ty < ' _ > ,
52
+ recv : ty:: Ty < ' _ > ,
53
+ recv_path : & Path < ' _ > ,
54
+ ) -> bool {
43
55
is_type_lang_item ( cx, expr, LangItem :: String )
44
56
&& is_type_lang_item ( cx, recv, LangItem :: String )
45
57
&& matches ! ( args, [ arg] if is_range_full( cx, arg, Some ( recv_path) ) )
46
58
}
47
59
48
60
/// Checks `std::collections::{HashSet, HashMap, BinaryHeap}`.
49
- fn check_collections ( cx : & LateContext < ' _ > , expr : Ty < ' _ > , recv : Ty < ' _ > ) -> Option < & ' static str > {
61
+ fn check_collections ( cx : & LateContext < ' _ > , expr : ty :: Ty < ' _ > , recv : ty :: Ty < ' _ > ) -> Option < & ' static str > {
50
62
types_match_diagnostic_item ( cx, expr, recv, sym:: HashSet )
51
63
. then_some ( "HashSet" )
52
64
. or_else ( || types_match_diagnostic_item ( cx, expr, recv, sym:: HashMap ) . then_some ( "HashMap" ) )
@@ -55,13 +67,14 @@ fn check_collections(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>) -> Option
55
67
56
68
pub ( super ) fn check ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] , expr : & Expr < ' _ > , recv : & Expr < ' _ > ) {
57
69
let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) ;
58
- let recv_ty = cx. typeck_results ( ) . expr_ty ( recv) . peel_refs ( ) ;
70
+ let recv_ty = cx. typeck_results ( ) . expr_ty ( recv) ;
71
+ let recv_ty_no_refs = recv_ty. peel_refs ( ) ;
59
72
60
73
if let ExprKind :: Path ( QPath :: Resolved ( _, recv_path) ) = recv. kind
61
- && let Some ( typename) = check_vec ( cx, args, expr_ty, recv_ty , recv_path)
74
+ && let Some ( typename) = check_vec ( cx, args, expr_ty, recv_ty_no_refs , recv_path)
62
75
. then_some ( "Vec" )
63
- . or_else ( || check_string ( cx, args, expr_ty, recv_ty , recv_path) . then_some ( "String" ) )
64
- . or_else ( || check_collections ( cx, expr_ty, recv_ty ) )
76
+ . or_else ( || check_string ( cx, args, expr_ty, recv_ty_no_refs , recv_path) . then_some ( "String" ) )
77
+ . or_else ( || check_collections ( cx, expr_ty, recv_ty_no_refs ) )
65
78
{
66
79
let recv = snippet ( cx, recv. span , "<expr>" ) ;
67
80
span_lint_and_sugg (
@@ -70,7 +83,10 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re
70
83
expr. span ,
71
84
& format ! ( "you seem to be trying to move all elements into a new `{typename}`" ) ,
72
85
"consider using `mem::take`" ,
73
- format ! ( "std::mem::take(&mut {recv})" ) ,
86
+ match recv_ty. kind ( ) {
87
+ ty:: Ref ( ..) => format ! ( "std::mem::take({recv})" ) ,
88
+ _ => format ! ( "std::mem::take(&mut {recv})" ) ,
89
+ } ,
74
90
Applicability :: MachineApplicable ,
75
91
) ;
76
92
}
0 commit comments