Skip to content

Resolve: more preperation work for parallelizing the import resolution loop#159440

Open
LorrensP-2158466 wants to merge 1 commit into
rust-lang:mainfrom
LorrensP-2158466:inplace-import-res
Open

Resolve: more preperation work for parallelizing the import resolution loop#159440
LorrensP-2158466 wants to merge 1 commit into
rust-lang:mainfrom
LorrensP-2158466:inplace-import-res

Conversation

@LorrensP-2158466

@LorrensP-2158466 LorrensP-2158466 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

This is basically #158845 but we do not:

  • actually use par_slice because:
  • we do not migrate CmRefCell to use RwLocks (yet) because of perf reasons.

The resolution loop is now in place instead of recollecting indeterminate imports.

Also implemented the unsafe traits DynSend/DynSync for RefOrMut and CmCell and tried to write correct SAFETY comments.

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 Jul 17, 2026
@rust-log-analyzer

This comment has been minimized.

Comment thread compiler/rustc_resolve/src/lib.rs Outdated
@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 Jul 17, 2026
@LorrensP-2158466

Copy link
Copy Markdown
Contributor Author

I double-checked with git diff f3d5c561f4c compiler/rustc_resolve and I only see comments or the unsafe impls as + diff.

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jul 17, 2026
@rust-log-analyzer

This comment has been minimized.

…par_slice`.

Currently it is all still single threaded, but almost everything needed to make the loop use multithreaded code is done in this commit.

For performance reasons we do the resolution now in place instead of recollecting the indeterminate imports ([see benchmark pr](rust-lang#159387) and pr of this commit).

With the accompanying changes to make datastructures concurrent:
- populating external resolution tables now use `Once` to ensure only 1 thread builds the table and all others wait if they need it
- implement `DynSync`/`DynSend` for `RefOrMut` and `CmCell` so it is allowed to use the `par_slice` function.

`Cache(Ref)Cells` are not tackled yet because they are not needed here (and require extra work).
&self,
def_id: DefId,
map_lock: &mut RefMut<'_, FxIndexMap<DefId, ExternModule<'ra>>>,
) -> Option<Module<'ra>> {

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
) -> Option<Module<'ra>> {
) -> Option<ExternModule<'ra>> {

View changes since the review

while let MacroRulesScope::Invocation(invoc_id) = scope {
if let Some(next) = self.output_macro_rules_scopes.get(&invoc_id) {
scope = next.get();
macro_rules_scope.set(scope);

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
macro_rules_scope.set(scope);
macro_rules_scope.set(next.get());

Does the RwLock version really not work in the nicer way, like before?

View changes since the review

indeterminate_count = 0;
let mut resolutions = Vec::new();

let mut to_resolve_imports = mem::take(&mut self.indeterminate_imports);

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
let mut to_resolve_imports = mem::take(&mut self.indeterminate_imports);
let mut imports_to_resolve = mem::take(&mut self.indeterminate_imports);

View changes since the review

let (new_resolution, import_indeterminate_count) =
cm_resolver.reborrow_ref().resolve_import(*import);
*resolution = new_resolution;
*indeterminate_count = import_indeterminate_count

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
*indeterminate_count = import_indeterminate_count
(*resolution, *indeterminate_count) = cm_resolver.reborrow_ref().resolve_import(*import);

This should actually work (it's a destructuring assignment).

View changes since the review

self.write_import_resolutions(&to_resolve_imports);

self.indeterminate_imports = to_resolve_imports
.extract_if(.., |(_, _, count)| {

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be nicer to extract_if into determined_imports instead and then do self.indeterminate_imports = imports_to_resolve;.
But it may be slower due to majority of the elements in the vector being determinate.
I'll benchmark it separately later after this PR lands.

View changes since the review


for (import, resolution) in import_resolutions {
let ImportResolution { imported_module, kind: resolution_kind } = resolution;
for (import, resolution, _) in import_resolutions {

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
for (import, resolution, _) in import_resolutions {
for &(import, resolution, _) in import_resolutions {

Could you do something like this here to avoid *s below?

View changes since the review

type CmResolver<'r, 'ra, 'tcx> = ref_mut::RefOrMut<'r, Resolver<'ra, 'tcx>>;

// FIXME: this should be removed in the process of migration to parallel name resolution.
unsafe impl<'ra, 'tcx> DynSync for Resolver<'ra, 'tcx> {}

@petrochenkov petrochenkov Jul 17, 2026

Copy link
Copy Markdown
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 Dyn(Sync,Send) impls from this PR?
I don't think they are justified yet, before the migration to RwLock (and probably not yet used too).

Or maybe they are? At least for RefOrMut.
I'm not actually sure.

View changes since the review

@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 Jul 17, 2026
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