1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::snippet_with_applicability;
3 use clippy_utils::{path_def_id, qpath_generic_tys};
4 use rustc_errors::Applicability;
5 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
6 use rustc_lint::LateContext;
7 use rustc_span::symbol::sym;
11 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
12 if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
13 if let Some(alternate) = match_buffer_type(cx, qpath) {
18 "usage of `Rc<T>` when T is a buffer type",
20 format!("Rc<{}>", alternate),
21 Applicability::MachineApplicable,
24 let Some(ty) = qpath_generic_tys(qpath).next() else { return false };
25 let Some(id) = path_def_id(cx, ty) else { return false };
26 if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
29 let qpath = match &ty.kind {
30 TyKind::Path(qpath) => qpath,
33 let inner_span = match qpath_generic_tys(qpath).next() {
37 let mut applicability = Applicability::MachineApplicable;
42 "usage of `Rc<T>` when T is a buffer type",
46 snippet_with_applicability(cx, inner_span, "..", &mut applicability)
48 Applicability::MachineApplicable,
52 } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
53 if let Some(alternate) = match_buffer_type(cx, qpath) {
58 "usage of `Arc<T>` when T is a buffer type",
60 format!("Arc<{}>", alternate),
61 Applicability::MachineApplicable,
63 } else if let Some(ty) = qpath_generic_tys(qpath).next() {
64 let Some(id) = path_def_id(cx, ty) else { return false };
65 if !cx.tcx.is_diagnostic_item(sym::Vec, id) {
68 let qpath = match &ty.kind {
69 TyKind::Path(qpath) => qpath,
72 let inner_span = match qpath_generic_tys(qpath).next() {
76 let mut applicability = Applicability::MachineApplicable;
81 "usage of `Arc<T>` when T is a buffer type",
85 snippet_with_applicability(cx, inner_span, "..", &mut applicability)
87 Applicability::MachineApplicable,
96 fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
97 let ty = qpath_generic_tys(qpath).next()?;
98 let id = path_def_id(cx, ty)?;
99 let path = match cx.tcx.get_diagnostic_name(id)? {
100 sym::String => "str",
101 sym::OsString => "std::ffi::OsStr",
102 sym::PathBuf => "std::path::Path",