Skip to content

Commit 237aef4

Browse files
committed
Don't walk the hir unnecessarily let the visitor do it
1 parent e57441a commit 237aef4

File tree

3 files changed

+55
-187
lines changed

3 files changed

+55
-187
lines changed

clippy_lints/src/disallowed_type.rs

Lines changed: 45 additions & 178 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
use clippy_utils::diagnostics::span_lint;
22

33
use rustc_data_structures::fx::FxHashSet;
4-
use rustc_hir::{
5-
def::Res, FnRetTy, GenericArg, GenericArgs, GenericBound, GenericParamKind, Item, ItemKind, Path, PolyTraitRef, Ty,
6-
TyKind, TypeBindingKind, UseKind,
7-
};
4+
use rustc_hir::{def::Res, Item, ItemKind, PolyTraitRef, TraitBoundModifier, Ty, TyKind, UseKind};
85
use rustc_lint::{LateContext, LateLintPass};
9-
use rustc_middle::ty;
106
use rustc_session::{declare_tool_lint, impl_lint_pass};
11-
use rustc_span::Symbol;
7+
use rustc_span::{Span, Symbol};
128

139
declare_clippy_lint! {
14-
/// **What it does:** Denies the configured types in clippy.toml
10+
/// **What it does:** Denies the configured types in clippy.toml.
1511
///
1612
/// **Why is this bad?** Some types are undesirable in certain contexts.
1713
///
@@ -24,8 +20,16 @@ declare_clippy_lint! {
2420
/// `disallowed-methods = ["alloc::collections::btree::map::BTreeMap"]` and not
2521
/// `disallowed-methods = ["std::collections::BTreeMap"]` as you might expect.
2622
///
23+
/// N.B. There is no way to ban primitive types.
24+
///
2725
/// **Example:**
2826
///
27+
/// An example clippy.toml configuration:
28+
/// ```toml
29+
/// # clippy.toml
30+
/// disallowed-methods = ["alloc::collections::btree::map::BTreeMap"]
31+
/// ```
32+
///
2933
/// ```rust,ignore
3034
/// use std::collections::BTreeMap;
3135
/// // or its use
@@ -58,198 +62,61 @@ impl DisallowedType {
5862

5963
impl_lint_pass!(DisallowedType => [DISALLOWED_TYPE]);
6064

61-
impl LateLintPass<'_> for DisallowedType {
62-
fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {
65+
impl<'tcx> LateLintPass<'tcx> for DisallowedType {
66+
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
6367
if_chain! {
6468
if let ItemKind::Use(path, UseKind::Single) = &item.kind;
6569
if let Res::Def(_, id) = path.res;
6670
let use_path = cx.get_def_path(id);
6771
if let Some(name) = self.disallowed.iter().find(|path| **path == use_path);
6872
then {
69-
let name = name.iter()
70-
.map(|s| s.to_ident_string())
71-
.collect::<Vec<_>>()
72-
.join("::");
73-
span_lint(
74-
cx,
75-
DISALLOWED_TYPE,
76-
item.span,
77-
&format!("`{}` is not allowed according to config", name),
78-
);
73+
emit(cx, name, item.span,);
7974
}
8075
}
8176
}
8277

83-
fn check_ty(&mut self, cx: &LateContext<'_>, ty: &Ty<'_>) {
84-
walk_to_path(cx, ty, &self.disallowed);
85-
}
86-
}
87-
88-
fn walk_to_path(cx: &LateContext<'_>, ty: &Ty<'_>, disallowed: &FxHashSet<Vec<Symbol>>) {
89-
match &ty.kind {
90-
TyKind::Slice(t) => walk_to_path(cx, t, disallowed),
91-
TyKind::Array(t, c) => {
92-
walk_to_path(cx, t, disallowed);
93-
// TODO: a bit hacky
94-
walk_to_path(
95-
cx,
96-
&Ty {
97-
hir_id: ty.hir_id,
98-
kind: TyKind::Typeof(*c),
99-
span: ty.span,
100-
},
101-
disallowed,
102-
);
103-
},
104-
TyKind::Ptr(mutable) | TyKind::Rptr(_, mutable) => walk_to_path(cx, mutable.ty, disallowed),
105-
TyKind::BareFn(barefn) => {
106-
for input in barefn.decl.inputs {
107-
walk_to_path(cx, input, disallowed);
108-
}
109-
if let FnRetTy::Return(t) = barefn.decl.output {
110-
walk_to_path(cx, t, disallowed);
111-
}
112-
},
113-
TyKind::Tup(tup) => {
114-
for t in *tup {
115-
walk_to_path(cx, t, disallowed);
116-
}
117-
},
118-
TyKind::Path(path) => {
119-
if_chain! {
120-
if let Some(did) = cx.qpath_res(path, ty.hir_id).opt_def_id();
121-
let use_path = cx.get_def_path(did);
122-
if let Some(name) = disallowed.iter().find(|path| **path == use_path);
123-
then {
124-
let name = name.iter()
125-
.map(|s| s.to_ident_string())
126-
.collect::<Vec<_>>()
127-
.join("::");
128-
span_lint(
129-
cx,
130-
DISALLOWED_TYPE,
131-
path.span(),
132-
&format!("`{}` is not allowed according to config", name),
133-
);
134-
}
135-
}
136-
},
137-
TyKind::OpaqueDef(_, gen) => {
138-
for arg in *gen {
139-
if let GenericArg::Type(t) = arg {
140-
walk_to_path(cx, t, disallowed);
141-
}
142-
}
143-
},
144-
TyKind::TraitObject(polyref, _, _) => walk_trait_obj(cx, &polyref.iter().collect::<Vec<_>>(), disallowed),
145-
TyKind::Typeof(anonconst) => {
146-
if_chain! {
147-
if let Some(tyck) = cx.maybe_typeck_results();
148-
if let Some(var_ty) = tyck.node_type_opt(anonconst.hir_id);
149-
if let ty::Adt(ty::AdtDef { did, .. }, _) = var_ty.kind();
150-
let use_path = cx.get_def_path(*did);
151-
if let Some(name) = disallowed.iter().find(|path| **path == use_path);
152-
then {
153-
let name = name.iter()
154-
.map(|s| s.to_ident_string())
155-
.collect::<Vec<_>>()
156-
.join("::");
157-
span_lint(
158-
cx,
159-
DISALLOWED_TYPE,
160-
ty.span,
161-
&format!("`{}` is not allowed according to config", name),
162-
);
163-
}
78+
fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {
79+
if_chain! {
80+
if let TyKind::Path(path) = &ty.kind;
81+
if let Some(did) = cx.qpath_res(path, ty.hir_id).opt_def_id();
82+
let use_path = cx.get_def_path(did);
83+
if let Some(name) = self.disallowed.iter().find(|path| **path == use_path);
84+
then {
85+
emit(cx, name, path.span());
16486
}
165-
},
166-
TyKind::Infer | TyKind::Never | TyKind::Err => {},
167-
}
168-
}
169-
170-
fn walk_path_segments(cx: &LateContext<'_>, path: &Path<'_>, disallowed: &FxHashSet<Vec<Symbol>>) {
171-
for arg in path.segments.iter().filter_map(|s| s.args) {
172-
walk_gen_args(cx, arg, disallowed);
87+
}
17388
}
174-
}
17589

176-
fn walk_trait_obj(cx: &LateContext<'_>, poly: &[&PolyTraitRef<'_>], disallowed: &FxHashSet<Vec<Symbol>>) {
177-
for poly in poly {
90+
fn check_poly_trait_ref(&mut self, cx: &LateContext<'tcx>, poly: &'tcx PolyTraitRef<'tcx>, _: TraitBoundModifier) {
17891
if_chain! {
17992
if let Res::Def(_, did) = poly.trait_ref.path.res;
18093
let use_path = cx.get_def_path(did);
181-
if let Some(name) = disallowed.iter().find(|path| **path == use_path);
94+
if let Some(name) = self.disallowed.iter().find(|path| **path == use_path);
18295
then {
183-
let name = name.iter()
184-
.map(|s| s.to_ident_string())
185-
.collect::<Vec<_>>()
186-
.join("::");
187-
span_lint(
188-
cx,
189-
DISALLOWED_TYPE,
190-
poly.trait_ref.path.span,
191-
&format!("`{}` is not allowed according to config", name),
192-
);
193-
}
194-
}
195-
walk_path_segments(cx, poly.trait_ref.path, disallowed);
196-
197-
for param in poly.bound_generic_params {
198-
walk_gen_bounds(cx, param.bounds, disallowed);
199-
match param.kind {
200-
GenericParamKind::Type { default: Some(ty), .. } => walk_to_path(cx, ty, disallowed),
201-
GenericParamKind::Const {
202-
ty,
203-
default: Some(anon),
204-
} => {
205-
walk_to_path(cx, ty, disallowed);
206-
walk_to_path(
207-
cx,
208-
&Ty {
209-
hir_id: ty.hir_id,
210-
kind: TyKind::Typeof(anon),
211-
span: ty.span,
212-
},
213-
disallowed,
214-
);
215-
},
216-
_ => {},
96+
emit(cx, name, poly.trait_ref.path.span);
21797
}
21898
}
21999
}
220-
}
221100

222-
fn walk_gen_args(cx: &LateContext<'_>, gen_args: &GenericArgs<'_>, disallowed: &FxHashSet<Vec<Symbol>>) {
223-
for arg in gen_args.args {
224-
match arg {
225-
GenericArg::Type(t) => walk_to_path(cx, t, disallowed),
226-
GenericArg::Const(c) => walk_to_path(
227-
cx,
228-
&Ty {
229-
hir_id: c.value.hir_id,
230-
kind: TyKind::Typeof(c.value),
231-
span: c.span,
232-
},
233-
disallowed,
234-
),
235-
GenericArg::Lifetime(_) => {},
236-
}
237-
}
238-
for bind in gen_args.bindings {
239-
match bind.kind {
240-
TypeBindingKind::Equality { ty } => walk_to_path(cx, ty, disallowed),
241-
TypeBindingKind::Constraint { bounds } => walk_gen_bounds(cx, bounds, disallowed),
242-
}
243-
walk_gen_args(cx, bind.gen_args, disallowed);
244-
}
101+
// TODO: if non primitive const generics are a thing
102+
// fn check_generic_arg(&mut self, cx: &LateContext<'tcx>, arg: &'tcx GenericArg<'tcx>) {
103+
// match arg {
104+
// GenericArg::Const(c) => {},
105+
// }
106+
// }
107+
// fn check_generic_param(&mut self, cx: &LateContext<'tcx>, param: &'tcx GenericParam<'tcx>) {
108+
// match param.kind {
109+
// GenericParamKind::Const { .. } => {},
110+
// }
111+
// }
245112
}
246113

247-
fn walk_gen_bounds(cx: &LateContext<'_>, bounds: &[GenericBound<'_>], disallowed: &FxHashSet<Vec<Symbol>>) {
248-
for b in bounds {
249-
match b {
250-
GenericBound::Trait(poly, _) => walk_trait_obj(cx, &[poly], disallowed),
251-
GenericBound::LangItemTrait(_, _, _, gen) => walk_gen_args(cx, gen, disallowed),
252-
GenericBound::Outlives(_) => {},
253-
}
254-
}
114+
fn emit(cx: &LateContext<'_>, name: &[Symbol], span: Span) {
115+
let name = name.iter().map(|s| s.to_ident_string()).collect::<Vec<_>>().join("::");
116+
span_lint(
117+
cx,
118+
DISALLOWED_TYPE,
119+
span,
120+
&format!("`{}` is not allowed according to config", name),
121+
);
255122
}

tests/ui-toml/toml_disallowed_type/conf_disallowed_type.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@ fn trait_obj(_: &dyn std::io::Read) {
2121
todo!()
2222
}
2323

24+
static BAD: foo::atomic::AtomicPtr<()> = foo::atomic::AtomicPtr::new(std::ptr::null_mut());
25+
2426
#[allow(clippy::diverging_sub_expression)]
2527
fn main() {
2628
let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
2729
let _ = Sneaky::now();
2830
let _ = foo::atomic::AtomicU32::new(0);
2931
static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
3032
let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
31-
// diverging_sub_expression ?
3233
let _ = syn::Ident::new("", todo!());
3334
let _ = HashMap;
3435
}

tests/ui-toml/toml_disallowed_type/conf_disallowed_type.stderr

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,49 +37,49 @@ LL | fn trait_obj(_: &dyn std::io::Read) {
3737
| ^^^^^^^^^^^^^
3838

3939
error: `std::collections::hash::map::HashMap` is not allowed according to config
40-
--> $DIR/conf_disallowed_type.rs:26:48
40+
--> $DIR/conf_disallowed_type.rs:28:48
4141
|
4242
LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
4343
| ^^^^^^^^^^^^^^^^^^^^^^^^^
4444

4545
error: `std::collections::hash::map::HashMap` is not allowed according to config
46-
--> $DIR/conf_disallowed_type.rs:26:12
46+
--> $DIR/conf_disallowed_type.rs:28:12
4747
|
4848
LL | let _: std::collections::HashMap<(), ()> = std::collections::HashMap::new();
4949
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5050

5151
error: `std::time::Instant` is not allowed according to config
52-
--> $DIR/conf_disallowed_type.rs:27:13
52+
--> $DIR/conf_disallowed_type.rs:29:13
5353
|
5454
LL | let _ = Sneaky::now();
5555
| ^^^^^^
5656

5757
error: `core::sync::atomic::AtomicU32` is not allowed according to config
58-
--> $DIR/conf_disallowed_type.rs:28:13
58+
--> $DIR/conf_disallowed_type.rs:30:13
5959
|
6060
LL | let _ = foo::atomic::AtomicU32::new(0);
6161
| ^^^^^^^^^^^^^^^^^^^^^^
6262

6363
error: `core::sync::atomic::AtomicU32` is not allowed according to config
64-
--> $DIR/conf_disallowed_type.rs:29:17
64+
--> $DIR/conf_disallowed_type.rs:31:17
6565
|
6666
LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
6767
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6868

6969
error: `core::sync::atomic::AtomicU32` is not allowed according to config
70-
--> $DIR/conf_disallowed_type.rs:29:48
70+
--> $DIR/conf_disallowed_type.rs:31:48
7171
|
7272
LL | static FOO: std::sync::atomic::AtomicU32 = foo::atomic::AtomicU32::new(1);
7373
| ^^^^^^^^^^^^^^^^^^^^^^
7474

7575
error: `syn::ty::TypePath` is not allowed according to config
76-
--> $DIR/conf_disallowed_type.rs:30:43
76+
--> $DIR/conf_disallowed_type.rs:32:43
7777
|
7878
LL | let _: std::collections::BTreeMap<(), syn::TypePath> = Default::default();
7979
| ^^^^^^^^^^^^^
8080

8181
error: `proc_macro2::Ident` is not allowed according to config
82-
--> $DIR/conf_disallowed_type.rs:32:13
82+
--> $DIR/conf_disallowed_type.rs:33:13
8383
|
8484
LL | let _ = syn::Ident::new("", todo!());
8585
| ^^^^^^^^^^

0 commit comments

Comments
 (0)