Skip to content

Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution. #144912

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

Merged
merged 1 commit into from
Aug 8, 2025

Conversation

LorrensP-2158466
Copy link
Contributor

@LorrensP-2158466 LorrensP-2158466 commented Aug 4, 2025

This pr introduces a CmResolver, a wrapper around the main resolver which gives out mutable access given a condition.

CmResolver only allows mutation when we’re not in speculative import resolution. This ensures we can’t accidentally mutate the resolver during this process, which is important as we move towards a batched resolution algorithm.

This also changes functions that are used during speculative import resolution to take a CmResolver instead of a &mut Resolver.

Also introduces a new kind of "smart pointer" which has the behaviour described above:

/// A wrapper around a mutable reference that conditionally allows mutable access.
pub(crate) struct RefOrMut<'a, T> {
    p: &'a mut T,
    mutable: bool,
}

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

r? petrochenkov

@rustbot rustbot added 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. labels Aug 4, 2025
@rust-log-analyzer

This comment has been minimized.

@petrochenkov petrochenkov 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 Aug 4, 2025
@petrochenkov
Copy link
Contributor

Looks good to me at high level.

Although I expected to use

impl Resolver {
  fn method(self: SmartResolver) { ... }
}

instead of

impl SmartResolver {
  fn method(&mut self) { ... }
}

(It would also allow to avoid moving code and make the diff readable.)

@LorrensP-2158466
Copy link
Contributor Author

I though arbitrary self types were not allowed? Only std smartpointers and Pin.

@petrochenkov
Copy link
Contributor

There's feature(arbitrary_self_types) for using arbitrary types for smart pointers, and the compiler can use unstable features.

@petrochenkov
Copy link
Contributor

petrochenkov commented Aug 5, 2025

The current scheme of constructing SmartResolver::Finalize is very brittle, I think.
We can very easily construct it without providing any proofs that we are not actually called from resolve_import.

I think the speculative/finalize flag should live in Resolver after all, and be set/cleared only in fn resolve_imports for now.
And then SmartResolver would never be constructed manually, only through resolver.smart(), where smart is

fn smart(&mut self) -> SmartResolver {
   if self.speculative { SmartResolver::Speculative(self) } else { SmartResolver::Finalize(self) }
}

And then every resolver method taking &mut self should take SmartResolver instead.

Of course there may be some temporary escape hatch until resolver_import is fully migrated from mutating resolver to producing outputs.

@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 Aug 5, 2025
@LorrensP-2158466
Copy link
Contributor Author

The current scheme of constructing SmartResolver::Finalize is very brittle, I think.

I very much agree.

Of course there may be some temporary escape hatch until resolver_import is fully migrated from mutating resolver to producing outputs.

Currently, mutating this flag shouldn't be a problem, since resolve_imports takes a &mut Resolver. This would need to be converted to a cell once we convert this to batched import resolution.

@LorrensP-2158466
Copy link
Contributor Author

And then every resolver method taking &mut self should take SmartResolver instead.

Also, this seems a bit extreme, I'm sure not every &mut self should be a SmartResolver.

@petrochenkov
Copy link
Contributor

petrochenkov commented Aug 5, 2025

And then every resolver method taking &mut self should take SmartResolver instead.

Also, this seems a bit extreme, I'm sure not every &mut self should be a SmartResolver.

How are you going to guaranteed that this &mut method is not called from resolve_import?
If it doesn't use SmartResolver, then it should run an assert checking that resolver.speculative is false.
Upd: we didn't get to it yet, but when import resolution is actually parallelized, non-SmartResolver methods probably just won't pass borrow-send-sync checking.

@LorrensP-2158466
Copy link
Contributor Author

LorrensP-2158466 commented Aug 5, 2025

How are you going to guaranteed that this &mut method is not called from resolve_import?
If it doesn't use SmartResolver, then it should run an assert checking that resolver.speculative is false.
Upd: we didn't get to it yet, but when import resolution is actually parallelized, non-SmartResolver methods probably just won't pass borrow-send-sync checking.

Good point, didn't think of it like that. It is going to take some time.

@LorrensP-2158466
Copy link
Contributor Author

So we'd only call res_mut() when we actually mutate the resolver, like:

self.res_mut().some_field = some_value;

@petrochenkov
Copy link
Contributor

Hmm, but on the other hand if fn resolve_import takes a smart resolver, then the only way to obtain &mut self in it would be to call res_mut at some point, so you cannot get it in speculative mode.

I guess it's not necessary to convert everything then, just convert enough functions directly or called by resolve_import to avoid panics caused by calling res_mut unconditionally before them rather than conditionally inside them.

@LorrensP-2158466
Copy link
Contributor Author

I converted some more to use a SmartResolver and I also checked every call for res_mut. They should be fine.

mutable resolver usages in resolve_import are now annotated with fixmes.

