Skip to content

Commit 1974da7

Browse files
committed
Only use HIR in the non_local_def lint
1 parent f2a9356 commit 1974da7

File tree

4 files changed

+90
-60
lines changed

4 files changed

+90
-60
lines changed

Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -4101,7 +4101,6 @@ dependencies = [
41014101
"rustc_target",
41024102
"rustc_trait_selection",
41034103
"rustc_type_ir",
4104-
"smallvec",
41054104
"tracing",
41064105
"unicode-security",
41074106
]

compiler/rustc_lint/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ rustc_span = { path = "../rustc_span" }
2323
rustc_target = { path = "../rustc_target" }
2424
rustc_trait_selection = { path = "../rustc_trait_selection" }
2525
rustc_type_ir = { path = "../rustc_type_ir" }
26-
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
2726
tracing = "0.1"
2827
unicode-security = "0.1.0"
2928
# tidy-alphabetical-end

compiler/rustc_lint/src/non_local_def.rs

+74-42
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
2-
use rustc_span::def_id::{DefId, LOCAL_CRATE};
1+
use rustc_hir::def_id::LocalDefId;
2+
use rustc_hir::{Body, Item, ItemKind, OwnerId, OwnerNode, Path, QPath, TyKind};
3+
use rustc_span::def_id::LOCAL_CRATE;
4+
use rustc_span::symbol::Ident;
35
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
46

5-
use smallvec::{smallvec, SmallVec};
6-
77
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
88
use crate::{LateContext, LateLintPass, LintContext};
99

@@ -67,17 +67,12 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
6767
return;
6868
}
6969

70-
let parent = cx.tcx.parent(item.owner_id.def_id.into());
71-
let parent_def_kind = cx.tcx.def_kind(parent);
72-
let parent_opt_item_name = cx.tcx.opt_item_name(parent);
70+
let mut parent_iter = cx.tcx.hir().parent_owner_iter(item.hir_id());
7371

74-
// Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
75-
if self.body_depth == 1
76-
&& parent_def_kind == DefKind::Const
77-
&& parent_opt_item_name == Some(kw::Underscore)
78-
{
79-
return;
80-
}
72+
// Unwrap SAFETY: `ParentOwnerIterator` documentation garenties that
73+
// it only panic when reaching the crate root but we made sure above
74+
// that we are not at crate root. So we are fine here.
75+
let (parent_owner_id, parent_owner_node) = parent_iter.next().unwrap();
8176

8277
let cargo_update = || {
8378
let oexpn = item.span.ctxt().outer_expn_data();
@@ -112,26 +107,35 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
112107
// If that's the case this means that this impl block declaration
113108
// is using local items and so we don't lint on it.
114109

115-
// We also ignore anon-const in item by including the anon-const
116-
// parent as well; and since it's quite uncommon, we use smallvec
117-
// to avoid unnecessary heap allocations.
118-
let local_parents: SmallVec<[DefId; 1]> = if parent_def_kind == DefKind::Const
119-
&& parent_opt_item_name == Some(kw::Underscore)
120-
{
121-
smallvec![parent, cx.tcx.parent(parent)]
122-
} else {
123-
smallvec![parent]
124-
};
110+
let parent_owner_is_anon_const = matches!(
111+
parent_owner_node,
112+
OwnerNode::Item(Item {
113+
ident: Ident { name: kw::Underscore, .. },
114+
kind: ItemKind::Const(..),
115+
..
116+
})
117+
);
118+
119+
// Per RFC we (currently) ignore `impl` def in anon-const (`const _: Ty = ...`)
120+
// at the top-level module.
121+
if self.body_depth == 1 && parent_owner_is_anon_const {
122+
return;
123+
}
124+
125+
let parent_parent_def_id = parent_owner_is_anon_const
126+
.then(|| parent_iter.next().map(|(owner_id, _)| owner_id.def_id))
127+
.flatten();
125128

126129
let self_ty_has_local_parent = match impl_.self_ty.kind {
127130
TyKind::Path(QPath::Resolved(_, ty_path)) => {
128-
path_has_local_parent(ty_path, cx, &*local_parents)
131+
path_has_local_parent(ty_path, cx, parent_owner_id, parent_parent_def_id)
129132
}
130133
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
131134
path_has_local_parent(
132135
principle_poly_trait_ref.trait_ref.path,
133136
cx,
134-
&*local_parents,
137+
parent_owner_id,
138+
parent_parent_def_id,
135139
)
136140
}
137141
TyKind::TraitObject([], _, _)
@@ -151,19 +155,25 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
151155
| TyKind::Err(_) => false,
152156
};
153157

