Skip to content

Refactor resolve_ident_in_module to use scopes #142547

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

b-naber
Copy link
Contributor

@b-naber b-naber commented Jun 15, 2025

Refactoring that should help with introducing name resolution for namespaced crates.

r? @petrochenkov

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 15, 2025
}

// --- From now on we either have a glob resolution or no resolution. ---
let break_result = self.visit_module_scopes(ns, |this, scope| match scope {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if it'd be worth making a ModuleScopeVisitor trait or something like that? It seems a little weird to me to loop through all the scope types and then match on which scope we're in. I feel like there might be a nicer way to factor that.

(Just a suggestion to consider, you don't need to change this just because I said so.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current setup is copied from the larger visit_scopes, in that case a match is certainly more convenient.

@eholk
Copy link
Contributor

eholk commented Jun 17, 2025

I gave this a quick read and it seems cleaner than before!

@rust-cloud-vms rust-cloud-vms bot force-pushed the refactor-resolve-ident-module branch from f6807eb to f9a6e87 Compare June 18, 2025 11:07
#[derive(Debug, Copy, Clone, PartialEq)]
enum ModuleScope {
NonGlobal,
Global,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Global,
Globs,

"Glob imports", not "global imports".

@@ -221,6 +223,27 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
None
}

#[instrument(skip(self, visitor), level = "debug")]
pub(crate) fn visit_module_scopes<T>(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub(crate) fn visit_module_scopes<T>(
fn visit_module_scopes<T>(

// However, it causes resolution/expansion to stuck too often (#53144), so, to make
// progress, we have to ignore those potential unresolved invocations from other modules
// and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
// shadowing is enabled, see `macro_expanded_macro_export_errors`).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make sure none of the comments is lost, like in this case?


let check_usable = |this: &mut Self, binding: NameBinding<'ra>| {
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
debug!(?usable);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remove the added debug statements some time before merge?

}

// --- From now on we either have a glob resolution or no resolution. ---
let break_result = self.visit_module_scopes(ns, |this, scope| match scope {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current setup is copied from the larger visit_scopes, in that case a match is certainly more convenient.

ModuleScope::Global => {
// If we are here, any primary `resolution.binding` is either a glob, None,
// or should be ignored.
let binding = [resolution.binding, resolution.shadowed_glob]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a sign showing that the conversion to scopes is not fully done.
Ideally resolution should contain resolution.non_glob_binding and resolution.glob_binding instead (or there should be two resolution maps for non-globs and globs), but that's a larger refactoring.

}
}

// Forbid expanded shadowing to avoid time travel.
Copy link
Contributor

@petrochenkov petrochenkov Jun 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also indicates that the conversion to scopes wasn't done properly.
Ideally MoreExpandedVsOuter should be reported here in a similar way to how it's done in early_resolve_ident_in_lexical_scope.

@@ -130,6 +130,13 @@ enum Scope<'ra> {
BuiltinTypes,
}

/// Scopes used for resolving an `Ident` in a `Module`.
#[derive(Debug, Copy, Clone, PartialEq)]
enum ModuleScope {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of this, I think enum Scope above should also get two variants ModuleNonGlobs and ModuleGlobs instead of one Module.

Then finding any resolution inside a module would be done using a new ScopeSet variant including just two scopes, but other ScopeSet would just iterate over ModuleNonGlobs and ModuleGlobs as a part of the common loop.

This would also be a much larger refactoring.

}
});

match break_result {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if let Some(result) = break_result {
  return result;
}

@petrochenkov
Copy link
Contributor

I think this is a small step in the right direction, but it probably doesn't move us much closer to implementing the open namespace proposal, splitting modules into scopes properly is a large refactoring that only partially intersects with open namespaces.

Also not sure if landing just this part of the refactoring is beneficial.
Extracting finalize_module_binding and single_import_can_define_name are certainly good though.

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants