Skip to content

Commit f985c2b

Browse files
committed
Replace str path utils with new PathLookup type
1 parent 0dd9722 commit f985c2b

Some content is hidden

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

63 files changed

+550
-1282
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 1 deletion
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

Lines changed: 2 additions & 2 deletions
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

Lines changed: 9 additions & 7 deletions
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_config/src/types.rs

Lines changed: 32 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use rustc_data_structures::fx::FxHashMap;
22
use rustc_errors::{Applicability, Diag};
33
use rustc_hir::PrimTy;
4-
use rustc_hir::def::{DefKind, Res};
4+
use rustc_hir::def::DefKind;
55
use rustc_hir::def_id::DefIdMap;
66
use rustc_middle::ty::TyCtxt;
7-
use rustc_span::Span;
7+
use rustc_span::{Span, Symbol};
88
use serde::de::{self, Deserializer, Visitor};
99
use serde::{Deserialize, Serialize, ser};
1010
use std::collections::HashMap;
@@ -145,57 +145,41 @@ pub fn create_disallowed_map<const REPLACEMENT_ALLOWED: bool>(
145145
FxHashMap::default();
146146
for disallowed_path in disallowed_paths {
147147
let path = disallowed_path.path();
148-
let mut resolutions = clippy_utils::def_path_res(tcx, &path.split("::").collect::<Vec<_>>());
149-
150-
let mut found_def_id = None;
151-
let mut found_prim_ty = false;
152-
resolutions.retain(|res| match res {
153-
Res::Def(def_kind, def_id) => {
154-
found_def_id = Some(*def_id);
155-
def_kind_predicate(*def_kind)
156-
},
157-
Res::PrimTy(_) => {
158-
found_prim_ty = true;
159-
allow_prim_tys
160-
},
161-
_ => false,
162-
});
148+
let sym_path: Vec<Symbol> = path.split("::").map(Symbol::intern).collect();
149+
let mut resolutions = clippy_utils::lookup_path(tcx, &sym_path);
163150

164-
if resolutions.is_empty() {
165-
let span = disallowed_path.span();
151+
let found_def_id = resolutions.first().copied();
152+
resolutions.retain(|&def_id| def_kind_predicate(tcx.def_kind(def_id)));
166153

167-
if let Some(def_id) = found_def_id {
168-
tcx.sess.dcx().span_warn(
169-
span,
170-
format!(
171-
"expected a {predicate_description}, found {} {}",
172-
tcx.def_descr_article(def_id),
173-
tcx.def_descr(def_id)
174-
),
175-
);
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+
162+
if resolutions.is_empty() && prim_ty.is_none() && !disallowed_path.allow_invalid {
163+
let message = if let Some(def_id) = found_def_id {
164+
let (article, description) = tcx.article_and_description(def_id);
165+
format!("expected a {predicate_description}, found {article} {description}")
176166
} else if found_prim_ty {
177-
tcx.sess.dcx().span_warn(
178-
span,
179-
format!("expected a {predicate_description}, found a primitive type",),
180-
);
181-
} else if !disallowed_path.allow_invalid {
182-
tcx.sess.dcx().span_warn(
183-
span,
184-
format!("`{path}` does not refer to an existing {predicate_description}"),
185-
);
186-
}
167+
format!("expected a {predicate_description}, found a primitive type")
168+
} else {
169+
format!("`{path}` does not refer to a reachable {predicate_description}")
170+
};
171+
tcx.sess
172+
.dcx()
173+
.struct_span_warn(disallowed_path.span(), message)
174+
.with_help("add `allow-invalid = true` to the entry to suppress this warning")
175+
.emit();
187176
}
188177

189-
for res in resolutions {
190-
match res {
191-
Res::Def(_, def_id) => {
192-
def_ids.insert(def_id, (path, disallowed_path));
193-
},
194-
Res::PrimTy(ty) => {
195-
prim_tys.insert(ty, (path, disallowed_path));
196-
},
197-
_ => unreachable!(),
198-
}
178+
for def_id in resolutions {
179+
def_ids.insert(def_id, (path, disallowed_path));
180+
}
181+
if let Some(ty) = prim_ty {
182+
prim_tys.insert(ty, (path, disallowed_path));
199183
}
200184
}
201185

clippy_lints/src/await_holding_invalid.rs

Lines changed: 5 additions & 7 deletions
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::paths;
55
use rustc_hir as hir;
66
use rustc_hir::def_id::{DefId, DefIdMap};
77
use rustc_lint::{LateContext, LateLintPass};
@@ -275,12 +275,10 @@ fn emit_invalid_type(
275275
}
276276

277277
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)
278+
match cx.tcx.get_diagnostic_name(def_id) {
279+
Some(name) => matches!(name, sym::MutexGuard | sym::RwLockReadGuard | sym::RwLockWriteGuard),
280+
None => paths::PARKING_LOT_GUARDS.iter().any(|guard| guard.matches(cx, def_id)),
281+
}
284282
}
285283

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

clippy_lints/src/casts/manual_dangling_ptr.rs

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

clippy_lints/src/derive.rs

Lines changed: 2 additions & 2 deletions
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/functions/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod too_many_arguments;
99
mod too_many_lines;
1010

1111
use clippy_config::Conf;
12-
use clippy_utils::def_path_def_ids;
12+
use clippy_utils::lookup_path_str;
1313
use clippy_utils::msrvs::Msrv;
1414
use rustc_hir as hir;
1515
use rustc_hir::intravisit;
@@ -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, p))
473473
.collect(),
474474
msrv: conf.msrv,
475475
}

