1 use clippy_utils::diagnostics::span_lint;
3 use rustc_data_structures::fx::FxHashSet;
5 def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, PrimTy, 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.
20 /// An example clippy.toml configuration:
23 /// disallowed-types = ["std::collections::BTreeMap"]
27 /// use std::collections::BTreeMap;
29 /// let x = std::collections::BTreeMap::new();
33 /// // A similar type that is allowed by the config
34 /// use std::collections::HashMap;
38 "use of a disallowed type"
40 #[derive(Clone, Debug)]
41 pub struct DisallowedType {
42 disallowed: FxHashSet<Vec<Symbol>>,
43 def_ids: FxHashSet<DefId>,
44 prim_tys: FxHashSet<PrimTy>,
48 pub fn new(disallowed: &FxHashSet<String>) -> Self {
50 disallowed: disallowed
52 .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
54 def_ids: FxHashSet::default(),
55 prim_tys: FxHashSet::default(),
59 fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
62 if self.def_ids.contains(did) {
63 emit(cx, &cx.tcx.def_path_str(*did), span);
66 Res::PrimTy(prim) => {
67 if self.prim_tys.contains(prim) {
68 emit(cx, prim.name_str(), span);
76 impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]);
78 impl<'tcx> LateLintPass<'tcx> for DisallowedType {
79 fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
80 for path in &self.disallowed {
81 let segs = path.iter().map(ToString::to_string).collect::<Vec<_>>();
82 match clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) {
84 self.def_ids.insert(id);
87 self.prim_tys.insert(ty);
94 fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
95 if let ItemKind::Use(path, UseKind::Single) = &item.kind {
96 self.check_res_emit(cx, &path.res, item.span);
100 fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
101 if let TyKind::Path(path) = &ty.kind {
102 self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
106 fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) {
107 self.check_res_emit(cx, &poly.trait_ref.path.res, poly.trait_ref.path.span);
111 fn emit(cx: &LateContext<'_>, name: &str, span: Span) {
116 &format!("`{}` is not allowed according to config", name),