1 use clippy_utils
::diagnostics
::span_lint
;
3 use rustc_data_structures
::fx
::FxHashSet
;
5 def
::Res
, def_id
::DefId
, Crate
, Item
, ItemKind
, PolyTraitRef
, TraitBoundModifier
, Ty
, TyKind
, UseKind
,
7 use rustc_lint
::{LateContext, LateLintPass}
;
8 use rustc_session
::{declare_tool_lint, impl_lint_pass}
;
9 use rustc_span
::{Span, Symbol}
;
11 declare_clippy_lint
! {
12 /// **What it does:** Denies the configured types in clippy.toml.
14 /// **Why is this bad?** Some types are undesirable in certain contexts.
16 /// **Known problems:** None.
18 /// N.B. There is no way to ban primitive types.
22 /// An example clippy.toml configuration:
25 /// disallowed-methods = ["std::collections::BTreeMap"]
29 /// use std::collections::BTreeMap;
31 /// let x = std::collections::BTreeMap::new();
35 /// // A similar type that is allowed by the config
36 /// use std::collections::HashMap;
40 "use of a disallowed type"
42 #[derive(Clone, Debug)]
43 pub struct DisallowedType
{
44 disallowed
: FxHashSet
<Vec
<Symbol
>>,
45 def_ids
: FxHashSet
<(DefId
, Vec
<Symbol
>)>,
49 pub fn new(disallowed
: &FxHashSet
<String
>) -> Self {
51 disallowed
: disallowed
53 .map(|s
| s
.split("::").map(|seg
| Symbol
::intern(seg
)).collect
::<Vec
<_
>>())
55 def_ids
: FxHashSet
::default(),
60 impl_lint_pass
!(DisallowedType
=> [DISALLOWED_TYPE
]);
62 impl<'tcx
> LateLintPass
<'tcx
> for DisallowedType
{
63 fn check_crate(&mut self, cx
: &LateContext
<'_
>, _
: &Crate
<'_
>) {
64 for path
in &self.disallowed
{
65 let segs
= path
.iter().map(ToString
::to_string
).collect
::<Vec
<_
>>();
66 if let Res
::Def(_
, id
) = clippy_utils
::path_to_res(cx
, &segs
.iter().map(String
::as_str
).collect
::<Vec
<_
>>())
68 self.def_ids
.insert((id
, path
.clone()));
73 fn check_item(&mut self, cx
: &LateContext
<'tcx
>, item
: &'tcx Item
<'tcx
>) {
75 if let ItemKind
::Use(path
, UseKind
::Single
) = &item
.kind
;
76 if let Res
::Def(_
, did
) = path
.res
;
77 if let Some((_
, name
)) = self.def_ids
.iter().find(|(id
, _
)| *id
== did
);
79 emit(cx
, name
, item
.span
,);
84 fn check_ty(&mut self, cx
: &LateContext
<'tcx
>, ty
: &'tcx Ty
<'tcx
>) {
86 if let TyKind
::Path(path
) = &ty
.kind
;
87 if let Some(did
) = cx
.qpath_res(path
, ty
.hir_id
).opt_def_id();
88 if let Some((_
, name
)) = self.def_ids
.iter().find(|(id
, _
)| *id
== did
);
90 emit(cx
, name
, path
.span());
95 fn check_poly_trait_ref(&mut self, cx
: &LateContext
<'tcx
>, poly
: &'tcx PolyTraitRef
<'tcx
>, _
: TraitBoundModifier
) {
97 if let Res
::Def(_
, did
) = poly
.trait_ref
.path
.res
;
98 if let Some((_
, name
)) = self.def_ids
.iter().find(|(id
, _
)| *id
== did
);
100 emit(cx
, name
, poly
.trait_ref
.path
.span
);
105 // TODO: if non primitive const generics are a thing
106 // fn check_generic_arg(&mut self, cx: &LateContext<'tcx>, arg: &'tcx GenericArg<'tcx>) {
108 // GenericArg::Const(c) => {},
111 // fn check_generic_param(&mut self, cx: &LateContext<'tcx>, param: &'tcx GenericParam<'tcx>) {
112 // match param.kind {
113 // GenericParamKind::Const { .. } => {},
118 fn emit(cx
: &LateContext
<'_
>, name
: &[Symbol
], span
: Span
) {
119 let name
= name
.iter().map(|s
| s
.to_ident_string()).collect
::<Vec
<_
>>().join("::");
124 &format
!("`{}` is not allowed according to config", name
),