@@ -11,7 +11,7 @@ use rustc_hir::Path;
1111use rustc_hir:: QPath ;
1212use rustc_lint:: LateContext ;
1313use rustc_middle:: query:: Key ;
14- use rustc_middle:: ty:: Ty ;
14+ use rustc_middle:: ty;
1515use rustc_span:: sym;
1616use rustc_span:: Symbol ;
1717
@@ -21,7 +21,7 @@ use rustc_span::Symbol;
2121/// ^^^^^^^^^ ^^^^^^ true
2222/// `vec![1,2].drain(..).collect::<HashSet<_>>()`
2323/// ^^^^^^^^^ ^^^^^^^^^^ 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 {
2525 if let Some ( expr_adt_did) = expr. ty_adt_id ( )
2626 && let Some ( recv_adt_did) = recv. ty_adt_id ( )
2727 {
@@ -32,21 +32,33 @@ fn types_match_diagnostic_item(cx: &LateContext<'_>, expr: Ty<'_>, recv: Ty<'_>,
3232}
3333
3434/// 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 {
3642 ( types_match_diagnostic_item ( cx, expr, recv, sym:: Vec )
3743 || types_match_diagnostic_item ( cx, expr, recv, sym:: VecDeque ) )
3844 && matches ! ( args, [ arg] if is_range_full( cx, arg, Some ( recv_path) ) )
3945}
4046
4147/// 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 {
4355 is_type_lang_item ( cx, expr, LangItem :: String )
4456 && is_type_lang_item ( cx, recv, LangItem :: String )
4557 && matches ! ( args, [ arg] if is_range_full( cx, arg, Some ( recv_path) ) )
4658}
4759
4860/// 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 > {
5062 types_match_diagnostic_item ( cx, expr, recv, sym:: HashSet )
5163 . then_some ( "HashSet" )
5264 . 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
5567
5668pub ( super ) fn check ( cx : & LateContext < ' _ > , args : & [ Expr < ' _ > ] , expr : & Expr < ' _ > , recv : & Expr < ' _ > ) {
5769 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 ( ) ;
5972
6073 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)
6275 . 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 ) )
6578 {
6679 let recv = snippet ( cx, recv. span , "<expr>" ) ;
6780 span_lint_and_sugg (
@@ -70,7 +83,10 @@ pub(super) fn check(cx: &LateContext<'_>, args: &[Expr<'_>], expr: &Expr<'_>, re
7083 expr. span ,
7184 & format ! ( "you seem to be trying to move all elements into a new `{typename}`" ) ,
7285 "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+ } ,
7490 Applicability :: MachineApplicable ,
7591 ) ;
7692 }
0 commit comments