Skip to content

Commit 58eefc3

Browse files
committed
Auto merge of rust-lang#113408 - petrochenkov:bindintern2, r=cjgillot
resolve: Stop creating `NameBinding`s on every use, create them once per definition instead `NameBinding` values are supposed to be unique, use referential equality, and be created once for every name declaration. Before this PR many `NameBinding`s were created on name use, rather than on name declaration, because it's sufficiently cheap, and comparisons are not actually used in practice for some binding kinds. This PR makes `NameBinding`s consistently unique and created on name declaration. There are two special cases - for extern prelude names creating `NameBinding` requires loading the corresponding crate, which is expensive, so such bindings are created lazily on first use, but they still keep the uniqueness by being reused on further uses. - for legacy derive helpers (helper attributes written before derives that introduce them) the declaration and the use is basically the same thing (that's one of the reasons why they are deprecated), so they are still created on use, but we can still maybe do a bit better in a way that I described in FIXME in the last commit.
2 parents b60e31b + 453edeb commit 58eefc3

File tree

5 files changed

+133
-79
lines changed

5 files changed

+133
-79
lines changed

compiler/rustc_resolve/src/build_reduced_graph.rs

+9-8
Original file line numberDiff line numberDiff line change
@@ -870,10 +870,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
870870
let imported_binding = self.r.import(binding, import);
871871
if parent == self.r.graph_root {
872872
if let Some(entry) = self.r.extern_prelude.get(&ident.normalize_to_macros_2_0()) {
873-
if expansion != LocalExpnId::ROOT
874-
&& orig_name.is_some()
875-
&& entry.extern_crate_item.is_none()
876-
{
873+
if expansion != LocalExpnId::ROOT && orig_name.is_some() && !entry.is_import() {
877874
let msg = "macro-expanded `extern crate` items cannot \
878875
shadow names passed with `--extern`";
879876
self.r.tcx.sess.span_err(item.span, msg);
@@ -884,10 +881,14 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
884881
return;
885882
}
886883
}
887-
let entry = self.r.extern_prelude.entry(ident.normalize_to_macros_2_0()).or_insert(
888-
ExternPreludeEntry { extern_crate_item: None, introduced_by_item: true },
889-
);
890-
entry.extern_crate_item = Some(imported_binding);
884+
let entry = self
885+
.r
886+
.extern_prelude
887+
.entry(ident.normalize_to_macros_2_0())
888+
.or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true });
889+
// Binding from `extern crate` item in source code can replace
890+
// a binding from `--extern` on command line here.
891+
entry.binding = Some(imported_binding);
891892
if orig_name.is_some() {
892893
entry.introduced_by_item = true;
893894
}

compiler/rustc_resolve/src/diagnostics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
10321032
.get(&expn_id)
10331033
.into_iter()
10341034
.flatten()
1035-
.map(|ident| TypoSuggestion::typo_from_ident(*ident, res)),
1035+
.map(|(ident, _)| TypoSuggestion::typo_from_ident(*ident, res)),
10361036
);
10371037
}
10381038
}

compiler/rustc_resolve/src/ident.rs

+24-42
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
use rustc_ast::{self as ast, NodeId};
2-
use rustc_feature::is_builtin_attr_name;
32
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
4-
use rustc_hir::PrimTy;
53
use rustc_middle::bug;
64
use rustc_middle::ty;
75
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
86
use rustc_session::lint::BuiltinLintDiagnostics;
97
use rustc_span::def_id::LocalDefId;
108
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
119
use rustc_span::symbol::{kw, Ident};
12-
use rustc_span::{Span, DUMMY_SP};
10+
use rustc_span::Span;
1311

