-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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
refactor: create multiple HIR items for imports #51425
refactor: create multiple HIR items for imports #51425
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Lol of course the test that breaks is a rustdoc test. The test seems to make sure that we rename re-exports to have the name of the export, rather than the original struct name. I'm taking a look... |
It looks like... travis passed?! I suppose it's ready for people to take a look. One place i'd like to make sure about is save-analysis. Right now the |
cc @nrc about the save-analysis questions up-thread. This is a compiler refactor that should be extended to save-analysis way better than i'm doing it right now, but doing that may require messing with the output format. I'm not familiar with save-analysis, so i don't know how involved the change will be. |
Will review today/tomorrow. |
I don't think this generally goes into the right direction. I think we can go from the end goal here:
I want to do a similar refactoring in resolve and desugar single import |
@petrochenkov I suppose that makes sense given that most paths only can access one NS. In terms of further expanding |
This is already kinda done locally in resolve (see
They would allow to fix issues like #15702 (but not #23937) while keeping the stability pass in its current place and not moving it to resolve. I'd rather prefer to move it to resolve to fix #23937 as well.
If stability pass is moved, then it should be possible to reduce imports in HIR to ExportMap, unless rustdoc needs to display glob imports precisely or some import extensions like this are adopted. |
@QuietMisdreavus changing the output of save-analysis to have mutiple defs per ref would not be too hard, you'd just change the data format (in rls-data) and how that is read (in rls-analysis), any tools rely on the rls-analysis crate not the data directly. However, I think that is only the right approach for imports. For all other refs, by the time we get to generating save-analysis there should only be one name in play since we know which namespace we're using by type checking at the latest (iiuc). |
I started with this approach before moving to the one in this PR. (It still started with changing It seems like you're proposing some new kind of map in the resolver just for the |
Yes, an additional table should get the job done. |
☔ The latest upstream changes (presumably #50617) made this pull request unmergeable. Please resolve the merge conflicts. |
72f9e04
to
df8c30d
Compare
Okay, i think i have something. I've just force-pushed an update that takes a different approach, more like @petrochenkov's suggestion. I had to modify the AST for use-trees to hold some new |
The job Click to expand the log.
I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
df8c30d
to
02121f3
Compare
src/librustc/hir/lowering.rs
Outdated
@@ -571,6 +574,21 @@ impl<'a> LoweringContext<'a> { | |||
}) | |||
} | |||
|
|||
fn expect_full_def_from_use(&mut self, id: NodeId) -> Vec<Def> { |
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.
This could return an impl Iterator<Item=Def>
by not doing the is_empty
dance which is repeated at the use site of this function anyway.
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, it turns out i can! I was scarred because i tried doing that to a version of lower_path
(which i wound up taking out when we moved to the AST modification) and wound up with exotic lifetime errors due to the introduction of a &ast::Path
with an unaccounted lifetime. But this one doesn't have to use anything external for its mapping, so it works out.
src/librustc/hir/lowering.rs
Outdated
let mut defs = self.expect_full_def_from_use(id).into_iter(); | ||
// we want to return *something* from this function, so hang onto the first item | ||
// for later | ||
let mut ret_def = defs.next().unwrap_or(Def::Err); |
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.
use site duplication here
let vis = vis.clone(); | ||
let name = name.clone(); | ||
let span = path.span; | ||
self.resolver.definitions().create_def_with_parent( |
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.
It could now be possible to not create def ids here, but instead in
rust/src/librustc/hir/map/def_collector.rs
Line 131 in 538fea5
fn visit_use_tree(&mut self, use_tree: &'a UseTree, id: NodeId, _nested: bool) { |
create_def
method. I'm not sure if it's possible, because you'd already need to know how many definitions you are going to need
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.
I'm guessing it's problematic to create all the defs ahead of time and leave them potentially unused? Is there a way to pull them back out later (or mark them used in a way that won't affect anything)?
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.
Yes, that's what I worry about, too.
/// | ||
/// The extra `NodeId`s are for HIR lowering, when additional statements are created for each | ||
/// namespace. | ||
Simple(Option<Ident>, NodeId, NodeId), |
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.
Is this really necessary?
Can't we create HIR items with fresh NodeId
s "out of thin air"?
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.
While possible, we'd need to insert a cache for the NodeId
of the Simple
variant to the generated NodeId
s and carry that one around in lowering.
The reason for that is that you need the same ids in https://github.com/rust-lang/rust/pull/51425/files#diff-64b696b0ef6ad44140e973801ed82b25R2742 and https://github.com/rust-lang/rust/pull/51425/files#diff-64b696b0ef6ad44140e973801ed82b25R2409
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.
I tried creating the NodeId
s during lowering, but they weren't referenced by the module after lowering, so type collection hit an error when it tried to account for these items. Unless there's an easier way to reference the new Item
s and their IDs when the module's ItemId
s are lowered, this is what @oli-obk came up with.
PR description also needs an update. |
I've updated the PR description. |
@bors r+ |
📌 Commit 903e2c8 has been approved by |
…=petrochenkov refactor: create multiple HIR items for imports When lowering `use` statements into HIR, they get a `Def` of the thing they're pointing at. This is great for things that need to know what was just pulled into scope. However, this is a bit misleading, because a `use` statement can pull things from multiple namespaces if their names collide. This is a problem for rustdoc, because if there are a module and a function with the same name (for example) then it will only document the module import, because that's that the lowered `use` statement points to. The current version of this PR does the following: * Whenever the resolver comes across a `use` statement, it loads the definitions into a new `import_map` instead of the existing `def_map`. This keeps the resolutions per-namespace so that all the target definitions are available. * When lowering `use` statements, it looks up the resolutions in the `import_map` and creates multiple `Item`s if there is more than one resolution. * To ensure the `NodeId`s are properly tracked in the lowered module, they need to be created in the AST, and pulled out as needed if multiple resolutions are available. Fixes #34843
☀️ Test successful - status-appveyor, status-travis |
rustdoc: import cross-crate macros alongside everything else The thrilling conclusion of the cross-crate macro saga in rustdoc! After #51425 made sure we saw all the namespaces of an import (and prevented us from losing the `vec!` macro in std's documentation), here is the PR to handle cross-crate macro re-exports at the same time as everything else. This way, attributes like `#[doc(hidden)]` and `#[doc(no_inline)]` can be used to control how the documentation for these macros is seen, rather than rustdoc inlining every macro every time. Fixes #50647
rustdoc: Hide struct and enum variant constructor imports This is fallout from #51425. The duplicate variant imports can be seen [here](https://doc.rust-lang.org/nightly/std/prelude/v1/index.html) for example. This is fixing a regression so could be backported to beta. r? @QuietMisdreavus
When lowering
use
statements into HIR, they get aDef
of the thing they're pointing at. This is great for things that need to know what was just pulled into scope. However, this is a bit misleading, because ause
statement can pull things from multiple namespaces if their names collide. This is a problem for rustdoc, because if there are a module and a function with the same name (for example) then it will only document the module import, because that's that the lowereduse
statement points to.The current version of this PR does the following:
use
statement, it loads the definitions into a newimport_map
instead of the existingdef_map
. This keeps the resolutions per-namespace so that all the target definitions are available.use
statements, it looks up the resolutions in theimport_map
and creates multipleItem
s if there is more than one resolution.NodeId
s are properly tracked in the lowered module, they need to be created in the AST, and pulled out as needed if multiple resolutions are available.Fixes #34843