11use clippy_utils:: diagnostics:: span_lint_and_sugg;
22use clippy_utils:: is_range_full;
3- use clippy_utils:: ty:: is_type_diagnostic_item;
3+ use clippy_utils:: ty:: { is_type_diagnostic_item, is_type_lang_item } ;
44use rustc_errors:: Applicability ;
55use rustc_hir as hir;
6- use rustc_hir:: { Expr , ExprKind , QPath } ;
6+ use rustc_hir:: { Expr , ExprKind , LangItem , QPath } ;
77use rustc_lint:: LateContext ;
88use rustc_span:: symbol:: sym;
99use rustc_span:: Span ;
1010
1111use super :: CLEAR_WITH_DRAIN ;
1212
13- const ACCEPTABLE_TYPES_WITH_ARG : [ rustc_span:: Symbol ; 3 ] = [ sym:: String , sym:: Vec , sym:: VecDeque ] ;
13+ // Add `String` here when it is added to diagnostic items
14+ const ACCEPTABLE_TYPES_WITH_ARG : [ rustc_span:: Symbol ; 2 ] = [ sym:: Vec , sym:: VecDeque ] ;
1415
1516const ACCEPTABLE_TYPES_WITHOUT_ARG : [ rustc_span:: Symbol ; 3 ] = [ sym:: BinaryHeap , sym:: HashMap , sym:: HashSet ] ;
1617
@@ -30,11 +31,14 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, span
3031fn match_acceptable_type ( cx : & LateContext < ' _ > , expr : & hir:: Expr < ' _ > , types : & [ rustc_span:: Symbol ] ) -> bool {
3132 let expr_ty = cx. typeck_results ( ) . expr_ty ( expr) . peel_refs ( ) ;
3233 types. iter ( ) . any ( |& ty| is_type_diagnostic_item ( cx, expr_ty, ty) )
34+ // String type is a lang item but not a diagnostic item for now so we need a separate check
35+ || is_type_lang_item ( cx, expr_ty, LangItem :: String )
3336}
3437
3538fn suggest ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , recv : & Expr < ' _ > , span : Span ) {
3639 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 ( ) )
40+ // Use `opt_item_name` while `String` is not a diagnostic item
41+ && let Some ( ty_name) = cx. tcx . opt_item_name ( adt. did ( ) )
3842 {
3943 span_lint_and_sugg (
4044 cx,
0 commit comments