Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 87cd7f5

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 b6e4299 + c84776f commit 87cd7f5

File tree

5 files changed

+158
-1136
lines changed

5 files changed

+158
-1136
lines changed

compiler/rustc_lint/src/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#![allow(rustc::diagnostic_outside_of_impl)]
22
#![allow(rustc::untranslatable_diagnostic)]
3+
#![allow(dead_code)]
34
use std::num::NonZero;
45

56
use crate::errors::RequestedLevel;
Lines changed: 156 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use rustc_hir::{def::DefKind, Body, Item, ItemKind, Node, Path, QPath, TyKind};
2-
use rustc_span::def_id::{DefId, LOCAL_CRATE};
3-
use rustc_span::{sym, symbol::kw, ExpnKind, MacroKind};
1+
#![allow(warnings)]
42

5-
use smallvec::{smallvec, SmallVec};
3+
use rustc_hir::{Body, Item, ItemKind, OwnerNode, Path, QPath, TyKind};
4+
use rustc_span::def_id::{DefId, LOCAL_CRATE};
5+
use rustc_span::{sym, symbol::kw, symbol::Ident, ExpnKind, MacroKind};
66

77
use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag};
88
use crate::{LateContext, LateLintPass, LintContext};
@@ -67,17 +67,14 @@ 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);
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-
}
70+
let mut parent_node = {
71+
let mut parent_node_cache = None;
72+
move || {
73+
*parent_node_cache.get_or_insert_with(|| {
74+
cx.tcx.hir().parent_owner_iter(item.hir_id()).next().unwrap().1
75+
})
76+
}
77+
};
8178

8279
let cargo_update = || {
8380
let oexpn = item.span.ctxt().outer_expn_data();
@@ -97,96 +94,130 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
9794
};
9895

