Skip to content

Commit acd70b2

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 d3d145e + 87a3a57 commit acd70b2

File tree

6 files changed

+147
-97
lines changed

6 files changed

+147
-97
lines changed

Cargo.lock

-1
Original file line numberDiff line numberDiff line change
@@ -4097,7 +4097,6 @@ dependencies = [
40974097
"rustc_target",
40984098
"rustc_trait_selection",
40994099
"rustc_type_ir",
4100-
"smallvec",
41014100
"tracing",
41024101
"unicode-security",
41034102
]

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

+95-43
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
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, Path, QPath, TyKind};
3+
use rustc_hir::{OwnerId, OwnerNode};
4+
use rustc_span::def_id::LOCAL_CRATE;
5+
use rustc_span::symbol::Ident;
36
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
47

5-
use smallvec::{smallvec, SmallVec};
6-
78
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
89
use crate::{LateContext, LateLintPass, LintContext};
910

@@ -67,24 +68,27 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
6768
return;
6869
}
6970

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;
71+
macro_rules! lazy {
72+
($ident:ident = $closure:expr) => {
73+
let cache = ::std::cell::RefCell::new(None);
74+
let $ident = || *cache.borrow_mut().get_or_insert_with($closure);
75+
};
8076
}
8177

78+
lazy!(
79+
parent_owner = || {
80+
// Unwrap safety: can only panic when reaching the crate root
81+
// but we made sure above that we are not at crate root.
82+
cx.tcx.hir().parent_owner_iter(item.hir_id()).next().unwrap()
83+
}
84+
);
85+
8286
let cargo_update = || {
8387
let oexpn = item.span.ctxt().outer_expn_data();
8488
if let Some(def_id) = oexpn.macro_def_id
8589
&& let ExpnKind::Macro(macro_kind, macro_name) = oexpn.kind
8690
&& def_id.krate != LOCAL_CRATE
87-
&& std::env::var_os("CARGO").is_some()
91+
&& rustc_session::utils::was_invoked_from_cargo()
8892
{
8993
Some(NonLocalDefinitionsCargoUpdateNote {
9094
macro_kind: macro_kind.descr(),
@@ -112,26 +116,39 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
112116
// If that's the case this means that this impl block declaration
113117
// is using local items and so we don't lint on it.
114118

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-
};
119+
lazy!(
120+
parent_owner_is_anon_const = || matches!(
121+
parent_owner().1,
122+
OwnerNode::Item(Item {
123+
ident: Ident { name: kw::Underscore, .. },
124+
kind: ItemKind::Const(..),
125+
..
126+
})
127+
)
128+
);
129+
lazy!(
130+
extra_local_parent = || parent_owner_is_anon_const()
131+
.then(|| {
132+
cx.tcx
133+
.hir()
134+
.parent_owner_iter(item.hir_id())
135+
.skip(1)
136+
.next()
137+
.map(|(owner_id, _owner_node)| owner_id.def_id)
138+
})
139+
.flatten()
140+
);
125141

126142
let self_ty_has_local_parent = match impl_.self_ty.kind {
127143
TyKind::Path(QPath::Resolved(_, ty_path)) => {
128-
path_has_local_parent(ty_path, cx, &*local_parents)
144+
path_has_local_parent(ty_path, cx, &parent_owner, &extra_local_parent)
129145
}
130146
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
131147
path_has_local_parent(
132148
principle_poly_trait_ref.trait_ref.path,
133149
cx,
134-
&*local_parents,
150+
&parent_owner,
151+
&extra_local_parent,
135152
)
136153
}
137154
TyKind::TraitObject([], _, _)
@@ -151,19 +168,31 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
151168
| TyKind::Err(_) => false,
152169
};
153170

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);
171+
let of_trait_has_local_parent = self_ty_has_local_parent
172+
|| impl_
173+
.of_trait
174+
.map(|of_trait| {
175+
path_has_local_parent(
176+
of_trait.path,
177+
cx,
178+
&parent_owner,
179+
&extra_local_parent,
180+
)
181+
})
182+
.unwrap_or(false);
158183

159184
// If none of them have a local parent (LOGICAL NOR) this means that
160185
// this impl definition is a non-local definition and so we lint on it.
161186
if !(self_ty_has_local_parent || of_trait_has_local_parent) {
187+
// Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in
188+
// top-level module.
189+
if self.body_depth == 1 && parent_owner_is_anon_const() {
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_owner().1
195+
&& item.ident.name != kw::Underscore
167196
&& let ItemKind::Const(ty, _, _) = item.kind
168197
&& let TyKind::Tup(&[]) = ty.kind
169198
{
@@ -177,9 +206,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
177206
item.span,
178207
NonLocalDefinitionsDiag::Impl {
179208
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())
209+
body_kind_descr: "?" /*cx.tcx.def_kind_descr(parent_def_kind(), parent())*/,
210+
body_name: parent_owner().1
211+
.ident()
212+
.map(|s| s.name.to_ident_string())
183213
.unwrap_or_else(|| "<unnameable>".to_string()),
184214
cargo_update: cargo_update(),
185215
const_anon,
@@ -195,9 +225,11 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
195225
item.span,
196226
NonLocalDefinitionsDiag::MacroRules {
197227
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())
228+
body_kind_descr: "?", /*cx.tcx.def_kind_descr(parent_def_kind(), parent())*/
229+
body_name: parent_owner()
230+
.1
231+
.ident()
232+
.map(|s| s.name.to_ident_string())
201233
.unwrap_or_else(|| "<unnameable>".to_string()),
202234
cargo_update: cargo_update(),
203235
},
@@ -217,6 +249,26 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
217249
/// std::convert::PartialEq<Foo<Bar>>
218250
/// ^^^^^^^^^^^^^^^^^^^^^^^
219251
/// ```
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)))
252+
fn path_has_local_parent<'tcx>(
253+
path: &Path<'_>,
254+
cx: &LateContext<'tcx>,
255+
local_parent: impl Fn() -> (OwnerId, OwnerNode<'tcx>),
256+
extra_local_parent: impl Fn() -> Option<LocalDefId>,
257+
) -> bool {
258+
let Some(res_did) = path.res.opt_def_id() else {
259+
return true;
260+
};
261+
let Some(did) = res_did.as_local() else {
262+
return false;
263+
};
264+
265+
let res_parent = {
266+
let Some(hir_id) = cx.tcx.opt_local_def_id_to_hir_id(did) else {
267+
return true;
268+
};
269+
let owner_id = cx.tcx.hir().get_parent_item(hir_id);
270+
owner_id.def_id
271+
};
272+
273+
res_parent == local_parent().0.def_id || Some(res_parent) == extra_local_parent()
222274
}

tests/ui/lint/non_local_definitions.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//@ check-pass
22
//@ edition:2021
33
//@ aux-build:non_local_macro.rs
4-
//@ rustc-env:CARGO=/usr/bin/cargo
4+
//@ rustc-env:CARGO_CRATE_NAME=non_local_def
55

66
#![feature(inline_const)]
77

0 commit comments

Comments
 (0)