Still wrapped (single,multi)_segment_macro_resolutions in RefCells just to be sure, but also annotated them with Fixmes since they should be outputs of speculative resolution.

@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 Aug 6, 2025
@petrochenkov
Copy link
Contributor

What about ScopedResolver?

It's used relatively often so let's make it short.

  • SmartResolver -> CmResolver (== conditionally mutable resolver)
  • fn smart -> fn cm
  • fn per_ns_smart -> fn per_ns_cm

Alternatively:

  • SmartResolver -> RomResolver (== RefOrMutResolver)
  • fn smart -> fn rom
  • fn per_ns_smart -> fn per_ns_rom

Could also be iom (ImmOrMut), moi (MutOrImm), mor (MutOrRef), then need to rename the smart pointer type correspondingly.

@rustbot author

@rustbot rustbot 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 Aug 7, 2025
@rustbot
Copy link
Collaborator

rustbot commented Aug 7, 2025

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@petrochenkov
Copy link
Contributor

Also need to update the PR title and description.

@LorrensP-2158466
Copy link
Contributor Author

LorrensP-2158466 commented Aug 7, 2025

I like the CmResolver, but maybe CMResolver is better? It's "Conditionally Mutable", 2 separate words.

Edit: same convention as Arc, Rc, TcpStream, ... . Got it

@LorrensP-2158466
Copy link
Contributor Author

@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 Aug 7, 2025
@petrochenkov
Copy link
Contributor

Also need to update the PR title and description.

^^^

@LorrensP-2158466 LorrensP-2158466 changed the title [WIP] Resolver: introduce SmartResolver for speculative and finalize resolutions. Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution. Aug 7, 2025
@petrochenkov
Copy link
Contributor

r=me after squashing commits.
@rustbot author
@bors delegate+

@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 7, 2025
@bors
Copy link
Collaborator

bors commented Aug 7, 2025

✌️ @LorrensP-2158466, you can now approve this pull request!

If @petrochenkov told you to "r=me" after making some further change, please make that change, then do @bors r=@petrochenkov

@rustbot rustbot added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Aug 7, 2025
@LorrensP-2158466
Copy link
Contributor Author

@bors r=@petrochenkov

@bors
Copy link
Collaborator

bors commented Aug 7, 2025

📌 Commit 487e5ce has been approved by petrochenkov

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 7, 2025
Zalathar added a commit to Zalathar/rust that referenced this pull request Aug 8, 2025
…=petrochenkov

Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.

This pr introduces a `CmResolver`, a wrapper around the main resolver which gives out mutable access given a condition.

`CmResolver` only allows mutation when we’re not in speculative import resolution. This ensures we can’t accidentally mutate the resolver during this process, which is important as we move towards a batched resolution algorithm.

This also changes functions that are used during speculative import resolution to take a `CmResolver` instead of a `&mut Resolver`.

Also introduces a new kind of "smart pointer" which has the behaviour described above:
```rust
/// A wrapper around a mutable reference that conditionally allows mutable access.
pub(crate) struct RefOrMut<'a, T> {
    p: &'a mut T,
    mutable: bool,
}

type CmResolver<'r, 'ra, 'tcx> = RefOrMut<'r, Resolver<'ra, 'tcx>>;
```
r? petrochenkov
bors added a commit that referenced this pull request Aug 8, 2025
Rollup of 19 pull requests

Successful merges:

 - #144400 (`tests/ui/issues/`: The Issues Strike Back [3/N])
 - #144764 ([codegen] assume the tag, not the relative discriminant)
 - #144807 (Streamline config in bootstrap)
 - #144899 (Print CGU reuse statistics in `-Zprint-mono-items`)
 - #144909 (Add new `test::print_merged_doctests_times` used by rustdoc to display more detailed time information)
 - #144912 (Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.)
 - #144914 (Add support for `ty::Instance` path shortening in diagnostics)
 - #144931 ([win][arm64ec] Fix msvc-wholearchive for Arm64EC)
 - #144999 (coverage: Remove all unstable support for MC/DC instrumentation)
 - #145009 (A couple small changes for rust-analyzer next-solver work)
 - #145030 (GVN:  Do not flatten derefs with ProjectionElem::Index. )
 - #145042 (stdarch subtree update)
 - #145047 (move `type_check` out of `compute_regions`)
 - #145051 (Prevent name collisions with internal implementation details)
 - #145053 (Add a lot of NLL `known-bug` tests)
 - #145055 (Move metadata symbol export from exported_non_generic_symbols to exported_symbols)
 - #145057 (Clean up some resolved test regressions of const trait removals in std)
 - #145068 (Readd myself to review queue)
 - #145070 (Add minimal `armv7a-vex-v5` tier three target)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit ecce94c into rust-lang:master Aug 8, 2025
