]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/types/rc_buffer.rs
Rollup merge of #97739 - a2aaron:let_underscore, r=estebank
[rust.git] / src / tools / clippy / clippy_lints / src / types / rc_buffer.rs
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;
8
9 use super::RC_BUFFER;
10
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) {
14             span_lint_and_sugg(
15                 cx,
16                 RC_BUFFER,
17                 hir_ty.span,
18                 "usage of `Rc<T>` when T is a buffer type",
19                 "try",
20                 format!("Rc<{}>", alternate),
21                 Applicability::MachineApplicable,
22             );
23         } else {
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) {
27                 return false;
28             }
29             let qpath = match &ty.kind {
30                 TyKind::Path(qpath) => qpath,
31                 _ => return false,
32             };
33             let inner_span = match qpath_generic_tys(qpath).next() {
34                 Some(ty) => ty.span,
35                 None => return false,
36             };
37             let mut applicability = Applicability::MachineApplicable;
38             span_lint_and_sugg(
39                 cx,
40                 RC_BUFFER,
41                 hir_ty.span,
42                 "usage of `Rc<T>` when T is a buffer type",
43                 "try",
44                 format!(
45                     "Rc<[{}]>",
46                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
47                 ),
48                 Applicability::MachineApplicable,
49             );
50             return true;
51         }
52     } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
53         if let Some(alternate) = match_buffer_type(cx, qpath) {
54             span_lint_and_sugg(
55                 cx,
56                 RC_BUFFER,
57                 hir_ty.span,
58                 "usage of `Arc<T>` when T is a buffer type",
59                 "try",
60                 format!("Arc<{}>", alternate),
61                 Applicability::MachineApplicable,
62             );
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) {
66                 return false;
67             }
68             let qpath = match &ty.kind {
69                 TyKind::Path(qpath) => qpath,
70                 _ => return false,
71             };
72             let inner_span = match qpath_generic_tys(qpath).next() {
73                 Some(ty) => ty.span,
74                 None => return false,
75             };
76             let mut applicability = Applicability::MachineApplicable;
77             span_lint_and_sugg(
78                 cx,
79                 RC_BUFFER,
80                 hir_ty.span,
81                 "usage of `Arc<T>` when T is a buffer type",
82                 "try",
83                 format!(
84                     "Arc<[{}]>",
85                     snippet_with_applicability(cx, inner_span, "..", &mut applicability)
86                 ),
87                 Applicability::MachineApplicable,
88             );
89             return true;
90         }
91     }
92
93     false
94 }
95
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",
103         _ => return None,
104     };
105     Some(path)
106 }