Skip to content

Commit 43905d9

Browse files
committed
Auto merge of #7488 - DevinR528:bantype-fix, r=camsteffen
Add primitive type support to disallowed_type lint Closes #6845 changelog: Enable the banning of primitive types in [`disallowed_type`]
2 parents ceb7a86 + a1bab3b commit 43905d9

File tree

5 files changed

+94
-64
lines changed

5 files changed

+94
-64
lines changed

clippy_lints/src/disallowed_type.rs

+35-43
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint;
22

33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_hir::{
5-
def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, TraitBoundModifier, Ty, TyKind, UseKind,
5+
def::Res, def_id::DefId, Crate, Item, ItemKind, PolyTraitRef, PrimTy, TraitBoundModifier, Ty, TyKind, UseKind,
66
};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_session::{declare_tool_lint, impl_lint_pass};
@@ -15,14 +15,12 @@ declare_clippy_lint! {
1515
///
1616
/// **Known problems:** None.
1717
///
18-
/// N.B. There is no way to ban primitive types.
19-
///
2018
/// **Example:**
2119
///
2220
/// An example clippy.toml configuration:
2321
/// ```toml
2422
/// # clippy.toml
25-
/// disallowed-methods = ["std::collections::BTreeMap"]
23+
/// disallowed-types = ["std::collections::BTreeMap"]
2624
/// ```
2725
///
2826
/// ```rust,ignore
@@ -42,7 +40,8 @@ declare_clippy_lint! {
4240
#[derive(Clone, Debug)]
4341
pub struct DisallowedType {
4442
disallowed: FxHashSet<Vec<Symbol>>,
45-
def_ids: FxHashSet<(DefId, Vec<Symbol>)>,
43+
def_ids: FxHashSet<DefId>,
44+
prim_tys: FxHashSet<PrimTy>,
4645
}
4746

4847
impl DisallowedType {
@@ -53,6 +52,23 @@ impl DisallowedType {
5352
.map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
5453
.collect(),
5554
def_ids: FxHashSet::default(),
55+
prim_tys: FxHashSet::default(),
56+
}
57+
}
58+
59+
fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
60+
match res {
61+
Res::Def(_, did) => {
62+
if self.def_ids.contains(did) {
63+
emit(cx, &cx.tcx.def_path_str(*did), span);
64+
}
65+
},
66+
Res::PrimTy(prim) => {
67+
if self.prim_tys.contains(prim) {
68+
emit(cx, prim.name_str(), span);
69+
}
70+
},
71+
_ => {},
5672
}
5773
}
5874
}
@@ -63,60 +79,36 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedType {
6379
fn check_crate(&mut self, cx: &LateContext<'_>, _: &Crate<'_>) {
6480
for path in &self.disallowed {
6581
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<_>>())
67-
{
68-
self.def_ids.insert((id, path.clone()));
82+
match clippy_utils::path_to_res(cx, &segs.iter().map(String::as_str).collect::<Vec<_>>()) {
83+
Res::Def(_, id) => {
84+
self.def_ids.insert(id);
85+
},
86+
Res::PrimTy(ty) => {
87+
self.prim_tys.insert(ty);
88+
},
89+
_ => {},
6990
}
7091
}
7192
}
7293

7394
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
74-
if_chain! {
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);
78-
then {
79-
emit(cx, name, item.span,);
80-
}
95+
if let ItemKind::Use(path, UseKind::Single) = &item.kind {
96+
self.check_res_emit(cx, &path.res, item.span);
8197
}
8298
}
8399

84100
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
85-
if_chain! {
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);
89-
then {
90-
emit(cx, name, path.span());
91-
}
101+
if let TyKind::Path(path) = &ty.kind {
102+
self.check_res_emit(cx, &cx.qpath_res(path, ty.hir_id), ty.span);
92103
}
93104
}
94105

