@@ -2,24 +2,45 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
22use clippy_utils:: is_range_full;
33use clippy_utils:: ty:: is_type_diagnostic_item;
44use rustc_errors:: Applicability ;
5+ use rustc_hir as hir;
56use rustc_hir:: { Expr , ExprKind , QPath } ;
67use rustc_lint:: LateContext ;
78use rustc_span:: symbol:: sym;
89use rustc_span:: Span ;
910
1011use super :: CLEAR_WITH_DRAIN ;
1112
12- pub ( super ) fn check ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , span : Span , arg : & Expr < ' _ > ) {
13- let ty = cx. typeck_results ( ) . expr_ty ( recv) ;
14- if is_type_diagnostic_item ( cx, ty, sym:: Vec )
15- && let ExprKind :: Path ( QPath :: Resolved ( None , container_path) ) = recv. kind
16- && is_range_full ( cx, arg, Some ( container_path) )
13+ const ACCEPTABLE_TYPES_WITH_ARG : [ rustc_span:: Symbol ; 3 ] = [ sym:: String , sym:: Vec , sym:: VecDeque ] ;
14+
15+ const ACCEPTABLE_TYPES_WITHOUT_ARG : [ rustc_span:: Symbol ; 3 ] = [ sym:: BinaryHeap , sym:: HashMap , sym:: HashSet ] ;
16+
17+ pub ( super ) fn check ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , span : Span , arg : Option < & Expr < ' _ > > ) {
18+ if let Some ( arg) = arg {
19+ if match_acceptable_type ( cx, recv, & ACCEPTABLE_TYPES_WITH_ARG )
20+ && let ExprKind :: Path ( QPath :: Resolved ( None , container_path) ) = recv. kind
21+ && is_range_full ( cx, arg, Some ( container_path) )
22+ {
23+ suggest ( cx, expr, recv, span) ;
24+ }
25+ } else if match_acceptable_type ( cx, recv, & ACCEPTABLE_TYPES_WITHOUT_ARG ) {
26+ suggest ( cx, expr, recv, span) ;
27+ }
28+ }
29+
30+ fn match_acceptable_type ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , types : & [ rustc_span:: Symbol ] ) -> bool {
31+ let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) . peel_refs ( ) ;
32+ types. iter ( ) . any ( |& ty| is_type_diagnostic_item ( cx, expr_ty, ty) )
33+ }
34+
35+ fn suggest ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , span : Span ) {
36+ if let Some ( adt) = cx. typeck_results ( ) . expr_ty ( recv) . ty_adt_def ( )
37+ && let Some ( ty_name) = cx. tcx . get_diagnostic_name ( adt. did ( ) )
1738 {
1839 span_lint_and_sugg (
1940 cx,
2041 CLEAR_WITH_DRAIN ,
2142 span. with_hi ( expr. span . hi ( ) ) ,
22- "`drain` used to clear a `Vec`" ,
43+ & format ! ( "`drain` used to clear a `{}`" , ty_name ) ,
2344 "try" ,
2445 "clear()" . to_string ( ) ,
2546 Applicability :: MachineApplicable ,
0 commit comments