-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathdisallowed_types.rs
116 lines (107 loc) · 3.95 KB
/
disallowed_types.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use clippy_config::Conf;
use clippy_config::types::{DisallowedPath, create_disallowed_map};
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::DefIdMap;
use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::TyCtxt;
use rustc_session::impl_lint_pass;
use rustc_span::Span;
declare_clippy_lint! {
/// ### What it does
/// Denies the configured types in clippy.toml.
///
/// Note: Even though this lint is warn-by-default, it will only trigger if
/// types are defined in the clippy.toml file.
///
/// ### Why is this bad?
/// Some types are undesirable in certain contexts.
///
/// ### Example:
/// An example clippy.toml configuration:
/// ```toml
/// # clippy.toml
/// disallowed-types = [
/// # Can use a string as the path of the disallowed type.
/// "std::collections::BTreeMap",
/// # Can also use an inline table with a `path` key.
/// { path = "std::net::TcpListener" },
/// # When using an inline table, can add a `reason` for why the type
/// # is disallowed.
/// { path = "std::net::Ipv4Addr", reason = "no IPv4 allowed" },
/// # Can also add a `replacement` that will be offered as a suggestion.
/// { path = "std::sync::Mutex", reason = "prefer faster & simpler non-poisonable mutex", replacement = "parking_lot::Mutex" },
/// ]
/// ```
///
/// ```rust,ignore
/// use std::collections::BTreeMap;
/// // or its use
/// let x = std::collections::BTreeMap::new();
/// ```
/// Use instead:
/// ```rust,ignore
/// // A similar type that is allowed by the config
/// use std::collections::HashMap;
/// ```
#[clippy::version = "1.55.0"]
pub DISALLOWED_TYPES,
style,
"use of disallowed types"
}
pub struct DisallowedTypes {
def_ids: DefIdMap<(&'static str, &'static DisallowedPath)>,
prim_tys: FxHashMap<PrimTy, (&'static str, &'static DisallowedPath)>,
}
impl DisallowedTypes {
pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
let (def_ids, prim_tys) = create_disallowed_map(tcx, &conf.disallowed_types, def_kind_predicate, "type", true);
Self { def_ids, prim_tys }
}
fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
let (path, disallowed_path) = match res {
Res::Def(_, did) if let Some(&x) = self.def_ids.get(did) => x,
Res::PrimTy(prim) if let Some(&x) = self.prim_tys.get(prim) => x,
_ => return,
};
span_lint_and_then(
cx,
DISALLOWED_TYPES,
span,
format!("use of a disallowed type `{path}`"),
disallowed_path.diag_amendment(span),
);
}
}
pub fn def_kind_predicate(def_kind: DefKind) -> bool {
matches!(
def_kind,
DefKind::Struct
| DefKind::Union
| DefKind::Enum
| DefKind::Trait
| DefKind::TyAlias
| DefKind::ForeignTy
| DefKind::AssocTy
)
}
impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind {
for res in &path.res {
self.check_res_emit(cx, res, item.span);
}
}
}
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) {
if let TyKind::Path(path) = &ty.kind {
self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
}
}
fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>) {
self.check_res_emit(cx, &poly.trait_ref.path.res, poly.trait_ref.path.span);
}
}