-
Notifications
You must be signed in to change notification settings - Fork 13k
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
resolve: allow super in module in block to refer to block items #79309
Conversation
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
I made a Pre-RFC for adding a new |
Thanks, that's a really interesting thread which I'd totally missed at the time. Explains why I couldn't find much about this on the Rust issue tracker! The The other proposal I saw in that thread was plain
I've added these to the alternatives above. |
I don't this is a desirable change, regardless of breakage. |
👍 I'm very happy to close this PR and try a different implementation depending on direction from the lang team. |
☔ The latest upstream changes (presumably #82281) made this pull request unmergeable. Please resolve the merge conflicts. |
This seems potentially reasonable to me, and the rationale makes sense. I have a few questions, which I don't see answered here:
|
5a5100e
to
68b9cdf
Compare
☀️ Try build successful - checks-actions |
Some language features simply work at module granularity, otherwise it would not make sense for modules to exist. Privacy works at module granularity - you can have a Paths work at module granularity, unnamed blocks or functions do not participate in paths like Would you want to make Do you have any examples of other languages where you can refer to outer unnamed scopes (like blocks) by name? |
@petrochenkov That's a compelling argument. In particular, I appreciate your observation about paths: there's a valuable property that if you're in I want to reiterate that while I think there may be some value in improving this particular case, it also seems like a sufficiently special-case scenario that it isn't worth adding substantial complexity for. I'd like to explore possible solutions, but I do think we should set a high bar for adopting one of them. As far as I can tell, the scheme proposed by the PR would say that if you're inside a module that's nested inside a function, when you go up via In other words, with this PR, That seems like a relatively understandable property from a language perspective. That said, from a compiler perspective, is that utterly at odds with how name/path resolution works? |
I'm going to go ahead and run this through craterbot, and if this causes any errors at all, I think we probably wouldn't want to pursue it further. @craterbot check |
👌 Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
I don't like the proposal as is, for basically the same reasons as @petrochenkov. I'd like to see it be explicit. I think making a path separator is right out (e.g. I postulated |
We discussed this in today's @rust-lang/lang meeting. The general sentiment was that we don't want to further complicate name resolution in this way, for this use case. We'd be open to hearing proposals for alternative solutions for the same use case that don't complicate name resolution or involve a potentially breaking transition. You may wish to take detailed discussions of potential alternatives to Zulip or Internals. We'd suggest proposing a new RFC for that. @craterbot abort |
Team member @joshtriplett has proposed to close this. The next step is review by the rest of the tagged team members: No concerns currently listed. Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up! See this document for info about what commands tagged team members can give me. |
🗑️ Experiment ℹ️ Crater is a tool to run experiments across parts of the Rust ecosystem. Learn more |
Specifically, I dislike the idea that |
🔔 This is now entering its final comment period, as per the review above. 🔔 |
Thanks to all in this thread (and the lang team) for discussing this. I think your concerns with this approach are valid. In particular I think that if we change Of the alternatives presented ( While explicit solutions are likely better, it might also be nice if an eventual solution resolved the doctest case presented in the OP without requiring users to be aware that doctests expand inside functions. These two goals are probably at odds. I'll continue to ponder and write a pre-RFC on internals if I settle on something I like. |
The final comment period, with a disposition to close, as per the review above, is now complete. As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed. |
This PR attempts to resolve #79260 by changing the way the resolver interprets
super
inmod
items that are children of blocks.Most notably, this means that doctests with modules which use other items from the snippet can now compile:
At the moment this doctest will fail to compile. (playground)
Background
At the moment, when an inline module is inside a block, the
super
keyword refers to the parent module of the block. The result of this is that the inline module has no way to refer to its sibling items inside the block.(playground)
The current interpretation of the
super
keyword is theoretically pure, however I want to argue it has practical drawbacks. As well as issues with doctests as per the first example, it means that in general code of the following form is interpreted differently depending on whether it is inside a block:In isolation it seems fair to me to assume that most readers would state this code compiles and that
foo::FOO
can resolve. However, if this code is actually inside a block, it doesn't compile.Proposed Design
This PR modifies the behaviour of the
super
keyword in examples like the above such that usage inside a module which is a child of (one of more) blocks will attempt to resolve items from those blocks as well as the parent module of those blocks.Ambiguity is resolved by always preferring items that are closer to the module in the hierarchy. E.g. in the following example:
the item
foo::FOO
will resolve to have the value1
.This example just above is unfortunately also an example where current code could break under these changes. Today the compiler would not see the
FOO
constant which is the child ofmain
from its siblingmod foo
, and so the itemfoo::FOO
today would instead resolve to have the value0
.(Assuming, of course, that the snippet just above were not itself wholly inside a block, in which case the compiler today would not consider the
FOO
on the first line either 🙃)I would argue inline modules inside blocks are rare. (I myself only found this case while testing a macro which created a module and discovering it did not compile when inside a block.) So this breakage is not likely to be widespread. Nevertheless we should assess carefully.
If we were to take a conservative approach it should be possible to change this PR to be backwards compatible. I'd propose in that case to push the complete change to the proposed design in this PR via an edition boundary, with a lint to warn of cases that will change.
Alternatives
I'm quite happy to throw this PR away in favour of an alternative design. I'll try to list them here as I see them:
#[transparent] mod foo
could behave as if it did not create a name boundary, which would allow these modules in blocks to share scope with their parent block. (See Cannot refer to item inside function from module inside function #79260 (comment))fn
modifier in use statements. (See https://internals.rust-lang.org/t/pre-rfc-add-fn-path-qualifier/10900)use;
. I'd personally prefer it was a new keyword e.g.use scope::*;
oruse scope::foo;
- that probably needs a new edition though as a new keyword.TODO
rustc_resolve
codebase. Please be unafraid to encourage me to rewrite this PR multiple times to get the cleanest result!