95106
fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) {
96-
if_chain! {
97-
if let Res::Def(_, did) = poly.trait_ref.path.res;
98-
if let Some((_, name)) = self.def_ids.iter().find(|(id, _)| *id == did);
99-
then {
100-
emit(cx, name, poly.trait_ref.path.span);
101-
}
102-
}
107+
self.check_res_emit(cx, &poly.trait_ref.path.res, poly.trait_ref.path.span);
103108
}
104-
105-
// TODO: if non primitive const generics are a thing
106-
// fn check_generic_arg(&mut self, cx: &LateContext<'tcx>, arg: &'tcx GenericArg<'tcx>) {
107-
// match arg {
108-
// GenericArg::Const(c) => {},
109-
// }
110-
// }
111-
// fn check_generic_param(&mut self, cx: &LateContext<'tcx>, param: &'tcx GenericParam<'tcx>) {
112-
// match param.kind {
113-
// GenericParamKind::Const { .. } => {},
114-
// }
115-
// }
116109
}
117110

118-
fn emit(cx: &LateContext<'_>, name: &[Symbol], span: Span) {
119-
let name = name.iter().map(|s| s.to_ident_string()).collect::<Vec<_>>().join("::");
111+
fn emit(cx: &LateContext<'_>, name: &str, span: Span) {
120112
span_lint(
121113
cx,
122114
DISALLOWED_TYPE,

clippy_utils/src/lib.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ use rustc_hir::LangItem::{ResultErr, ResultOk};
7272
use rustc_hir::{
7373
def, Arm, BindingAnnotation, Block, Body, Constness, Destination, Expr, ExprKind, FnDecl, GenericArgs, HirId, Impl,
7474
ImplItem, ImplItemKind, IsAsync, Item, ItemKind, LangItem, Local, MatchSource, Node, Param, Pat, PatKind, Path,
75-
PathSegment, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
75+
PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp,
7676
};
7777
use rustc_lint::{LateContext, Level, Lint, LintContext};
7878
use rustc_middle::hir::exports::Export;
@@ -490,6 +490,9 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
490490

491491
let (krate, first, path) = match *path {
492492
[krate, first, ref path @ ..] => (krate, first, path),
493+
[primitive] => {
494+
return PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy);
495+
},
493496
_ => return Res::Err,
494497
};
495498
let tcx = cx.tcx;

tests/ui-toml/toml_disallowed_type/clippy.toml

+2
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ disallowed-types = [
66
"std::thread::Thread",
77
"std::time::Instant",
88
"std::io::Read",
9+
"std::primitive::usize",
10+
"bool"
911
]

tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,15 @@ fn bad_return_type() -> fn() -> Sneaky {
1313
todo!()
1414
}
1515

16-
fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
17-
todo!()
18-
}
16+
fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {}
1917

20-
fn trait_obj(_: &dyn std::io::Read) {
21-
todo!()
22-
}
18+
fn trait_obj(_: &dyn std::io::Read) {}
19+
20+
fn full_and_single_path_prim(_: usize, _: bool) {}
21+
22+
fn const_generics<const C: usize>() {}
23+
24+
struct GenArg<const U: usize>([u8; U]);
2325

2426
static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut());
2527

@@ -32,4 +34,5 @@ fn main() {
3234
let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
3335
let _ = syn::Ident::new("", todo!());
3436
let _ = HashMap;
37+
let _: usize = 64_usize;
3538
}

tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr

