Auto merge of #132761 - nnethercote:resolve-tweaks, r=petrochenkov

Resolve tweaks

A couple of small perf improvements, and some minor refactorings, all in `rustc_resolve`.

r? `@petrochenkov`
This commit is contained in:
bors 2024-11-19 19:54:35 +00:00
commit ee612c45f0
5 changed files with 54 additions and 94 deletions

View File

@ -641,9 +641,10 @@ impl<'a> Parser<'a> {
return true; return true;
} }
// Do an ASCII case-insensitive match, because all keywords are ASCII.
if case == Case::Insensitive if case == Case::Insensitive
&& let Some((ident, IdentIsRaw::No)) = self.token.ident() && let Some((ident, IdentIsRaw::No)) = self.token.ident()
&& ident.as_str().to_lowercase() == kw.as_str().to_lowercase() && ident.as_str().eq_ignore_ascii_case(kw.as_str())
{ {
true true
} else { } else {

View File

@ -535,14 +535,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
filter_fn: &impl Fn(Res) -> bool, filter_fn: &impl Fn(Res) -> bool,
ctxt: Option<SyntaxContext>, ctxt: Option<SyntaxContext>,
) { ) {
for (key, resolution) in self.resolutions(module).borrow().iter() { module.for_each_child(self, |_this, ident, _ns, binding| {
if let Some(binding) = resolution.borrow().binding {
let res = binding.res(); let res = binding.res();
if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == key.ident.span.ctxt()) { if filter_fn(res) && ctxt.map_or(true, |ctxt| ctxt == ident.span.ctxt()) {
names.push(TypoSuggestion::typo_from_ident(key.ident, res)); names.push(TypoSuggestion::typo_from_ident(ident, res));
}
}
} }
});
} }
/// Combines an error with provided span and emits it. /// Combines an error with provided span and emits it.

View File

