]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/types/rc_buffer.rs
Move rc_buffer to its own module
[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) {
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,
28             };
29             let inner_span = match get_qpath_generic_tys(qpath).next() {
30                 Some(ty) => ty.span,
31                 None => return,
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         }
47     } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
48         if let Some(alternate) = match_buffer_type(cx, qpath) {
49             span_lint_and_sugg(
50                 cx,
51                 RC_BUFFER,
52                 hir_ty.span,
53                 "usage of `Arc<T>` when T is a buffer type",
54                 "try",
55                 format!("Arc<{}>", alternate),
56                 Applicability::MachineApplicable,
57             );
58         } else if let Some(ty) = is_ty_param_diagnostic_item(cx, qpath, sym::vec_type) {
59             let qpath = match &ty.kind {
60                 TyKind::Path(qpath) => qpath,
61                 _ => return,
62             };
63             let inner_span = match get_qpath_generic_tys(qpath).next() {
64                 Some(ty) => ty.span,
65                 None => return,
66             };
67             let mut applicability = Applicability::MachineApplicable;
68             span_lint_and_sugg(
69                 cx,
70                 RC_BUFFER,
71                 hir_ty.span,
72                 "usage of `Arc<T>` when T is a buffer type",
73                 "try",
74                 format!(
75                     "Arc<[{}]>",
76                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
77                 ),
78                 Applicability::MachineApplicable,
79             );
80         }
81     }
82 }
83
84 fn match_buffer_type(cx: &LateContext<'_>, qpath: &QPath<'_>) -> Option<&'static str> {
85     if is_ty_param_diagnostic_item(cx, qpath, sym::string_type).is_some() {
86         Some("str")
87     } else if is_ty_param_diagnostic_item(cx, qpath, sym::OsString).is_some() {
88         Some("std::ffi::OsStr")
89     } else if is_ty_param_diagnostic_item(cx, qpath, sym::PathBuf).is_some() {
90         Some("std::path::Path")
91     } else {
92         None
93     }
94 }