clippy_lints/src/let_underscore.rs

Lines changed: 4 additions & 8 deletions
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

Lines changed: 2 additions & 2 deletions
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
}

clippy_lints/src/methods/io_other_error.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::msrvs::{self, Msrv};
3+
use clippy_utils::{expr_or_init, paths};
34
use rustc_errors::Applicability;
45
use rustc_hir::{Expr, ExprKind, QPath};
56
use rustc_lint::LateContext;
@@ -8,13 +9,9 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, path: &Expr<'_>, args
89
if let [error_kind, error] = args
910
&& !expr.span.from_expansion()
1011
&& !error_kind.span.from_expansion()
11-
&& clippy_utils::is_expr_path_def_path(cx, path, &clippy_utils::paths::IO_ERROR_NEW)
12-
&& clippy_utils::is_expr_path_def_path(
13-
cx,
14-
clippy_utils::expr_or_init(cx, error_kind),
15-
&clippy_utils::paths::IO_ERRORKIND_OTHER,
16-
)
1712
&& let ExprKind::Path(QPath::TypeRelative(_, new_segment)) = path.kind
13+
&& paths::IO_ERROR_NEW.matches_path(cx, path)
14+
&& paths::IO_ERRORKIND_OTHER.matches_path(cx, expr_or_init(cx, error_kind))
1815
&& msrv.meets(cx, msrvs::IO_ERROR_OTHER)
1916
{
2017
span_lint_and_then(

clippy_lints/src/methods/manual_saturating_arithmetic.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_with_applicability;
3-
use clippy_utils::{match_def_path, path_def_id};
3+
use clippy_utils::{path_res, sym};
44
use rustc_ast::ast;
55
use rustc_errors::Applicability;
66
use rustc_hir as hir;
7+
use rustc_hir::def::Res;
78
use rustc_lint::LateContext;
89
use rustc_middle::ty::layout::LayoutOf;
910

@@ -79,16 +80,15 @@ fn is_min_or_max(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<MinMax> {
7980
}
8081

8182
let ty = cx.typeck_results().expr_ty(expr);
82-
let ty_str = ty.to_string();
8383

84-
// `std::T::MAX` `std::T::MIN` constants
85-
if let Some(id) = path_def_id(cx, expr) {
86-
if match_def_path(cx, id, &["core", &ty_str, "MAX"]) {
87-
return Some(MinMax::Max);
88-
}
89-
90-
if match_def_path(cx, id, &["core", &ty_str, "MIN"]) {
91-
return Some(MinMax::Min);
84+
// `T::MAX` and `T::MIN` constants
85+
if let hir::ExprKind::Path(hir::QPath::TypeRelative(base, seg)) = expr.kind
86+
&& let Res::PrimTy(_) = path_res(cx, base)
87+
{
88+
match seg.ident.name {
89+
sym::MAX => return Some(MinMax::Max),
90+
sym::MIN => return Some(MinMax::Min),
91+
_ => {},
9292
}
9393
}
9494

clippy_lints/src/methods/needless_character_iteration.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ use rustc_span::Span;
77
use super::NEEDLESS_CHARACTER_ITERATION;
88
use super::utils::get_last_chain_binding_hir_id;
99
use clippy_utils::diagnostics::span_lint_and_sugg;
10-
use clippy_utils::paths::CHAR_IS_ASCII;
1110
use clippy_utils::source::SpanRangeExt;
12-
use clippy_utils::{match_def_path, path_to_local_id, peel_blocks, sym};
11+
use clippy_utils::{is_path_diagnostic_item, path_to_local_id, peel_blocks, sym};
1312

1413
fn peels_expr_ref<'a, 'tcx>(mut expr: &'a Expr<'tcx>) -> &'a Expr<'tcx> {
1514
while let ExprKind::AddrOf(_, _, e) = expr.kind {
@@ -76,9 +75,7 @@ fn handle_expr(
7675
// If we have `!is_ascii`, then only `.any()` should warn. And if the condition is
7776
// `is_ascii`, then only `.all()` should warn.
7877
if revert != is_all
79-
&& let ExprKind::Path(path) = fn_path.kind
80-
&& let Some(fn_def_id) = cx.qpath_res(&path, fn_path.hir_id).opt_def_id()
81-
&& match_def_path(cx, fn_def_id, &CHAR_IS_ASCII)
78+
&& is_path_diagnostic_item(cx, fn_path, sym::char_is_ascii)
8279
&& path_to_local_id(peels_expr_ref(arg), first_param)
8380
&& let Some(snippet) = before_chars.get_source_text(cx)
8481
{

0 commit comments

Comments
 (0)