10 checks passed
@rustbot rustbot added this to the 1.91.0 milestone Aug 8, 2025
rust-timer added a commit that referenced this pull request Aug 8, 2025
Rollup merge of #144912 - LorrensP-2158466:smart-resolver, r=petrochenkov

Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.

This pr introduces a `CmResolver`, a wrapper around the main resolver which gives out mutable access given a condition.

`CmResolver` only allows mutation when we’re not in speculative import resolution. This ensures we can’t accidentally mutate the resolver during this process, which is important as we move towards a batched resolution algorithm.

This also changes functions that are used during speculative import resolution to take a `CmResolver` instead of a `&mut Resolver`.

Also introduces a new kind of "smart pointer" which has the behaviour described above:
```rust
/// A wrapper around a mutable reference that conditionally allows mutable access.
pub(crate) struct RefOrMut<'a, T> {
    p: &'a mut T,
    mutable: bool,
}

type CmResolver<'r, 'ra, 'tcx> = RefOrMut<'r, Resolver<'ra, 'tcx>>;
```
r? petrochenkov
github-actions bot pushed a commit to rust-lang/compiler-builtins that referenced this pull request Aug 9, 2025
Rollup of 19 pull requests

Successful merges:

 - rust-lang/rust#144400 (`tests/ui/issues/`: The Issues Strike Back [3/N])
 - rust-lang/rust#144764 ([codegen] assume the tag, not the relative discriminant)
 - rust-lang/rust#144807 (Streamline config in bootstrap)
 - rust-lang/rust#144899 (Print CGU reuse statistics in `-Zprint-mono-items`)
 - rust-lang/rust#144909 (Add new `test::print_merged_doctests_times` used by rustdoc to display more detailed time information)
 - rust-lang/rust#144912 (Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.)
 - rust-lang/rust#144914 (Add support for `ty::Instance` path shortening in diagnostics)
 - rust-lang/rust#144931 ([win][arm64ec] Fix msvc-wholearchive for Arm64EC)
 - rust-lang/rust#144999 (coverage: Remove all unstable support for MC/DC instrumentation)
 - rust-lang/rust#145009 (A couple small changes for rust-analyzer next-solver work)
 - rust-lang/rust#145030 (GVN:  Do not flatten derefs with ProjectionElem::Index. )
 - rust-lang/rust#145042 (stdarch subtree update)
 - rust-lang/rust#145047 (move `type_check` out of `compute_regions`)
 - rust-lang/rust#145051 (Prevent name collisions with internal implementation details)
 - rust-lang/rust#145053 (Add a lot of NLL `known-bug` tests)
 - rust-lang/rust#145055 (Move metadata symbol export from exported_non_generic_symbols to exported_symbols)
 - rust-lang/rust#145057 (Clean up some resolved test regressions of const trait removals in std)
 - rust-lang/rust#145068 (Readd myself to review queue)
 - rust-lang/rust#145070 (Add minimal `armv7a-vex-v5` tier three target)

r? `@ghost`
`@rustbot` modify labels: rollup
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Aug 9, 2025
Rollup of 19 pull requests

Successful merges:

 - rust-lang/rust#144400 (`tests/ui/issues/`: The Issues Strike Back [3/N])
 - rust-lang/rust#144764 ([codegen] assume the tag, not the relative discriminant)
 - rust-lang/rust#144807 (Streamline config in bootstrap)
 - rust-lang/rust#144899 (Print CGU reuse statistics in `-Zprint-mono-items`)
 - rust-lang/rust#144909 (Add new `test::print_merged_doctests_times` used by rustdoc to display more detailed time information)
 - rust-lang/rust#144912 (Resolver: introduce a conditionally mutable Resolver for (non-)speculative resolution.)
 - rust-lang/rust#144914 (Add support for `ty::Instance` path shortening in diagnostics)
 - rust-lang/rust#144931 ([win][arm64ec] Fix msvc-wholearchive for Arm64EC)
 - rust-lang/rust#144999 (coverage: Remove all unstable support for MC/DC instrumentation)
 - rust-lang/rust#145009 (A couple small changes for rust-analyzer next-solver work)
 - rust-lang/rust#145030 (GVN:  Do not flatten derefs with ProjectionElem::Index. )
 - rust-lang/rust#145042 (stdarch subtree update)
 - rust-lang/rust#145047 (move `type_check` out of `compute_regions`)
 - rust-lang/rust#145051 (Prevent name collisions with internal implementation details)
 - rust-lang/rust#145053 (Add a lot of NLL `known-bug` tests)
 - rust-lang/rust#145055 (Move metadata symbol export from exported_non_generic_symbols to exported_symbols)
 - rust-lang/rust#145057 (Clean up some resolved test regressions of const trait removals in std)
 - rust-lang/rust#145068 (Readd myself to review queue)
 - rust-lang/rust#145070 (Add minimal `armv7a-vex-v5` tier three target)

r? `@ghost`
`@rustbot` modify labels: rollup
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. 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.

5 participants