154-
let of_trait_has_local_parent = impl_
155-
.of_trait
156-
.map(|of_trait| path_has_local_parent(of_trait.path, cx, &*local_parents))
157-
.unwrap_or(false);
158+
let of_trait_has_local_parent = self_ty_has_local_parent
159+
|| impl_
160+
.of_trait
161+
.map(|of_trait| {
162+
path_has_local_parent(
163+
of_trait.path,
164+
cx,
165+
parent_owner_id,
166+
parent_parent_def_id,
167+
)
168+
})
169+
.unwrap_or(false);
158170

159171
// If none of them have a local parent (LOGICAL NOR) this means that
160172
// this impl definition is a non-local definition and so we lint on it.
161173
if !(self_ty_has_local_parent || of_trait_has_local_parent) {
162174
let const_anon = if self.body_depth == 1
163-
&& parent_def_kind == DefKind::Const
164-
&& parent_opt_item_name != Some(kw::Underscore)
165-
&& let Some(parent) = parent.as_local()
166-
&& let Node::Item(item) = cx.tcx.hir_node_by_def_id(parent)
175+
&& let OwnerNode::Item(item) = parent_owner_node
176+
&& item.ident.name != kw::Underscore
167177
&& let ItemKind::Const(ty, _, _) = item.kind
168178
&& let TyKind::Tup(&[]) = ty.kind
169179
{
@@ -177,9 +187,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
177187
item.span,
178188
NonLocalDefinitionsDiag::Impl {
179189
depth: self.body_depth,
180-
body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent),
181-
body_name: parent_opt_item_name
182-
.map(|s| s.to_ident_string())
190+
body_kind_descr: parent_owner_node.descr(),
191+
body_name: parent_owner_node
192+
.ident()
193+
.map(|s| s.name.to_ident_string())
183194
.unwrap_or_else(|| "<unnameable>".to_string()),
184195
cargo_update: cargo_update(),
185196
const_anon,
@@ -195,9 +206,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
195206
item.span,
196207
NonLocalDefinitionsDiag::MacroRules {
197208
depth: self.body_depth,
198-
body_kind_descr: cx.tcx.def_kind_descr(parent_def_kind, parent),
199-
body_name: parent_opt_item_name
200-
.map(|s| s.to_ident_string())
209+
body_kind_descr: parent_owner_node.descr(),
210+
body_name: parent_owner_node
211+
.ident()
212+
.map(|s| s.name.to_ident_string())
201213
.unwrap_or_else(|| "<unnameable>".to_string()),
202214
cargo_update: cargo_update(),
203215
},
@@ -217,6 +229,26 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
217229
/// std::convert::PartialEq<Foo<Bar>>
218230
/// ^^^^^^^^^^^^^^^^^^^^^^^
219231
/// ```
220-
fn path_has_local_parent(path: &Path<'_>, cx: &LateContext<'_>, local_parents: &[DefId]) -> bool {
221-
path.res.opt_def_id().is_some_and(|did| local_parents.contains(&cx.tcx.parent(did)))
232+
fn path_has_local_parent<'tcx>(
233+
path: &Path<'_>,
234+
cx: &LateContext<'tcx>,
235+
local_parent: OwnerId,
236+
extra_local_parent: Option<LocalDefId>,
237+
) -> bool {
238+
let Some(res_did) = path.res.opt_def_id() else {
239+
return true;
240+
};
241+
let Some(did) = res_did.as_local() else {
242+
return false;
243+
};
244+
245+
let res_parent = {
246+
let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(did) else {
247+
return true;
248+
};
249+
let owner_id = cx.tcx.hir().get_parent_item(hir_id);
250+
owner_id.def_id
251+
};
252+
253+
res_parent == local_parent.def_id || Some(res_parent) == extra_local_parent
222254
}

0 commit comments

Comments
 (0)