-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Try to break resolve into more isolated parts #63400
Conversation
f5bf56d
to
4b564f1
Compare
Actually, let's r? @matklad @Xanewok on this, nobody knows the nuances of this code anyway and this PR doesn't do many nuanced things beside perhaps some of the @rust-lang/compiler @davidtwco are also welcome to review. The PR is better reviewed in per-commit fashion. |
@@ -395,7 +400,7 @@ impl<'a> Resolver<'a> { | |||
}); | |||
self.potentially_unused_imports.push(directive); | |||
let imported_binding = self.import(binding, directive); | |||
if ptr::eq(self.current_module, self.graph_root) { | |||
if ptr::eq(parent, self.graph_root) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Random aside, is there any chance we could compare modules by DefId
or something?
Also, the way they are used (for block scopes as well), they feel a bit more like "(def) scopes" than "modules" (but we also have the other kind of scope, the Rib
s, which can contain runtime variables).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Module
in resolve is either a mod
, or enum
, or trait
, or an ast::Block
.
The naming seems ancient, I don't know why it was chosen, perhaps there was only mod
initially, but then it got extended.
Modules and many other things (including those without IDs) are allocated on the resolver arena, so they use referential equality pretty regularly.
In this case ptr::eq
is just simpler, I guess, than extracting the optional DefId
s and comparing them if they exist.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, wait, two different Module
s can have the same DefId
in cross-crate scenarios, see #57181.
I think that case cannot apply to self.graph_root
specifically, though.
@petrochenkov I'm a bit curious, what "inputs" does late resolution have, i.e. what does it use from the |
(PathSource::Pat, false) | (PathSource::TupleStruct, false) => "E0531", | ||
(PathSource::TraitItem(..), true) => "E0575", | ||
(PathSource::TraitItem(..), false) => "E0576", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nikomatsakis This sort of error code juggling feels very silly tbh.
@bors r+ |
📌 Commit 4b564f1da0fe91df0bc1022f967b556c5663bfcb has been approved by |
@bors p=1 (this PR conflicts with other resolve changes in the queue and is hard to rebase) |
🔒 Merge conflict This pull request and the master branch diverged in a way that cannot be automatically merged. Please rebase on top of the latest master branch, and let the reviewer approve again. How do I rebase?Assuming
You may also read Git Rebasing to Resolve Conflicts by Drew Blessing for a short tutorial. Please avoid the "Resolve conflicts" button on GitHub. It uses Sometimes step 4 will complete without asking for resolution. This is usually due to difference between how Error message
|
☔ The latest upstream changes (presumably #63428) made this pull request unmergeable. Please resolve the merge conflicts. |
Move `Resolver` fields specific to late resolution to the new visitor. The `current_module` field from `Resolver` is replaced with two `current_module`s in `LateResolutionVisitor` and `BuildReducedGraphVisitor`. Outside of those visitors `current_module` is replaced by passing `parent_scope` to more functions and using the parent module from it. Visibility resolution no longer have access to later resolution methods and has to use early resolution, so its diagnostics in case of errors regress slightly.
Instead of tracking current module and other components separately. (`ParentScope` includes the module as a component.)
It's now immediately clear what fields belong to the global resolver state and what are specific to passes/visitors.
Rename it to `report_error` and move into `diagnostics.rs` Also turn `check_unused` into a method on `Resolver`
Move methods logically belonging to build-reduced-graph into `impl BuildReducedGraphVisitor` and `build_reduced_graph.rs` Move types mostly specific to late resolution closer to the late resolution visitor
Cleanup some surrounding code. Support resolution of intra doc links in unnamed block scopes. (Paths from rustdoc now use early resolution and no longer need results of late resolution like all the built ribs.) Fix one test hitting file path limits on Windows.
Make the `is_import` flag in `ScopeSet` independent from namespace Fix rebase
@bors r=eddyb |
📌 Commit 319f0de has been approved by |
@bors p=20 |
Most of the resolver fields, I think? A few of the |
Try to break resolve into more isolated parts Some small step towards resolve librarification. "Late resolution" is the pass that resolves most of names in a crate beside imports and macros. It runs when the crate is fully expanded and its module structure is fully built. So we just walk through the crate and resolve all the expressions, types, etc. This pass is pretty self-contained, but it was previously done by implementing `Visitor` on the whole `Resolver` (which is used for many other tasks), and fields specific to this pass were indiscernible from the global `Resolver` state. This PR moves the late resolution pass into a separate visitor and a separate file, fields specific to this visitor are moved from `Resolver` as well. I'm especially happy about `current_module` being removed from `Resolver`. It was used even for operations not related to visiting and changing the `current_module` position in process. It was also used as an implicit argument for some functions used in this style ```rust let orig_current_module = mem::replace(&mut self.current_module, module); self.resolve_ident_somewhere(); self.current_module = orig_current_module; ``` and having effects on e.g. privacy checking somewhere deeply inside `resolve_ident_somewhere`. Now we explicitly pass a `ParentScope` to those functions instead, which includes the module and some other data describing our position in the crate relatively to which we resolve names. Rustdoc was one of the users of `current_module`, it set it for resolving intra-doc links. Now it passes it explicitly as an argument as well (I also supported resolving paths from rustdoc in unnamed blocks as a drive-by fix). Visibility resolution is also changed to use early resolution (which is correct because it's used during the work of `BuildReducedGraphVisitor`, i.e. integration of a new AST fragment into the existing partially built module structures.) instead of untimely late resolution (which worked only due to restrictions on paths in visibilities like inability to refer to anything except ancestor modules). This slightly regresses its diagnostics because late resolution has a more systematic error detection and recovery currently. Due to changes in `current_module` and visibilities `BuildReducedGraphVisitor` ended up almost as heavily affected by this refactoring as late resolution. Fixes rust-lang#63223 (due to visibility resolution changes).
I love this so much, thank you! Could you perhaps add a short comment at the top of |
also cc @vlad20012: this new setup might serve as an inspiration for rewriting IntelliJ Rust's name resolution :) |
Some file-level docs are added in #63535. |
rustdoc: Add test for fixed issue rust-lang#61732 was almost certainly fixed by rust-lang#63400. Closes rust-lang#61732
Some small step towards resolve librarification.
"Late resolution" is the pass that resolves most of names in a crate beside imports and macros.
It runs when the crate is fully expanded and its module structure is fully built.
So we just walk through the crate and resolve all the expressions, types, etc.
This pass is pretty self-contained, but it was previously done by implementing
Visitor
on the wholeResolver
(which is used for many other tasks), and fields specific to this pass were indiscernible from the globalResolver
state.This PR moves the late resolution pass into a separate visitor and a separate file, fields specific to this visitor are moved from
Resolver
as well.I'm especially happy about
current_module
being removed fromResolver
.It was used even for operations not related to visiting and changing the
current_module
position in process.It was also used as an implicit argument for some functions used in this style
and having effects on e.g. privacy checking somewhere deeply inside
resolve_ident_somewhere
.Now we explicitly pass a
ParentScope
to those functions instead, which includes the module and some other data describing our position in the crate relatively to which we resolve names.Rustdoc was one of the users of
current_module
, it set it for resolving intra-doc links.Now it passes it explicitly as an argument as well (I also supported resolving paths from rustdoc in unnamed blocks as a drive-by fix).
Visibility resolution is also changed to use early resolution (which is correct because it's used during the work of
BuildReducedGraphVisitor
, i.e. integration of a new AST fragment into the existing partially built module structures.) instead of untimely late resolution (which worked only due to restrictions on paths in visibilities like inability to refer to anything except ancestor modules).This slightly regresses its diagnostics because late resolution has a more systematic error detection and recovery currently.
Due to changes in
current_module
and visibilitiesBuildReducedGraphVisitor
ended up almost as heavily affected by this refactoring as late resolution.Fixes #63223 (due to visibility resolution changes).