Skip to content

Commit 383149e

Browse files
committed
Auto merge of rust-lang#121625 - Urgau:non-local-defs_recover_perf, r=<try>
Recover most of the perf loss of rust-lang#120393 [rust-lang#120393](rust-lang#120393 (comment)) draft for perf
2 parents 91cae1d + 0903c02 commit 383149e

File tree

3 files changed

+136
-92
lines changed

3 files changed

+136
-92
lines changed

compiler/rustc_lint/src/non_local_def.rs

+85-41
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
1+
use rustc_hir::{Body, Item, ItemKind, OwnerNode, Path, QPath, TyKind};
22
use rustc_span::def_id::{DefId, LOCAL_CRATE};
3-
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
4-
5-
use smallvec::{smallvec, SmallVec};
3+
use rustc_span::{sym, symbol::kw, symbol::Ident, ExpnKind, MacroKind};
64

75
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
86
use crate::{LateContext, LateLintPass, LintContext};
@@ -67,17 +65,14 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
6765
return;
6866
}
6967

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);
73-
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-
}
68+
let mut parent_node = {
69+
let mut parent_node_cache = None;
70+
move || {
71+
*parent_node_cache.get_or_insert_with(|| {
72+
cx.tcx.hir().parent_owner_iter(item.hir_id()).next().unwrap().1
73+
})
74+
}
75+
};
8176

8277
let cargo_update = || {
8378
let oexpn = item.span.ctxt().outer_expn_data();
@@ -112,26 +107,50 @@ 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]
110+
let mut parent_node_is_anon_const = {
111+
let mut parent_node_is_anon_const = None;
112+
move || {
113+
*parent_node_is_anon_const.get_or_insert_with(|| {
114+
matches!(
115+
parent_node(),
116+
OwnerNode::Item(Item {
117+
ident: Ident { name: kw::Underscore, .. },
118+
kind: ItemKind::Const(..),
119+
..
120+
})
121+
)
122+
})
123+
}
124+
};
125+
let mut local_parent = {
126+
let mut local_parent_cache = None;
127+
move || {
128+
*local_parent_cache
129+
.get_or_insert_with(|| cx.tcx.parent(item.owner_id.to_def_id()))
130+
}
131+
};
132+
let mut extra_local_parent = {
133+
let mut extra_parent_cache = None;
134+
move |did| {
135+
*extra_parent_cache.get_or_insert_with(|| {
136+
parent_node_is_anon_const().then(|| cx.tcx.parent(did))
137+
})
138+
}
124139
};
125140

126141
let self_ty_has_local_parent = match impl_.self_ty.kind {
127-
TyKind::Path(QPath::Resolved(_, ty_path)) => {
128-
path_has_local_parent(ty_path, cx, &*local_parents)
129-
}
142+
TyKind::Path(QPath::Resolved(_, ty_path)) => path_has_local_parent(
143+
ty_path,
144+
cx,
145+
&mut local_parent,
146+
&mut extra_local_parent,
147+
),
130148
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
131149
path_has_local_parent(
132150
principle_poly_trait_ref.trait_ref.path,
133151
cx,
134-
&*local_parents,
152+
&mut local_parent,
153+
&mut extra_local_parent,
135154
)
136155
}
137156
TyKind::TraitObject([], _, _)
@@ -153,17 +172,26 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
153172

154173
let of_trait_has_local_parent = impl_
155174
.of_trait
156-
.map(|of_trait| path_has_local_parent(of_trait.path, cx, &*local_parents))
175+
.map(|of_trait| {
176+
path_has_local_parent(
177+
of_trait.path,
178+
cx,
179+
&mut local_parent,
180+
&mut extra_local_parent,
181+
)
182+
})
157183
.unwrap_or(false);
158184

159185
// If none of them have a local parent (LOGICAL NOR) this means that
160186
// this impl definition is a non-local definition and so we lint on it.
161187
if !(self_ty_has_local_parent || of_trait_has_local_parent) {
188+
// Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
189+
if parent_node_is_anon_const() && self.body_depth == 1 {
190+
return;
191+
}
192+
162193
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)
194+
&& let OwnerNode::Item(item) = parent_node()
167195
&& let ItemKind::Const(ty, _, _) = item.kind
168196
&& let TyKind::Tup(&[]) = ty.kind
169197
{
@@ -177,9 +205,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
177205
item.span,
178206
NonLocalDefinitionsDiag::Impl {
179207
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())
208+
body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
209+
body_name: parent_node()
210+
.ident()
211+
.map(|s| s.name.to_ident_string())
183212
.unwrap_or_else(|| "<unnameable>".to_string()),
184213
cargo_update: cargo_update(),
185214
const_anon,
@@ -195,9 +224,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
195224
item.span,
196225
NonLocalDefinitionsDiag::MacroRules {
197226
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())
227+
body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
228+
body_name: parent_node()
229+
.ident()
230+
.map(|s| s.name.to_ident_string())
201231
.unwrap_or_else(|| "<unnameable>".to_string()),
202232
cargo_update: cargo_update(),
203233
},
@@ -217,6 +247,20 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
217247
/// std::convert::PartialEq<Foo<Bar>>
218248
/// ^^^^^^^^^^^^^^^^^^^^^^^
219249
/// ```
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)))
250+
fn path_has_local_parent(
251+
path: &Path<'_>,
252+
cx: &LateContext<'_>,
253+
local_parent: &mut impl FnMut() -> DefId,
254+
extra_local_parent: &mut impl FnMut(DefId) -> Option<DefId>,
255+
) -> bool {
256+
if let Some(did) = path.res.opt_def_id() {
257+
if !did.is_local() {
258+
false
259+
} else {
260+
let res_parent = cx.tcx.parent(did);
261+
res_parent == local_parent() || Some(res_parent) == extra_local_parent(local_parent())
262+
}
263+
} else {
264+
true
265+
}
222266
}

0 commit comments

Comments
 (0)