+44-14
Original file line numberDiff line numberDiff line change
@@ -21,68 +21,98 @@ LL | fn bad_return_type() -> fn() -> Sneaky {
2121
error: `std::time::Instant` is not allowed according to config
2222
--> $DIR/conf_disallowed_type.rs:16:28
2323
|
24-
LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
24+
LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {}
2525
| ^^^^^^
2626

2727
error: `std::sync::atomic::AtomicU32` is not allowed according to config
2828
--> $DIR/conf_disallowed_type.rs:16:39
2929
|
30-
LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {
30+
LL | fn bad_arg_type(_: impl Fn(Sneaky) -> foo::atomic::AtomicU32) {}
3131
| ^^^^^^^^^^^^^^^^^^^^^^
3232

3333
error: `std::io::Read` is not allowed according to config
34-
--> $DIR/conf_disallowed_type.rs:20:22
34+
--> $DIR/conf_disallowed_type.rs:18:22
3535
|
36-
LL | fn trait_obj(_: &dyn std::io::Read) {
36+
LL | fn trait_obj(_: &dyn std::io::Read) {}
3737
| ^^^^^^^^^^^^^
3838

39+
error: `usize` is not allowed according to config
40+
--> $DIR/conf_disallowed_type.rs:20:33
41+
|
42+
LL | fn full_and_single_path_prim(_: usize, _: bool) {}
43+
| ^^^^^
44+
45+
error: `bool` is not allowed according to config
46+
--> $DIR/conf_disallowed_type.rs:20:43
47+
|
48+
LL | fn full_and_single_path_prim(_: usize, _: bool) {}
49+
| ^^^^
50+
51+
error: `usize` is not allowed according to config
52+
--> $DIR/conf_disallowed_type.rs:22:28
53+
|
54+
LL | fn const_generics<const C: usize>() {}
55+
| ^^^^^
56+
57+
error: `usize` is not allowed according to config
58+
--> $DIR/conf_disallowed_type.rs:24:24
59+
|
60+
LL | struct GenArg<const U: usize>([u8; U]);
61+
| ^^^^^
62+
3963
error: `std::collections::HashMap` is not allowed according to config
40-
--> $DIR/conf_disallowed_type.rs:28:48
64+
--> $DIR/conf_disallowed_type.rs:30:48
4165
|
4266
LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
4367
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4468

4569
error: `std::collections::HashMap` is not allowed according to config
46-
--> $DIR/conf_disallowed_type.rs:28:12
70+
--> $DIR/conf_disallowed_type.rs:30:12
4771
|
4872
LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
4973
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5074

5175
error: `std::time::Instant` is not allowed according to config
52-
--> $DIR/conf_disallowed_type.rs:29:13
76+
--> $DIR/conf_disallowed_type.rs:31:13
5377
|
5478
LL | let _ = Sneaky::now();
5579
| ^^^^^^
5680

5781
error: `std::sync::atomic::AtomicU32` is not allowed according to config
58-
--> $DIR/conf_disallowed_type.rs:30:13
82+
--> $DIR/conf_disallowed_type.rs:32:13
5983
|
6084
LL | let _ = foo::atomic::AtomicU32::new(0);
6185
| ^^^^^^^^^^^^^^^^^^^^^^
6286

6387
error: `std::sync::atomic::AtomicU32` is not allowed according to config
64-
--> $DIR/conf_disallowed_type.rs:31:17
88+
--> $DIR/conf_disallowed_type.rs:33:17
6589
|
6690
LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
6791
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6892

6993
error: `std::sync::atomic::AtomicU32` is not allowed according to config
70-
--> $DIR/conf_disallowed_type.rs:31:48
94+
--> $DIR/conf_disallowed_type.rs:33:48
7195
|
7296
LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
7397
| ^^^^^^^^^^^^^^^^^^^^^^
7498

7599
error: `syn::TypePath` is not allowed according to config
76-
--> $DIR/conf_disallowed_type.rs:32:43
100+
--> $DIR/conf_disallowed_type.rs:34:43
77101
|
78102
LL | let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
79103
| ^^^^^^^^^^^^^
80104

81-
error: `proc_macro2::Ident` is not allowed according to config
82-
--> $DIR/conf_disallowed_type.rs:33:13
105+
error: `syn::Ident` is not allowed according to config
106+
--> $DIR/conf_disallowed_type.rs:35:13
83107
|
84108
LL | let _ = syn::Ident::new("", todo!());
85109
| ^^^^^^^^^^
86110

87-
error: aborting due to 14 previous errors
111+
error: `usize` is not allowed according to config
112+
--> $DIR/conf_disallowed_type.rs:37:12
113+
|
114+
LL | let _: usize = 64_usize;
115+
| ^^^^^
116+
117+
error: aborting due to 19 previous errors
88118

0 commit comments

Comments
 (0)