Skip to content

Commit f60186f

Browse files
committed
Auto merge of #9800 - Alexendoo:def_path_res_multiple, r=dswij
Return multiple resolutions from `def_path_res` Changes `def_path_res` to return all the resolutions matching the path rather than the first one (with a namespace hint that covered some cases). This would fix any issues that come up with multiple versions of the same crate being present as they all have the same crate name It also adds resolution of `impl _ {}` items for local items, and removes struct field resolution as it didn't seem to be used anywhere I tested it on a local crate and it worked for the multiple crate issue, but I couldn't come up with a test that worked well with `// aux-build`, maybe `// aux-crate` after rust-lang/rust#103266 could work but I'm not sure on that either changelog: [`disallowed_methods`], [`disallowed_types`], [`disallowed_macros`]: fix path resolution with multiple versions of the same crate changelog: [`disallowed_methods`]: Resolve methods in `impl`s in the current crate
2 parents e144c7d + 1e1ac2b commit f60186f

15 files changed

+281
-236
lines changed

clippy_lints/src/await_holding_invalid.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::{match_def_path, paths};
33
use rustc_data_structures::fx::FxHashMap;
4-
use rustc_hir::def::{Namespace, Res};
54
use rustc_hir::def_id::DefId;
65
use rustc_hir::{AsyncGeneratorKind, Body, BodyId, GeneratorKind};
76
use rustc_lint::{LateContext, LateLintPass};
@@ -189,7 +188,7 @@ impl LateLintPass<'_> for AwaitHolding {
189188
fn check_crate(&mut self, cx: &LateContext<'_>) {
190189
for conf in &self.conf_invalid_types {
191190
let segs: Vec<_> = conf.path().split("::").collect();
192-
if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
191+
for id in clippy_utils::def_path_def_ids(cx, &segs) {
193192
self.def_ids.insert(id, conf.clone());
194193
}
195194
}

clippy_lints/src/disallowed_macros.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::macros::macro_backtrace;
33
use rustc_data_structures::fx::FxHashSet;
4-
use rustc_hir::def::{Namespace, Res};
54
use rustc_hir::def_id::DefIdMap;
65
use rustc_hir::{Expr, ForeignItem, HirId, ImplItem, Item, Pat, Path, Stmt, TraitItem, Ty};
76
use rustc_lint::{LateContext, LateLintPass};
@@ -89,7 +88,7 @@ impl DisallowedMacros {
8988
&format!("use of a disallowed macro `{}`", conf.path()),
9089
|diag| {
9190
if let Some(reason) = conf.reason() {
92-
diag.note(&format!("{reason} (from clippy.toml)"));
91+
diag.note(reason);
9392
}
9493
},
9594
);
@@ -104,7 +103,7 @@ impl LateLintPass<'_> for DisallowedMacros {
104103
fn check_crate(&mut self, cx: &LateContext<'_>) {
105104
for (index, conf) in self.conf_disallowed.iter().enumerate() {
106105
let segs: Vec<_> = conf.path().split("::").collect();
107-
if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::MacroNS)) {
106+
for id in clippy_utils::def_path_def_ids(cx, &segs) {
108107
self.disallowed.insert(id, index);
109108
}
110109
}

clippy_lints/src/disallowed_methods.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22
use clippy_utils::{fn_def_id, get_parent_expr, path_def_id};
33

4-
use rustc_hir::def::{Namespace, Res};
54
use rustc_hir::def_id::DefIdMap;
65
use rustc_hir::{Expr, ExprKind};
76
use rustc_lint::{LateContext, LateLintPass};
@@ -79,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
7978
fn check_crate(&mut self, cx: &LateContext<'_>) {
8079
for (index, conf) in self.conf_disallowed.iter().enumerate() {
8180
let segs: Vec<_> = conf.path().split("::").collect();
82-
if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, Some(Namespace::ValueNS)) {
81+
for id in clippy_utils::def_path_def_ids(cx, &segs) {
8382
self.disallowed.insert(id, index);
8483
}
8584
}
@@ -104,7 +103,7 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedMethods {
104103
let msg = format!("use of a disallowed method `{}`", conf.path());
105104
span_lint_and_then(cx, DISALLOWED_METHODS, expr.span, &msg, |diag| {
106105
if let Some(reason) = conf.reason() {
107-
diag.note(&format!("{reason} (from clippy.toml)"));
106+
diag.note(reason);
108107
}
109108
});
110109
}

clippy_lints/src/disallowed_types.rs

+21-19
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
22

33
use rustc_data_structures::fx::FxHashMap;
4-
use rustc_hir::def::{Namespace, Res};
4+
use rustc_hir::def::Res;
55
use rustc_hir::def_id::DefId;
66
use rustc_hir::{Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind};
77
use rustc_lint::{LateContext, LateLintPass};
@@ -53,8 +53,8 @@ declare_clippy_lint! {
5353
#[derive(Clone, Debug)]
5454
pub struct DisallowedTypes {
5555
conf_disallowed: Vec<conf::DisallowedPath>,
56-
def_ids: FxHashMap<DefId, Option<String>>,
57-
prim_tys: FxHashMap<PrimTy, Option<String>>,
56+
def_ids: FxHashMap<DefId, usize>,
57+
prim_tys: FxHashMap<PrimTy, usize>,
5858
}
5959

6060
impl DisallowedTypes {
@@ -69,13 +69,13 @@ impl DisallowedTypes {
6969
fn check_res_emit(&self, cx: &LateContext<'_>, res: &Res, span: Span) {
7070
match res {
7171
Res::Def(_, did) => {
72-
if let Some(reason) = self.def_ids.get(did) {
73-
emit(cx, &cx.tcx.def_path_str(*did), span, reason.as_deref());
72+
if let Some(&index) = self.def_ids.get(did) {
73+
emit(cx, &cx.tcx.def_path_str(*did), span, &self.conf_disallowed[index]);
7474
}
7575
},
7676
Res::PrimTy(prim) => {
77-
if let Some(reason) = self.prim_tys.get(prim) {
78-
emit(cx, prim.name_str(), span, reason.as_deref());
77+
if let Some(&index) = self.prim_tys.get(prim) {
78+
emit(cx, prim.name_str(), span, &self.conf_disallowed[index]);
7979
}
8080
},
8181
_ => {},
@@ -87,17 +87,19 @@ impl_lint_pass!(DisallowedTypes => [DISALLOWED_TYPES]);
8787

8888
impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
8989
fn check_crate(&mut self, cx: &LateContext<'_>) {
90-
for conf in &self.conf_disallowed {
90+
for (index, conf) in self.conf_disallowed.iter().enumerate() {
9191
let segs: Vec<_> = conf.path().split("::").collect();
92-
let reason = conf.reason().map(|reason| format!("{reason} (from clippy.toml)"));
93-
match clippy_utils::def_path_res(cx, &segs, Some(Namespace::TypeNS)) {
94-
Res::Def(_, id) => {
95-
self.def_ids.insert(id, reason);
96-
},
97-
Res::PrimTy(ty) => {
98-
self.prim_tys.insert(ty, reason);
99-
},
100-
_ => {},
92+
93+
for res in clippy_utils::def_path_res(cx, &segs) {
94+
match res {
95+
Res::Def(_, id) => {
96+
self.def_ids.insert(id, index);
97+
},
98+
Res::PrimTy(ty) => {
99+
self.prim_tys.insert(ty, index);
100+
},
101+
_ => {},
102+
}
101103
}
102104
}
103105
}
@@ -119,14 +121,14 @@ impl<'tcx> LateLintPass<'tcx> for DisallowedTypes {
119121
}
120122
}
121123

122-
fn emit(cx: &LateContext<'_>, name: &str, span: Span, reason: Option<&str>) {
124+
fn emit(cx: &LateContext<'_>, name: &str, span: Span, conf: &conf::DisallowedPath) {
123125
span_lint_and_then(
124126
cx,
125127
DISALLOWED_TYPES,
126128
span,
127129
&format!("`{name}` is not allowed according to config"),
128130
|diag| {
129-
if let Some(reason) = reason {
131+
if let Some(reason) = conf.reason() {
130132
diag.note(reason);
131133
}
132134
},

clippy_lints/src/missing_enforced_import_rename.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ impl LateLintPass<'_> for ImportRename {
5959
fn check_crate(&mut self, cx: &LateContext<'_>) {
6060
for Rename { path, rename } in &self.conf_renames {
6161
let segs = path.split("::").collect::<Vec<_>>();
62-
if let Res::Def(_, id) = clippy_utils::def_path_res(cx, &segs, None) {
62+
for id in clippy_utils::def_path_def_ids(cx, &segs) {
6363
self.renames.insert(id, Symbol::intern(rename));
6464
}
6565
}

clippy_lints/src/mut_key.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use clippy_utils::diagnostics::span_lint;
2-
use clippy_utils::{def_path_res, trait_ref_of_method};
2+
use clippy_utils::{def_path_def_ids, trait_ref_of_method};
33
use rustc_data_structures::fx::FxHashSet;
44
use rustc_hir as hir;
5-
use rustc_hir::def::Namespace;
65
use rustc_lint::{LateContext, LateLintPass};
76
use rustc_middle::ty::TypeVisitable;
87
use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
@@ -94,7 +93,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableKeyType {
9493
let mut path = Vec::new();
9594
for ty in &self.ignore_interior_mutability {
9695
path.extend(ty.split("::"));
97-
if let Some(id) = def_path_res(cx, &path[..], Some(Namespace::TypeNS)).opt_def_id() {
96+
for id in def_path_def_ids(cx, &path[..]) {
9897
self.ignore_mut_def_ids.insert(id);
9998
}
10099
path.clear();

clippy_lints/src/utils/conf.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ impl DisallowedPath {
5353
path
5454
}
5555

56-
pub fn reason(&self) -> Option<&str> {
56+
pub fn reason(&self) -> Option<String> {
5757
match self {
5858
Self::WithReason {
5959
reason: Some(reason), ..
60-
} => Some(reason),
60+
} => Some(format!("{reason} (from clippy.toml)")),
6161
_ => None,
6262
}
6363
}

clippy_lints/src/utils/internal_lints/interning_defined_symbol.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use clippy_utils::consts::{constant_simple, Constant};
22
use clippy_utils::diagnostics::span_lint_and_sugg;
33
use clippy_utils::source::snippet;
44
use clippy_utils::ty::match_type;
5-
use clippy_utils::{def_path_res, is_expn_of, match_def_path, paths};
5+
use clippy_utils::{def_path_def_ids, is_expn_of, match_def_path, paths};
66
use if_chain::if_chain;
77
use rustc_data_structures::fx::FxHashMap;
88
use rustc_errors::Applicability;
@@ -74,7 +74,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
7474
}
7575

7676
for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
77-
if let Some(def_id) = def_path_res(cx, module, None).opt_def_id() {
77+
for def_id in def_path_def_ids(cx, module) {
7878
for item in cx.tcx.module_children(def_id).iter() {
7979
if_chain! {
8080
if let Res::Def(DefKind::Const, item_def_id) = item.res;

clippy_lints/src/utils/internal_lints/invalid_paths.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::def_path_res;
33
use clippy_utils::diagnostics::span_lint;
44
use if_chain::if_chain;
55
use rustc_hir as hir;
6-
use rustc_hir::def::{DefKind, Res};
6+
use rustc_hir::def::DefKind;
77
use rustc_hir::Item;
88
use rustc_hir_analysis::hir_ty_to_ty;
99
use rustc_lint::{LateContext, LateLintPass};
@@ -63,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidPaths {
6363
// This is not a complete resolver for paths. It works on all the paths currently used in the paths
6464
// module. That's all it does and all it needs to do.
6565
pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
66-
if def_path_res(cx, path, None) != Res::Err {
66+
if !def_path_res(cx, path).is_empty() {
6767
return true;
6868
}
6969

clippy_lints/src/utils/internal_lints/unnecessary_def_path.rs

+9-39
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
22
use clippy_utils::source::snippet_with_applicability;
3-
use clippy_utils::{def_path_res, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
3+
use clippy_utils::{def_path_def_ids, is_lint_allowed, match_any_def_paths, peel_hir_expr_refs};
44
use if_chain::if_chain;
55
use rustc_ast::ast::LitKind;
66
use rustc_data_structures::fx::FxHashSet;
77
use rustc_errors::Applicability;
88
use rustc_hir as hir;
9-
use rustc_hir::def::{DefKind, Namespace, Res};
9+
use rustc_hir::def::{DefKind, Res};
1010
use rustc_hir::def_id::DefId;
1111
use rustc_hir::{Expr, ExprKind, Local, Mutability, Node};
1212
use rustc_lint::{LateContext, LateLintPass};
1313
use rustc_middle::mir::interpret::{Allocation, ConstValue, GlobalAlloc};
14-
use rustc_middle::ty::{self, AssocKind, DefIdTree, Ty};
14+
use rustc_middle::ty::{self, DefIdTree, Ty};
1515
use rustc_session::{declare_tool_lint, impl_lint_pass};
16-
use rustc_span::symbol::{Ident, Symbol};
16+
use rustc_span::symbol::Symbol;
1717
use rustc_span::Span;
1818

1919
use std::str;
@@ -110,7 +110,7 @@ impl UnnecessaryDefPath {
110110
// Extract the path to the matched type
111111
if let Some(segments) = path_to_matched_type(cx, item_arg);
112112
let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
113-
if let Some(def_id) = inherent_def_path_res(cx, &segments[..]);
113+
if let Some(def_id) = def_path_def_ids(cx, &segments[..]).next();
114114
then {
115115
// Check if the target item is a diagnostic item or LangItem.
116116
#[rustfmt::skip]
@@ -209,7 +209,7 @@ impl UnnecessaryDefPath {
209209
fn check_array(&mut self, cx: &LateContext<'_>, elements: &[Expr<'_>], span: Span) {
210210
let Some(path) = path_from_array(elements) else { return };
211211

212-
if let Some(def_id) = inherent_def_path_res(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
212+
for def_id in def_path_def_ids(cx, &path.iter().map(AsRef::as_ref).collect::<Vec<_>>()) {
213213
self.array_def_ids.insert((def_id, span));
214214
}
215215
}
@@ -293,41 +293,11 @@ fn path_from_array(exprs: &[Expr<'_>]) -> Option<Vec<String>> {
293293
.collect()
294294
}
295295

296-
// def_path_res will match field names before anything else, but for this we want to match
297-
// inherent functions first.
298-
fn inherent_def_path_res(cx: &LateContext<'_>, segments: &[&str]) -> Option<DefId> {
299-
def_path_res(cx, segments, None).opt_def_id().map(|def_id| {
300-
if cx.tcx.def_kind(def_id) == DefKind::Field {
301-
let method_name = *segments.last().unwrap();
302-
cx.tcx
303-
.def_key(def_id)
304-
.parent
305-
.and_then(|parent_idx| {
306-
cx.tcx
307-
.inherent_impls(DefId {
308-
index: parent_idx,
309-
krate: def_id.krate,
310-
})
311-
.iter()
312-
.find_map(|impl_id| {
313-
cx.tcx.associated_items(*impl_id).find_by_name_and_kind(
314-
cx.tcx,
315-
Ident::from_str(method_name),
316-
AssocKind::Fn,
317-
*impl_id,
318-
)
319-
})
320-
})
321-
.map_or(def_id, |item| item.def_id)
322-
} else {
323-
def_id
324-
}
325-
})
326-
}
327-
328296
fn get_lang_item_name(cx: &LateContext<'_>, def_id: DefId) -> Option<Symbol> {
329297
if let Some(lang_item) = cx.tcx.lang_items().items().iter().position(|id| *id == Some(def_id)) {
330-
let lang_items = def_path_res(cx, &["rustc_hir", "lang_items", "LangItem"], Some(Namespace::TypeNS)).def_id();
298+
let lang_items = def_path_def_ids(cx, &["rustc_hir", "lang_items", "LangItem"])
299+
.next()
300+
.unwrap();
331301
let item_name = cx
332302
.tcx
333303
.adt_def(lang_items)

0 commit comments

Comments
 (0)