Skip to content

Commit 5ab8daa

Browse files
committed
Replace str path utils with new PathLookup type
1 parent ea13461 commit 5ab8daa

File tree

71 files changed

+809
-1402
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+809
-1402
lines changed

CONTRIBUTING.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ debugging to find the actual problem behind the issue.
7777

7878
[`T-middle`] issues can be more involved and require verifying types. The [`ty`] module contains a
7979
lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of
80-
an AST expression). `match_def_path()` in Clippy's `utils` module can also be useful.
80+
an AST expression).
8181

8282
[`good-first-issue`]: https://github.com/rust-lang/rust-clippy/labels/good-first-issue
8383
[`S-inactive-closed`]: https://github.com/rust-lang/rust-clippy/pulls?q=is%3Aclosed+label%3AS-inactive-closed

book/src/development/common_tools_writing_lints.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ arguments have to be checked separately.
8686

8787
```rust
8888
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
89-
use clippy_utils::{paths, match_def_path};
89+
use clippy_utils::paths;
9090
use rustc_span::symbol::sym;
9191
use rustc_hir::LangItem;
9292

@@ -108,7 +108,7 @@ impl LateLintPass<'_> for MyStructLint {
108108

109109
// 3. Using the type path
110110
// This method should be avoided if possible
111-
if match_def_path(cx, def_id, &paths::RESULT) {
111+
if paths::RESULT.matches_ty(cx, ty) {
112112
// The type is a `core::result::Result`
113113
}
114114
}

book/src/development/trait_checking.md

+9-7
Original file line numberDiff line numberDiff line change
@@ -73,22 +73,24 @@ impl LateLintPass<'_> for CheckDropTraitLint {
7373
## Using Type Path
7474

7575
If neither diagnostic item nor a language item is available, we can use
76-
[`clippy_utils::paths`][paths] with the `match_trait_method` to determine trait
77-
implementation.
76+
[`clippy_utils::paths`][paths] to determine get a trait's `DefId`.
7877

7978
> **Note**: This approach should be avoided if possible, the best thing to do would be to make a PR to [`rust-lang/rust`][rust] adding a diagnostic item.
8079
81-
Below, we check if the given `expr` implements the `Iterator`'s trait method `cloned` :
80+
Below, we check if the given `expr` implements [`core::iter::Step`](https://doc.rust-lang.org/std/iter/trait.Step.html):
8281

8382
```rust
84-
use clippy_utils::{match_trait_method, paths};
83+
use clippy_utils::{implements_trait, paths};
8584
use rustc_hir::Expr;
8685
use rustc_lint::{LateContext, LateLintPass};
8786

88-
impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
87+
impl LateLintPass<'_> for CheckIterStep {
8988
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
90-
if match_trait_method(cx, expr, &paths::CORE_ITER_CLONED) {
91-
println!("`expr` implements `CORE_ITER_CLONED` trait!");
89+
let ty = cx.typeck_results().expr_ty(expr);
90+
if let Some(trait_def_id) = paths::ITER_STEP.first(cx)
91+
&& implements_trait(cx, ty, trait_def_id, &[])
92+
{
93+
println!("`expr` implements the `core::iter::Step` trait!");
9294
}
9395
}
9496
}

clippy.toml

-3
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@ lint-commented-code = true
77
[[disallowed-methods]]
88
path = "rustc_lint::context::LintContext::lint"
99
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
10-
allow-invalid = true
1110

