]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/types/rc_buffer.rs
Rollup merge of #83092 - petrochenkov:qspan, r=estebank
[rust.git] / clippy_lints / src / types / rc_buffer.rs
1 use rustc_errors::Applicability;
2 use rustc_hir::{self as hir, def_id::DefId, QPath, TyKind};
3 use rustc_lint::LateContext;
4 use rustc_span::symbol::sym;
5
6 use crate::utils::{
7     get_qpath_generic_tys, is_ty_param_diagnostic_item, snippet_with_applicability, span_lint_and_sugg,
8 };
9
10 use super::RC_BUFFER;
11
12 pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_>, def_id: DefId) -> bool {
13     if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
14         if let Some(alternate) = match_buffer_type(cx, qpath) {
15             span_lint_and_sugg(
16                 cx,
17                 RC_BUFFER,
18                 hir_ty.span,
19                 "usage of `Rc<T>` when T is a buffer type",
20                 "try",
21                 format!("Rc<{}>", alternate),
22                 Applicability::MachineApplicable,
23             );
24         } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
25             let qpath = match &ty.kind {
26                 TyKind::Path(qpath) => qpath,
27                 _ => return false,
28             };
29             let inner_span = match get_qpath_generic_tys(qpath).next() {
30                 Some(ty) => ty.span,
31                 None => return false,
32             };
33             let mut applicability = Applicability::MachineApplicable;
34             span_lint_and_sugg(
35                 cx,
36                 RC_BUFFER,
37                 hir_ty.span,
38                 "usage of `Rc<T>` when T is a buffer type",
39                 "try",
40                 format!(
41                     "Rc<[{}]>",
42                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
43                 ),
44                 Applicability::MachineApplicable,
45             );
46             return true;
47         }
48     } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
49         if let Some(alternate) = match_buffer_type(cx, qpath) {
50             span_lint_and_sugg(
51                 cx,
52                 RC_BUFFER,
53                 hir_ty.span,
54                 "usage of `Arc<T>` when T is a buffer type",
55                 "try",
56                 format!("Arc<{}>", alternate),
57                 Applicability::MachineApplicable,
58             );
59         } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
60             let qpath = match &ty.kind {
61                 TyKind::Path(qpath) => qpath,
62                 _ => return false,
63             };
64             let inner_span = match get_qpath_generic_tys(qpath).next() {
65                 Some(ty) => ty.span,
66                 None => return false,
67             };
68             let mut applicability = Applicability::MachineApplicable;
69             span_lint_and_sugg(
70                 cx,
71                 RC_BUFFER,
72                 hir_ty.span,
73                 "usage of `Arc<T>` when T is a buffer type",
74                 "try",
75                 format!(
76                     "Arc<[{}]>",
77                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
78                 ),
79                 Applicability::MachineApplicable,
80             );
81             return true;
82         }
83     }
84
85     false
86 }
87
88 fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
89     if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
90         Some("str")
91     } else if is_ty_param_diagnostic_item(cx, qpath, sym::OsString).is_some() {
92         Some("std::ffi::OsStr")
93     } else if is_ty_param_diagnostic_item(cx, qpath, sym::PathBuf).is_some() {
94         Some("std::path::Path")
95     } else {
96         None
97     }
98 }