9996
match item.kind {
100-
ItemKind::Impl(impl_) => {
101-
// The RFC states:
102-
//
103-
// > An item nested inside an expression-containing item (through any
104-
// > level of nesting) may not define an impl Trait for Type unless
105-
// > either the **Trait** or the **Type** is also nested inside the
106-
// > same expression-containing item.
107-
//
108-
// To achieve this we get try to get the paths of the _Trait_ and
109-
// _Type_, and we look inside thoses paths to try a find in one
110-
// of them a type whose parent is the same as the impl definition.
111-
//
112-
// If that's the case this means that this impl block declaration
113-
// is using local items and so we don't lint on it.
114-
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-
};
125-
126-
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-
}
130-
TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
131-
path_has_local_parent(
132-
principle_poly_trait_ref.trait_ref.path,
133-
cx,
134-
&*local_parents,
135-
)
136-
}
137-
TyKind::TraitObject([], _, _)
138-
| TyKind::InferDelegation(_, _)
139-
| TyKind::Slice(_)
140-
| TyKind::Array(_, _)
141-
| TyKind::Ptr(_)
142-
| TyKind::Ref(_, _)
143-
| TyKind::BareFn(_)
144-
| TyKind::Never
145-
| TyKind::Tup(_)
146-
| TyKind::Path(_)
147-
| TyKind::AnonAdt(_)
148-
| TyKind::OpaqueDef(_, _, _)
149-
| TyKind::Typeof(_)
150-
| TyKind::Infer
151-
| TyKind::Err(_) => false,
152-
};
153-
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-
159-
// If none of them have a local parent (LOGICAL NOR) this means that
160-
// this impl definition is a non-local definition and so we lint on it.
161-
if !(self_ty_has_local_parent || of_trait_has_local_parent) {
162-
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)
167-
&& let ItemKind::Const(ty, _, _) = item.kind
168-
&& let TyKind::Tup(&[]) = ty.kind
169-
{
170-
Some(item.ident.span)
171-
} else {
172-
None
173-
};
174-
175-
cx.emit_span_lint(
176-
NON_LOCAL_DEFINITIONS,
177-
item.span,
178-
NonLocalDefinitionsDiag::Impl {
179-
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())
183-
.unwrap_or_else(|| "<unnameable>".to_string()),
184-
cargo_update: cargo_update(),
185-
const_anon,
186-
},
187-
)
188-
}
189-
}
97+
// ItemKind::Impl(impl_) => {
98+
// // The RFC states:
99+
// //
100+
// // > An item nested inside an expression-containing item (through any
101+
// // > level of nesting) may not define an impl Trait for Type unless
102+
// // > either the **Trait** or the **Type** is also nested inside the
103+
// // > same expression-containing item.
104+
// //
105+
// // To achieve this we get try to get the paths of the _Trait_ and
106+
// // _Type_, and we look inside thoses paths to try a find in one
107+
// // of them a type whose parent is the same as the impl definition.
108+
// //
109+
// // If that's the case this means that this impl block declaration
110+
// // is using local items and so we don't lint on it.
111+
//
112+
// let mut parent_node_is_anon_const = {
113+
// let mut parent_node_is_anon_const = None;
114+
// move || {
115+
// *parent_node_is_anon_const.get_or_insert_with(|| {
116+
// matches!(
117+
// parent_node(),
118+
// OwnerNode::Item(Item {
119+
// ident: Ident { name: kw::Underscore, .. },
120+
// kind: ItemKind::Const(..),
121+
// ..
122+
// })
123+
// )
124+
// })
125+
// }
126+
// };
127+
// let mut local_parent = {
128+
// let mut local_parent_cache = None;
129+
// move || {
130+
// *local_parent_cache
131+
// .get_or_insert_with(|| cx.tcx.parent(item.owner_id.to_def_id()))
132+
// }
133+
// };
134+
// let mut extra_local_parent = {
135+
// let mut extra_parent_cache = None;
136+
// move |did| {
137+
// *extra_parent_cache.get_or_insert_with(|| {
138+
// parent_node_is_anon_const().then(|| cx.tcx.parent(did))
139+
// })
140+
// }
141+
// };
142+
//
143+
// let self_ty_has_local_parent = match impl_.self_ty.kind {
144+
// TyKind::Path(QPath::Resolved(_, ty_path)) => path_has_local_parent(
145+
// ty_path,
146+
// cx,
147+
// &mut local_parent,
148+
// &mut extra_local_parent,
149+
// ),
150+
// TyKind::TraitObject([principle_poly_trait_ref, ..], _, _) => {
151+
// path_has_local_parent(
152+
// principle_poly_trait_ref.trait_ref.path,
153+
// cx,
154+
// &mut local_parent,
155+
// &mut extra_local_parent,
156+
// )
157+
// }
158+
// TyKind::TraitObject([], _, _)
159+
// | TyKind::InferDelegation(_, _)
160+
// | TyKind::Slice(_)
161+
// | TyKind::Array(_, _)
162+
// | TyKind::Ptr(_)
163+
// | TyKind::Ref(_, _)
164+
// | TyKind::BareFn(_)
165+
// | TyKind::Never
166+
// | TyKind::Tup(_)
167+
// | TyKind::Path(_)
168+
// | TyKind::AnonAdt(_)
169+
// | TyKind::OpaqueDef(_, _, _)
170+
// | TyKind::Typeof(_)
171+
// | TyKind::Infer
172+
// | TyKind::Err(_) => false,
173+
// };
174+
//
175+
// let of_trait_has_local_parent = impl_
176+
// .of_trait
177+
// .map(|of_trait| {
178+
// path_has_local_parent(
179+
// of_trait.path,
180+
// cx,
181+
// &mut local_parent,
182+
// &mut extra_local_parent,
183+
// )
184+
// })
185+
// .unwrap_or(false);
186+
//
187+
// // If none of them have a local parent (LOGICAL NOR) this means that
188+
// // this impl definition is a non-local definition and so we lint on it.
189+
// if !(self_ty_has_local_parent || of_trait_has_local_parent) {
190+
// // Per RFC we (currently) ignore anon-const (`const _: Ty = ...`) in top-level module.
191+
// if parent_node_is_anon_const() && self.body_depth == 1 {
192+
// return;
193+
// }
194+
//
195+
// let const_anon = if self.body_depth == 1
196+
// && let OwnerNode::Item(item) = parent_node()
197+
// && let ItemKind::Const(ty, _, _) = item.kind
198+
// && let TyKind::Tup(&[]) = ty.kind
199+
// {
200+
// Some(item.ident.span)
201+
// } else {
202+
// None
203+
// };
204+
//
205+
// cx.emit_span_lint(
206+
// NON_LOCAL_DEFINITIONS,
207+
// item.span,
208+
// NonLocalDefinitionsDiag::Impl {
209+
// depth: self.body_depth,
210+
// body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
211+
// body_name: parent_node()
212+
// .ident()
213+
// .map(|s| s.name.to_ident_string())
214+
// .unwrap_or_else(|| "<unnameable>".to_string()),
215+
// cargo_update: cargo_update(),
216+
// const_anon,
217+
// },
218+
// )
219+
// }
220+
// }
190221
ItemKind::Macro(_macro, MacroKind::Bang)
191222
if cx.tcx.has_attr(item.owner_id.def_id, sym::macro_export) =>
192223
{
@@ -195,9 +226,10 @@ impl<'tcx> LateLintPass<'tcx> for NonLocalDefinitions {
195226
item.span,
196227
NonLocalDefinitionsDiag::MacroRules {
197228
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())
229+
body_kind_descr: "?" /* FIXME: cx.tcx.def_kind_descr(parent_def_kind, parent) */,
230+
body_name: parent_node()
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,20 @@ 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(
253+
path: &Path<'_>,
254+
cx: &LateContext<'_>,
255+
local_parent: &mut impl FnMut() -> DefId,
256+
extra_local_parent: &mut impl FnMut(DefId) -> Option<DefId>,
257+
) -> bool {
258+
if let Some(did) = path.res.opt_def_id() {
259+
if !did.is_local() {
260+
false
261+
} else {
262+
let res_parent = cx.tcx.parent(did);
263+
res_parent == local_parent() || Some(res_parent) == extra_local_parent(local_parent())
264+
}
265+
} else {
266+
true
267+
}
222268
}

0 commit comments

Comments
 (0)