1412
use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
1513
use crate::late::{
@@ -423,32 +421,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
423421
orig_ident.span.ctxt(),
424422
|this, scope, use_prelude, ctxt| {
425423
let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
426-
let ok = |res, span, arenas| {
427-
Ok((
428-
(res, Visibility::Public, span, LocalExpnId::ROOT).to_name_binding(arenas),
429-
Flags::empty(),
430-
))
431-
};
432424
let result = match scope {
433425
Scope::DeriveHelpers(expn_id) => {
434-
if let Some(attr) = this
435-
.helper_attrs
436-
.get(&expn_id)
437-
.and_then(|attrs| attrs.iter().rfind(|i| ident == **i))
438-
{
439-
let binding = (
440-
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper),
441-
Visibility::Public,
442-
attr.span,
443-
expn_id,
444-
)
445-
.to_name_binding(this.arenas);
426+
if let Some(binding) = this.helper_attrs.get(&expn_id).and_then(|attrs| {
427+
attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding)
428+
}) {
446429
Ok((binding, Flags::empty()))
447430
} else {
448431
Err(Determinacy::Determined)
449432
}
450433
}
451434
Scope::DeriveHelpersCompat => {
435+
// FIXME: Try running this logic eariler, to allocate name bindings for
436+
// legacy derive helpers when creating an attribute invocation with
437+
// following derives. Legacy derive helpers are not common, so it shouldn't
438+
// affect performance. It should also allow to remove the `derives`
439+
// component from `ParentScope`.
452440
let mut result = Err(Determinacy::Determined);
453441
for derive in parent_scope.derives {
454442
let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
@@ -461,11 +449,14 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
461449
) {
462450
Ok((Some(ext), _)) => {
463451
if ext.helper_attrs.contains(&ident.name) {
464-
result = ok(
452+
let binding = (
465453
Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
454+
Visibility::Public,
466455
derive.span,
467-
this.arenas,
468-
);
456+
LocalExpnId::ROOT,
457+
)
458+
.to_name_binding(this.arenas);
459+
result = Ok((binding, Flags::empty()));
469460
break;
470461
}
471462
}
@@ -562,17 +553,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
562553
)),
563554
}
564555
}
565-
Scope::BuiltinAttrs => {
566-
if is_builtin_attr_name(ident.name) {
567-
ok(
568-
Res::NonMacroAttr(NonMacroAttrKind::Builtin(ident.name)),
569-
DUMMY_SP,
570-
this.arenas,
571-
)
572-
} else {
573-
Err(Determinacy::Determined)
574-
}
575-
}
556+
Scope::BuiltinAttrs => match this.builtin_attrs_bindings.get(&ident.name) {
557+
Some(binding) => Ok((*binding, Flags::empty())),
558+
None => Err(Determinacy::Determined),
559+
},
576560
Scope::ExternPrelude => {
577561
match this.extern_prelude_get(ident, finalize.is_some()) {
578562
Some(binding) => Ok((binding, Flags::empty())),
@@ -581,8 +565,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
581565
)),
582566
}
583567
}
584-
Scope::ToolPrelude => match this.registered_tools.get(&ident).cloned() {
585-
Some(ident) => ok(Res::ToolMod, ident.span, this.arenas),
568+
Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) {
569+
Some(binding) => Ok((*binding, Flags::empty())),
586570
None => Err(Determinacy::Determined),
587571
},
588572
Scope::StdLibPrelude => {
@@ -603,8 +587,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
603587
}
604588
result
605589
}
606-
Scope::BuiltinTypes => match PrimTy::from_name(ident.name) {
607-
Some(prim_ty) => ok(Res::PrimTy(prim_ty), DUMMY_SP, this.arenas),
590+
Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
591+
Some(binding) => Ok((*binding, Flags::empty())),
608592
None => Err(Determinacy::Determined),
609593
},
610594
};
@@ -842,9 +826,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
842826
if ns == TypeNS {
843827
if ident.name == kw::Crate || ident.name == kw::DollarCrate {
844828
let module = self.resolve_crate_root(ident);
845-
let binding = (module, Visibility::Public, module.span, LocalExpnId::ROOT)
846-
.to_name_binding(self.arenas);
847-
return Ok(binding);
829+
return Ok(self.module_self_bindings[&module]);
848830
} else if ident.name == kw::Super || ident.name == kw::SelfLower {
849831
// FIXME: Implement these with renaming requirements so that e.g.
850832
// `use super;` doesn't work, but `use super as name;` does.

0 commit comments

Comments
 (0)