@ -38,6 +38,12 @@ impl From<UsePrelude> for bool {
} }
} }
#[derive(Debug, PartialEq)]
enum Shadowing {
Restricted,
Unrestricted,
}
impl<'ra, 'tcx> Resolver<'ra, 'tcx> { impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
/// A generic scope visitor. /// A generic scope visitor.
/// Visits scopes in order to resolve some identifier in them or perform other actions. /// Visits scopes in order to resolve some identifier in them or perform other actions.
@ -311,13 +317,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Walk backwards up the ribs in scope. // Walk backwards up the ribs in scope.
let mut module = self.graph_root; let mut module = self.graph_root;
for i in (0..ribs.len()).rev() { for (i, rib) in ribs.iter().enumerate().rev() {
debug!("walk rib\n{:?}", ribs[i].bindings); debug!("walk rib\n{:?}", rib.bindings);
// Use the rib kind to determine whether we are resolving parameters // Use the rib kind to determine whether we are resolving parameters
// (macro 2.0 hygiene) or local variables (`macro_rules` hygiene). // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
let rib_ident = if ribs[i].kind.contains_params() { normalized_ident } else { ident }; let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };
if let Some((original_rib_ident_def, res)) = ribs[i].bindings.get_key_value(&rib_ident) if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {
{
// The ident resolves to a type parameter or local variable. // The ident resolves to a type parameter or local variable.
return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs( return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
i, i,
@ -329,7 +334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
))); )));
} }
module = match ribs[i].kind { module = match rib.kind {
RibKind::Module(module) => module, RibKind::Module(module) => module,
RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => { RibKind::MacroDefinition(def) if def == self.macro_def(ident.span.ctxt()) => {
// If an invocation of this macro created `ident`, give up on `ident` // If an invocation of this macro created `ident`, give up on `ident`
@ -350,6 +355,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident, ident,
ns, ns,
parent_scope, parent_scope,
Shadowing::Unrestricted,
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding, ignore_binding,
None, None,
@ -494,7 +500,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
Scope::CrateRoot => { Scope::CrateRoot => {
let root_ident = Ident::new(kw::PathRoot, ident.span); let root_ident = Ident::new(kw::PathRoot, ident.span);
let root_module = this.resolve_crate_root(root_ident); let root_module = this.resolve_crate_root(root_ident);
let binding = this.resolve_ident_in_module_ext( let binding = this.resolve_ident_in_module(
ModuleOrUniformRoot::Module(root_module), ModuleOrUniformRoot::Module(root_module),
ident, ident,
ns, ns,
@ -516,12 +522,16 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
} }
Scope::Module(module, derive_fallback_lint_id) => { Scope::Module(module, derive_fallback_lint_id) => {
let adjusted_parent_scope = &ParentScope { module, ..*parent_scope }; let adjusted_parent_scope = &ParentScope { module, ..*parent_scope };
let binding = this.resolve_ident_in_module_unadjusted_ext( let binding = this.resolve_ident_in_module_unadjusted(
ModuleOrUniformRoot::Module(module), ModuleOrUniformRoot::Module(module),
ident, ident,
ns, ns,
adjusted_parent_scope, adjusted_parent_scope,
!matches!(scope_set, ScopeSet::Late(..)), if matches!(scope_set, ScopeSet::Late(..)) {
Shadowing::Unrestricted
} else {
Shadowing::Restricted
},
finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }), finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
ignore_binding, ignore_binding,
ignore_import, ignore_import,
@ -590,6 +600,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident, ident,
ns, ns,
parent_scope, parent_scope,
Shadowing::Unrestricted,
None, None,
ignore_binding, ignore_binding,
ignore_import, ignore_import,
@ -748,35 +759,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
parent_scope: &ParentScope<'ra>, parent_scope: &ParentScope<'ra>,
ignore_import: Option<Import<'ra>>, ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> { ) -> Result<NameBinding<'ra>, Determinacy> {
self.resolve_ident_in_module_ext(module, ident, ns, parent_scope, None, None, ignore_import) self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)
.map_err(|(determinacy, _)| determinacy) .map_err(|(determinacy, _)| determinacy)
} }
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
pub(crate) fn resolve_ident_in_module( pub(crate) fn resolve_ident_in_module(
&mut self,
module: ModuleOrUniformRoot<'ra>,
ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>,
ignore_binding: Option<NameBinding<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
self.resolve_ident_in_module_ext(
module,
ident,
ns,
parent_scope,
finalize,
ignore_binding,
ignore_import,
)
.map_err(|(determinacy, _)| determinacy)
}
#[instrument(level = "debug", skip(self))]
fn resolve_ident_in_module_ext(
&mut self, &mut self,
module: ModuleOrUniformRoot<'ra>, module: ModuleOrUniformRoot<'ra>,
mut ident: Ident, mut ident: Ident,
@ -803,18 +791,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// No adjustments // No adjustments
} }
} }
self.resolve_ident_in_module_unadjusted_ext( self.resolve_ident_in_module_unadjusted(
module, module,
ident, ident,
ns, ns,
adjusted_parent_scope, adjusted_parent_scope,
false, Shadowing::Unrestricted,
finalize, finalize,
ignore_binding, ignore_binding,
ignore_import, ignore_import,
) )
} }
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
#[instrument(level = "debug", skip(self))] #[instrument(level = "debug", skip(self))]
fn resolve_ident_in_module_unadjusted( fn resolve_ident_in_module_unadjusted(
&mut self, &mut self,
@ -822,33 +812,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident: Ident, ident: Ident,
ns: Namespace, ns: Namespace,
parent_scope: &ParentScope<'ra>, parent_scope: &ParentScope<'ra>,
finalize: Option<Finalize>, shadowing: Shadowing,
ignore_binding: Option<NameBinding<'ra>>,
ignore_import: Option<Import<'ra>>,
) -> Result<NameBinding<'ra>, Determinacy> {
self.resolve_ident_in_module_unadjusted_ext(
module,
ident,
ns,
parent_scope,
false,
finalize,
ignore_binding,
ignore_import,
)
.map_err(|(determinacy, _)| determinacy)
}
/// Attempts to resolve `ident` in namespaces `ns` of `module`.
/// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
#[instrument(level = "debug", skip(self))]
fn resolve_ident_in_module_unadjusted_ext(
&mut self,
module: ModuleOrUniformRoot<'ra>,
ident: Ident,
ns: Namespace,
parent_scope: &ParentScope<'ra>,
restricted_shadowing: bool,
finalize: Option<Finalize>, finalize: Option<Finalize>,
// This binding should be ignored during in-module resolution, so that we don't get // This binding should be ignored during in-module resolution, so that we don't get
// "self-confirming" import resolutions during import validation and checking. // "self-confirming" import resolutions during import validation and checking.
@ -858,7 +822,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let module = match module { let module = match module {
ModuleOrUniformRoot::Module(module) => module, ModuleOrUniformRoot::Module(module) => module,
ModuleOrUniformRoot::CrateRootAndExternPrelude => { ModuleOrUniformRoot::CrateRootAndExternPrelude => {
assert!(!restricted_shadowing); assert_eq!(shadowing, Shadowing::Unrestricted);
let binding = self.early_resolve_ident_in_lexical_scope( let binding = self.early_resolve_ident_in_lexical_scope(
ident, ident,
ScopeSet::AbsolutePath(ns), ScopeSet::AbsolutePath(ns),
@ -871,7 +835,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
return binding.map_err(|determinacy| (determinacy, Weak::No)); return binding.map_err(|determinacy| (determinacy, Weak::No));
} }
ModuleOrUniformRoot::ExternPrelude => { ModuleOrUniformRoot::ExternPrelude => {
assert!(!restricted_shadowing); assert_eq!(shadowing, Shadowing::Unrestricted);
return if ns != TypeNS { return if ns != TypeNS {
Err((Determined, Weak::No)) Err((Determined, Weak::No))
} else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) { } else if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
@ -884,7 +848,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}; };
} }
ModuleOrUniformRoot::CurrentScope => { ModuleOrUniformRoot::CurrentScope => {
assert!(!restricted_shadowing); assert_eq!(shadowing, Shadowing::Unrestricted);
if ns == TypeNS { if ns == TypeNS {
if ident.name == kw::Crate || ident.name == kw::DollarCrate { if ident.name == kw::Crate || ident.name == kw::DollarCrate {
let module = self.resolve_crate_root(ident); let module = self.resolve_crate_root(ident);
@ -943,7 +907,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Forbid expanded shadowing to avoid time travel. // Forbid expanded shadowing to avoid time travel.
if let Some(shadowed_glob) = resolution.shadowed_glob if let Some(shadowed_glob) = resolution.shadowed_glob
&& restricted_shadowing && shadowing == Shadowing::Restricted
&& binding.expansion != LocalExpnId::ROOT && binding.expansion != LocalExpnId::ROOT
&& binding.res() != shadowed_glob.res() && binding.res() != shadowed_glob.res()
{ {
@ -958,7 +922,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
}); });
} }
if !restricted_shadowing if shadowing == Shadowing::Unrestricted
&& binding.expansion != LocalExpnId::ROOT && binding.expansion != LocalExpnId::ROOT
&& let NameBindingKind::Import { import, .. } = binding.kind && let NameBindingKind::Import { import, .. } = binding.kind
&& matches!(import.kind, ImportKind::MacroExport) && matches!(import.kind, ImportKind::MacroExport)
@ -1047,13 +1011,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_binding, ignore_binding,
ignore_import, ignore_import,
) { ) {
Err(Determined) => continue, Err((Determined, _)) => continue,
Ok(binding) Ok(binding)
if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) => if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
{ {
continue; continue;
} }
Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::No)), Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::No)),
} }
} }
@ -1070,7 +1034,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
// shadowing is enabled, see `macro_expanded_macro_export_errors`). // shadowing is enabled, see `macro_expanded_macro_export_errors`).
if let Some(binding) = binding { if let Some(binding) = binding {
if binding.determined() || ns == MacroNS || restricted_shadowing { if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
return check_usable(self, binding); return check_usable(self, binding);
} else { } else {
return Err((Undetermined, Weak::No)); return Err((Undetermined, Weak::No));
@ -1122,19 +1086,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ident, ident,
ns, ns,
adjusted_parent_scope, adjusted_parent_scope,
Shadowing::Unrestricted,
None, None,
ignore_binding, ignore_binding,
ignore_import, ignore_import,
); );
match result { match result {
Err(Determined) => continue, Err((Determined, _)) => continue,
Ok(binding) Ok(binding)
if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) => if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) =>
{ {
continue; continue;
} }
Ok(_) | Err(Undetermined) => return Err((Undetermined, Weak::Yes)), Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::Yes)),
} }
} }
@ -1200,7 +1165,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
// Still doesn't deal with upvars // Still doesn't deal with upvars
if let Some(span) = finalize { if let Some(span) = finalize {
let (span, resolution_error) = match item { let (span, resolution_error) = match item {
None if rib_ident.as_str() == "self" => (span, LowercaseSelf), None if rib_ident.name == kw::SelfLower => {
(span, LowercaseSelf)
}
None => { None => {
// If we have a `let name = expr;`, we have the span for // If we have a `let name = expr;`, we have the span for
// `name` and use that to see if it is followed by a type // `name` and use that to see if it is followed by a type
@ -1563,6 +1530,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
ignore_binding, ignore_binding,
ignore_import, ignore_import,
) )
.map_err(|(determinacy, _)| determinacy)
} else if let Some(ribs) = ribs } else if let Some(ribs) = ribs
&& let Some(TypeNS | ValueNS) = opt_ns && let Some(TypeNS | ValueNS) = opt_ns
{ {

View File

@ -1688,9 +1688,9 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
} }
} }
let normalized_ident = ident.normalize_to_macros_2_0();
let mut outer_res = None; let mut outer_res = None;
for rib in lifetime_rib_iter { for rib in lifetime_rib_iter {
let normalized_ident = ident.normalize_to_macros_2_0();
if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) { if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
outer_res = Some(outer); outer_res = Some(outer);
break; break;

View File

@ -1082,8 +1082,6 @@ pub struct Resolver<'ra, 'tcx> {
binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>, binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
underscore_disambiguator: u32, underscore_disambiguator: u32,
/// Disambiguator for anonymous adts.
empty_disambiguator: u32,
/// Maps glob imports to the names of items actually imported. /// Maps glob imports to the names of items actually imported.
glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>, glob_map: FxHashMap<LocalDefId, FxHashSet<Symbol>>,
@ -1462,7 +1460,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
module_children: Default::default(), module_children: Default::default(),
trait_map: NodeMap::default(), trait_map: NodeMap::default(),
underscore_disambiguator: 0, underscore_disambiguator: 0,
empty_disambiguator: 0,
empty_module, empty_module,
module_map, module_map,
block_map: Default::default(), block_map: Default::default(),
@ -1809,12 +1806,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
assoc_item: Option<(Symbol, Namespace)>, assoc_item: Option<(Symbol, Namespace)>,
) -> bool { ) -> bool {
match (trait_module, assoc_item) { match (trait_module, assoc_item) {
(Some(trait_module), Some((name, ns))) => { (Some(trait_module), Some((name, ns))) => self
self.resolutions(trait_module).borrow().iter().any(|resolution| { .resolutions(trait_module)
let (&BindingKey { ident: assoc_ident, ns: assoc_ns, .. }, _) = resolution; .borrow()
assoc_ns == ns && assoc_ident.name == name .iter()
}) .any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
}
_ => true, _ => true,
} }
} }
@ -1842,9 +1838,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
let disambiguator = if ident.name == kw::Underscore { let disambiguator = if ident.name == kw::Underscore {
self.underscore_disambiguator += 1; self.underscore_disambiguator += 1;
self.underscore_disambiguator self.underscore_disambiguator
} else if ident.name == kw::Empty {
self.empty_disambiguator += 1;
self.empty_disambiguator
} else { } else {
0 0
}; };