1211
[[disallowed-methods]]
1312
path = "rustc_lint::context::LintContext::span_lint"
1413
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint*` functions instead"
15-
allow-invalid = true
1614

1715
[[disallowed-methods]]
1816
path = "rustc_middle::ty::context::TyCtxt::node_span_lint"
1917
reason = "this function does not add a link to our documentation, please use the `clippy_utils::diagnostics::span_lint_hir*` functions instead"
20-
allow-invalid = true

clippy_config/src/types.rs

+37-50
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
use clippy_utils::PathNS;
12
use rustc_data_structures::fx::FxHashMap;
23
use rustc_errors::{Applicability, Diag};
34
use rustc_hir::PrimTy;
4-
use rustc_hir::def::{DefKind, Res};
5+
use rustc_hir::def::DefKind;
56
use rustc_hir::def_id::DefIdMap;
67
use rustc_middle::ty::TyCtxt;
78
use rustc_span::{Span, Symbol};
@@ -133,6 +134,7 @@ impl DisallowedPathEnum {
133134
pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
134135
tcx: TyCtxt<'_>,
135136
disallowed_paths: &'static [DisallowedPath<REPLACEMENT_ALLOWED>],
137+
ns: PathNS,
136138
def_kind_predicate: impl Fn(DefKind) -> bool,
137139
predicate_description: &str,
138140
allow_prim_tys: bool,
@@ -145,62 +147,47 @@ pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
145147
FxHashMap::default();
146148
for disallowed_path in disallowed_paths {
147149
let path = disallowed_path.path();
148-
let path_split = path.split("::").collect::<Vec<_>>();
149-
let mut resolutions = clippy_utils::def_path_res(tcx, &path_split);
150-
151-
let mut found_def_id = None;
152-
let mut found_prim_ty = false;
153-
resolutions.retain(|res| match res {
154-
Res::Def(def_kind, def_id) => {
155-
found_def_id = Some(*def_id);
156-
def_kind_predicate(*def_kind)
157-
},
158-
Res::PrimTy(_) => {
159-
found_prim_ty = true;
160-
allow_prim_tys
161-
},
162-
_ => false,
163-
});
150+
let sym_path: Vec<Symbol> = path.split("::").map(Symbol::intern).collect();
151+
let mut resolutions = clippy_utils::lookup_path(tcx, ns, &sym_path);
152+
resolutions.retain(|&def_id| def_kind_predicate(tcx.def_kind(def_id)));
153+
154+
let (prim_ty, found_prim_ty) = if let &[name] = sym_path.as_slice()
155+
&& let Some(prim) = PrimTy::from_name(name)
156+
{
157+
(allow_prim_tys.then_some(prim), true)
158+
} else {
159+
(None, false)
160+
};
161+
164162
if resolutions.is_empty()
163+
&& prim_ty.is_none()
164+
&& !disallowed_path.allow_invalid
165165
// Don't warn about unloaded crates:
166166
// https://github.com/rust-lang/rust-clippy/pull/14397#issuecomment-2848328221
167-
&& (path_split.len() < 2
168-
|| !clippy_utils::find_crates(tcx, Symbol::intern(path_split[0])).is_empty())
167+
&& (sym_path.len() < 2 || !clippy_utils::find_crates(tcx, sym_path[0]).is_empty())
169168
{
170-
let span = disallowed_path.span();
171-
172-
if let Some(def_id) = found_def_id {
173-
tcx.sess.dcx().span_warn(
174-
span,
175-
format!(
176-
"expected a {predicate_description}, found {} {}",
177-
tcx.def_descr_article(def_id),
178-
tcx.def_descr(def_id)
179-
),
180-
);
169+
// Relookup the path in an arbitrary namespace to get a good `expected, found` message
170+
let found_def_ids = clippy_utils::lookup_path(tcx, PathNS::Arbitrary, &sym_path);
171+
let message = if let Some(&def_id) = found_def_ids.first() {
172+
let (article, description) = tcx.article_and_description(def_id);
173+
format!("expected a {predicate_description}, found {article} {description}")
181174
} else if found_prim_ty {
182-
tcx.sess.dcx().span_warn(
183-
span,
184-
format!("expected a {predicate_description}, found a primitive type",),
185-
);
186-
} else if !disallowed_path.allow_invalid {
187-
tcx.sess.dcx().span_warn(
188-
span,
189-
format!("`{path}` does not refer to an existing {predicate_description}"),
190-
);
191-
}
175+
format!("expected a {predicate_description}, found a primitive type")
176+
} else {
177+
format!("`{path}` does not refer to a reachable {predicate_description}")
178+
};
179+
tcx.sess
180+
.dcx()
181+
.struct_span_warn(disallowed_path.span(), message)
182+
.with_help("add `allow-invalid = true` to the entry to suppress this warning")
183+
.emit();
192184
}
193185

194-
for res in resolutions {
195-
match res {
196-
Res::Def(_, def_id) => {
197-
def_ids.insert(def_id, (path, disallowed_path));
198-
},
199-
Res::PrimTy(ty) => {
200-
prim_tys.insert(ty, (path, disallowed_path));
201-
},
202-
_ => unreachable!(),
203-
}
186+
for def_id in resolutions {
187+
def_ids.insert(def_id, (path, disallowed_path));
188+
}
189+
if let Some(ty) = prim_ty {
190+
prim_tys.insert(ty, (path, disallowed_path));
204191
}
205192
}
206193

clippy_lints/src/arc_with_non_send_sync.rs

+8
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,12 @@ impl<'tcx> LateLintPass<'tcx> for ArcWithNonSendSync {
8282
);
8383
}
8484
}
85+
86+
// fn check_item(&mut self, cx: &LateContext<'_>, _: &rustc_hir::Item<'_>) {
87+
// dbg!(clippy_utils::lookup_path_str(
88+
// cx.tcx,
89+
// clippy_utils::PathNS::Type,
90+
// "std::boxed::Box::downcast"
91+
// ));
92+
// }
8593
}

clippy_lints/src/await_holding_invalid.rs

+6-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_config::Conf;
22
use clippy_config::types::{DisallowedPathWithoutReplacement, create_disallowed_map};
33
use clippy_utils::diagnostics::span_lint_and_then;
4-
use clippy_utils::{match_def_path, paths};
4+
use clippy_utils::{PathNS, paths};
55
use rustc_hir as hir;
66
use rustc_hir::def_id::{DefId, DefIdMap};
77
use rustc_lint::{LateContext, LateLintPass};
@@ -182,6 +182,7 @@ impl AwaitHolding {
182182
let (def_ids, _) = create_disallowed_map(
183183
tcx,
184184
&conf.await_holding_invalid_types,
185+
PathNS::Type,
185186
crate::disallowed_types::def_kind_predicate,
186187
"type",
187188
false,
@@ -275,12 +276,10 @@ fn emit_invalid_type(
275276
}
276277

277278
fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
278-
cx.tcx.is_diagnostic_item(sym::MutexGuard, def_id)
279-
|| cx.tcx.is_diagnostic_item(sym::RwLockReadGuard, def_id)
280-
|| cx.tcx.is_diagnostic_item(sym::RwLockWriteGuard, def_id)
281-
|| match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
282-
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
283-
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
279+
match cx.tcx.get_diagnostic_name(def_id) {
280+
Some(name) => matches!(name, sym::MutexGuard | sym::RwLockReadGuard | sym::RwLockWriteGuard),
281+
None => paths::PARKING_LOT_GUARDS.iter().any(|guard| guard.matches(cx, def_id)),
282+
}
284283
}
285284

286285
fn is_refcell_ref(cx: &LateContext<'_>, def_id: DefId) -> bool {

clippy_lints/src/casts/manual_dangling_ptr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::SpanRangeExt;
3-
use clippy_utils::{expr_or_init, match_def_path, path_def_id, paths, std_or_core};
3+
use clippy_utils::{expr_or_init, path_def_id, paths, std_or_core};
44
use rustc_ast::LitKind;
55
use rustc_errors::Applicability;
66
use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, Ty, TyKind};
@@ -54,7 +54,7 @@ fn is_expr_const_aligned(cx: &LateContext<'_>, expr: &Expr<'_>, to: &Ty<'_>) ->
5454
fn is_align_of_call(cx: &LateContext<'_>, fun: &Expr<'_>, to: &Ty<'_>) -> bool {
5555
if let ExprKind::Path(QPath::Resolved(_, path)) = fun.kind
5656
&& let Some(fun_id) = path_def_id(cx, fun)
57-
&& match_def_path(cx, fun_id, &paths::ALIGN_OF)
57+
&& paths::ALIGN_OF.matches(cx, fun_id)
5858
&& let Some(args) = path.segments.last().and_then(|seg| seg.args)
5959
&& let [GenericArg::Type(generic_ty)] = args.args
6060
{

clippy_lints/src/derive.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use std::ops::ControlFlow;
22

33
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_then, span_lint_hir_and_then};
44
use clippy_utils::ty::{implements_trait, implements_trait_with_env, is_copy};
5-
use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, match_def_path, paths};
5+
use clippy_utils::{has_non_exhaustive_attr, is_lint_allowed, paths};
66
use rustc_errors::Applicability;
77
use rustc_hir::def_id::DefId;
88
use rustc_hir::intravisit::{FnKind, Visitor, walk_expr, walk_fn, walk_item};
@@ -377,7 +377,7 @@ fn check_unsafe_derive_deserialize<'tcx>(
377377
}
378378

379379
if let Some(trait_def_id) = trait_ref.trait_def_id()
380-
&& match_def_path(cx, trait_def_id, &paths::SERDE_DESERIALIZE)
380+
&& paths::SERDE_DESERIALIZE.matches(cx, trait_def_id)
381381
&& let ty::Adt(def, _) = ty.kind()
382382
&& let Some(local_def_id) = def.did().as_local()
383383
&& let adt_hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id)

clippy_lints/src/disallowed_macros.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use clippy_config::Conf;
22
use clippy_config::types::{DisallowedPath, create_disallowed_map};
3+
use clippy_utils::PathNS;
34
use clippy_utils::diagnostics::{span_lint_and_then, span_lint_hir_and_then};
45
use clippy_utils::macros::macro_backtrace;
56
use rustc_data_structures::fx::FxHashSet;
@@ -75,6 +76,7 @@ impl DisallowedMacros {
7576
let (disallowed, _) = create_disallowed_map(
7677
tcx,
7778
&conf.disallowed_macros,
79+
PathNS::Macro,
7880
|def_kind| matches!(def_kind, DefKind::Macro(_)),
7981
"macro",
8082
false,

clippy_lints/src/disallowed_methods.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use clippy_config::Conf;
22
use clippy_config::types::{DisallowedPath, create_disallowed_map};
3+
use clippy_utils::PathNS;
34
use clippy_utils::diagnostics::span_lint_and_then;
45
use rustc_hir::def::{CtorKind, DefKind, Res};
56
use rustc_hir::def_id::DefIdMap;
@@ -66,6 +67,7 @@ impl DisallowedMethods {
6667
let (disallowed, _) = create_disallowed_map(
6768
tcx,
6869
&conf.disallowed_methods,
70+
PathNS::Value,
6971
|def_kind| {
7072
matches!(
7173
def_kind,

clippy_lints/src/disallowed_types.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use clippy_config::Conf;
22
use clippy_config::types::{DisallowedPath, create_disallowed_map};
3+
use clippy_utils::PathNS;
34
use clippy_utils::diagnostics::span_lint_and_then;
45
use rustc_data_structures::fx::FxHashMap;
56
use rustc_hir::def::{DefKind, Res};
@@ -60,7 +61,14 @@ pub struct DisallowedTypes {
6061

6162
impl DisallowedTypes {
6263
pub fn new(tcx: TyCtxt<'_>, conf: &'static Conf) -> Self {
63-
let (def_ids, prim_tys) = create_disallowed_map(tcx, &conf.disallowed_types, def_kind_predicate, "type", true);
64+
let (def_ids, prim_tys) = create_disallowed_map(
65+
tcx,
66+
&conf.disallowed_types,
67+
PathNS::Type,
68+
def_kind_predicate,
69+
"type",
70+
true,
71+
);
6472
Self { def_ids, prim_tys }
6573
}
6674

clippy_lints/src/functions/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ mod too_many_arguments;
99
mod too_many_lines;
1010

1111
use clippy_config::Conf;
12-
use clippy_utils::def_path_def_ids;
1312
use clippy_utils::msrvs::Msrv;
13+
use clippy_utils::{PathNS, lookup_path_str};
1414
use rustc_hir as hir;
1515
use rustc_hir::intravisit;
1616
use rustc_lint::{LateContext, LateLintPass};
@@ -469,7 +469,7 @@ impl Functions {
469469
trait_ids: conf
470470
.allow_renamed_params_for
471471
.iter()
472-
.flat_map(|p| def_path_def_ids(tcx, &p.split("::").collect::<Vec<_>>()))
472+
.flat_map(|p| lookup_path_str(tcx, PathNS::Type, p))
473473
.collect(),
474474
msrv: conf.msrv,
475475
}

clippy_lints/src/let_underscore.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
2+
use clippy_utils::ty::{implements_trait, is_must_use_ty};
33
use clippy_utils::{is_from_proc_macro, is_must_use_func_call, paths};
44
use rustc_hir::{LetStmt, LocalSource, PatKind};
55
use rustc_lint::{LateContext, LateLintPass};
@@ -129,12 +129,6 @@ declare_clippy_lint! {
129129

130130
declare_lint_pass!(LetUnderscore => [LET_UNDERSCORE_MUST_USE, LET_UNDERSCORE_LOCK, LET_UNDERSCORE_FUTURE, LET_UNDERSCORE_UNTYPED]);
131131

132-
const SYNC_GUARD_PATHS: [&[&str]; 3] = [
133-
&paths::PARKING_LOT_MUTEX_GUARD,
134-
&paths::PARKING_LOT_RWLOCK_READ_GUARD,
135-
&paths::PARKING_LOT_RWLOCK_WRITE_GUARD,
136-
];
137-
138132
impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
139133
fn check_local(&mut self, cx: &LateContext<'tcx>, local: &LetStmt<'tcx>) {
140134
if matches!(local.source, LocalSource::Normal)
@@ -144,7 +138,9 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
144138
{
145139
let init_ty = cx.typeck_results().expr_ty(init);
146140
let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
147-
GenericArgKind::Type(inner_ty) => SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)),
141+
GenericArgKind::Type(inner_ty) => inner_ty
142+
.ty_adt_def()
143+
.is_some_and(|adt| paths::PARKING_LOT_GUARDS.iter().any(|path| path.matches(cx, adt.did()))),
148144
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
149145
});
150146
if contains_sync_guard {

clippy_lints/src/manual_option_as_slice.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_config::Conf;
22
use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg};
33
use clippy_utils::msrvs::Msrv;
4-
use clippy_utils::{is_none_arm, msrvs, peel_hir_expr_refs, sym};
4+
use clippy_utils::{is_none_arm, msrvs, paths, peel_hir_expr_refs, sym};
55
use rustc_errors::Applicability;
66
use rustc_hir::def::{DefKind, Res};
77
use rustc_hir::{Arm, Expr, ExprKind, LangItem, Pat, PatKind, QPath, is_range_literal};
@@ -220,5 +220,5 @@ fn is_empty_slice(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
220220
}
221221

222222
fn is_slice_from_ref(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
223-
clippy_utils::is_expr_path_def_path(cx, expr, &["core", "slice", "raw", "from_ref"])
223+
paths::SLICE_FROM_REF.matches_path(cx, expr)
224224
}

0 commit comments

Comments
 (0)