-
Notifications
You must be signed in to change notification settings - Fork 557
Expand name resolution stub #2055
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
base: master
Are you sure you want to change the base?
Conversation
|
Thanks for posting. Lot of good here. The main thing I'd suggest, by way of helping to sharpen this up, would be to try to write a concise example after each claim, in as many cases as that might make sense, that demonstrates that the claim is true (and would not pass if the claim were false). Aside from the intrinsic benefit of having such examples, I think this might help to focus the text on the language-level effects. (It's not surprising, given the good research you've been doing, that some bits of this currently have some "description of the implementation" flavor.) |
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.
a fair number of comments are also contained inline in the documents
| @@ -1,4 +1,114 @@ | |||
| r[names.resolution] | |||
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.
duplicate of a section in names.md, not sure which to change or how
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.
Let's just delete the duplicates: #2060
src/names/name-resolution.md
Outdated
| * derive helpers used before their associated derive may not shadow other attributes or other derive helpers that are otherwise in scope after their derive | ||
| r[names.resolution.early.imports.errors.ambiguity.textualvspathbasedscope] | ||
| * path-based scope bindings for macros may not shadow textual scope bindings to macros | ||
| * https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces.use-shadow |
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.
The linked to section definitely needs to be moved and updated in some way. I think its subtly wrong as is, and also its named like one of the shadowing sections but this is actually a disallowed case of shadowing aka ambiguity error that is being documented.
| restricted based on their [visibility]. | ||
|
|
||
| * Names are resolved at three different stages of compilation. | ||
| * [Macros] and [use declarations] are resolved during macro expansion. |
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 feel like we're probably going to want to craft new terms of art for the various stages of name resolution. I think early resolution should be named in a way that indicates its required for macro expansion, type dependent name resolution is something I haven't really seen documented anywhere else but follows the same pattern, these are the names that depend on type information to be fully resolved.
Everything else is called "late resolution" but I hate that and would prefer to drop the late if possible.
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.
currently going with type-relative resolution for the last stage since that's the term vadim uses.
src/names/name-resolution.md
Outdated
| * early name resolution is the part of name resolution that happens during macro expansion | ||
| * early name resolution includes the resolution of imports and macros | ||
| * early name resolution is the minimum amount of resolution required to resolve macro invocations so they can be expanded. | ||
| * resolving imports is necessary to resolve macro invocations (as of 2018 edition i think, pretty sure this applies specifically to path-based scope for macros) |
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 not sure on this but my guess based on what I know so far is that function like proc macros have path based scope in all editions so resolving imports is probably still necessary in all editions. Most of my attention has been focused on MBE macros.
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 is needed for 2015 edition too.
For proc macros, as you said, but also for #[macro_export] macro_rules! which puts an additional modularized "path-based" declaration into the crate root module (which can be used both internally and from other crates).
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.
ACK, updated the text a bit, I still have a bit about how you can only re-export macros in 2018 edition which I'm pretty sure is true (edit: yup, tested it, works as expected only in 2018 and later). I also went and added a section about re-exporting to the path-based scope section in the mbe chapter.
| * except where shadowing is allowed | ||
| r[names.resolution.early.imports.errors.ambiguity.globvsglob] | ||
| * it is an error to name an item through ambiguous use declarations | ||
| * two globs imports which both have an item matching that name where the items are different |
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.
| r[names.resolution.early.imports.errors.ambiguity.globvsglob] | ||
| * it is an error to name an item through ambiguous use declarations | ||
| * two globs imports which both have an item matching that name where the items are different | ||
| * this is still an error even if there is a third non glob binding resolution to an item with the same name |
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.
citation needed
I expected this to be dependent upon ordering. Much of the ambiguity checking logic saves the first resolution result and checks that against subsequent results, which can end up suppressing errors that would have occured had the 2nd and 3rd results been compared against each other. I'm honestly surprised this isn't one of those cases, gonna check into why, but iirc globvsglob might be one of the few ambiguity errors that is checked outside of resolve_ident_in_scope_set
edit: yeah this is handled by try_define_local in rustc_resolve/src/imports.rs, entirely different piece of logic that I haven't looked at in a while
I feel like this should still be possible to trigger but I can't figure out how and afaict this claim came from my read of the logic in try_define_local not from some ui test, comment, or similar source
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 is still an error even if there is a third non glob binding resolution to an item with the same name
This doesn't seem right.
If there's an explicit item (import or not) with the same name, then it will shadow the ambiguous glob and will be used as a resolution instead.
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 expected this to be dependent upon ordering.
Resolution results are supposed to never depend on the item ordering (besides macro_rules with their "textual scope"), otherwise we won't be able to have things like parallel import resolution or import reordering in rustfmt.
In practice there may be dependencies in corner cases, but every such case is a bug.
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.
Resolution results are supposed to never depend on the item ordering
I guess this is worth putting into the reference as an axiom / expressed intent.
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.
Resolution results are supposed to never depend on the item ordering (besides
macro_ruleswith their "textual scope"), otherwise we won't be able to have things like parallel import resolution or import reordering in rustfmt.
you're of course right, I went back and revisited the example that I was thinking of when I made this comment, it has to do with how resolve_ident_in_scope_set only tracks the innermost resolution when tracking ambiguity errors, so in some cases you can add code and remove ambiguity despite still having the code that is otherwise illegal. the first m decl and the m import never get compared for ambiguity to each other and neither is ambiguous with the second m decl (innermost) so no error is emitted.
macro_rules! m {
() => {}
}
fn foo() {
use bar::m2 as m; // remove `m` decl below and this becomes an ambiguity error
macro_rules! m {
() => {}
}
m!();
}
mod bar {
macro_rules! m2 {
() => {}
}
pub(crate) use m2;
}This isn't necessarily a bug or anything but its where I got the ordering dependent thought. The order in which these are visited does impact whether errors get emitted, but that's the idea, and changing the order involves changing the code semantically, not reordering things lexically.
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.
Alright so I dug more into the bit of code which I think I have an incomplete understanding of that the initial comment was based off of. Here's the codepath I am trying to trigger and describe
- upon calling try_define_local
- the new resolution is a glob import
- there is already a resolution
- that resolution contains a shadowed glob res and a shadowing non glob res
- because the best binding is a non-glob and the new binding is a glob, we go into the second codepath
- the bindings through the shadowed glob and the new glob are not equal
- because there was a shadowed glob and it didn't match the res of the new glob binding, we produce a globvsglob ambiguity error
I think my problem is better understanding how try_define_local fits into the rest of import resolution, and when it will get called and when the different members get filled, gonna keep investigating
Edit: best I can tell it doesn't matter if that codepath gets executed. I only vaguely remember this but I recall us talking about how these ambiguity errors are attached to resolutions and only get emitted when we actually use an import. The fact that there exists a shadowed glob import is irrelevant because it is shadowed, so the non glob import will always be selected when resolving the associated name.
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.
The thing I don't understand is, when will the ambiguity errors from this codepath ever see the light of day?
As far as I can tell there are two scenarios where it gets triggered
- old binding is a glob import
- the new binding cannot be a glob import
- the old bindings glob import would have to not equal the glob import between the old and new best candidates, but those are both referring to old binding so they're always the same, impossible to go further in and attach the ambiguity error
- old binding is not a glob import
- This is the case described above, the old binding has to have a shadowed glob which ends up being where any ambiguity error is attached, seems like it will always then be ignored.
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 went ahead and added a bomb field to that associated ambiguity error to make it panic if it ever observed an error from that codepath and found the culprits
[ui] tests/ui/resolve/issue-105069.rs
[ui] tests/ui/resolve/issue-109153.rs
|
|
||
| * except where shadowing is allowed | ||
| r[names.resolution.early.imports.errors.ambiguity.globvsglob] | ||
| * it is an error to name an item through ambiguous use declarations |
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.
documented already
| * it is an error to name an item through ambiguous use declarations | ||
| * two globs imports which both have an item matching that name where the items are different | ||
| * this is still an error even if there is a third non glob binding resolution to an item with the same name | ||
| * it is not an error to have two glob imports which include items which would be ambiguous so long as you do not name one of those items through the ambiguous glob imports |
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.
documented
| For example, the [`cfg` attribute] and the [`cfg` macro] are two different entities with the same name in the macro namespace, but they can still be used in their respective context. | ||
|
|
||
| r[names.namespaces.sub-namespaces.use-shadow] | ||
| It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces. |
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 feel conflicted about this piece of info being in this section. On the one hand sub-namespaces are quite similar to shadowing, though they work via an independent mechanism. On the other, I'm fairly certain this is exclusively referring to the TextualVsPathBased ambiguity error with the added bit of information of pointing out that this is unaffected by sub-namespaces. I need to verify this but I suspect this is because of how imports bring in names from all namespaces so it probably always counts as a sub-namespace match preventing the subnamespace mismatch early exit from ever bailing before we report the ambiguity error.
Assuming this explanation is correct, we can maybe find a place within the use-declarations or mbe chapters to mention how imports are unaffected by subnamespaces. I'm currently wondering if it would make sense to move the subnamespace stuff to live in one of the macros chapters and link to it from here.
src/items/use-declarations.md
Outdated
| sure if this actually exists or is just proposed, TODO investigate) | ||
| * TODO example? This ones harder to do concisely afaik | ||
| r[names.resolution.early.imports.errors.ambiguity.derivehelper] | ||
| * derive helpers used before their associated derive may not shadow other attributes or other derive helpers that are otherwise in scope after their derive |
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 is something that exists under a deprecation lint in the final stage of its lifecycle (rust-lang/rust#79202), and hopefully will be removed next year.
Not sure if things like this are supposed to be documented in the reference.
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.
If the current behavior in rustc is considered to be a bug, then we document the intended behavior in the rules and add an admonition that describes what rustc does instead (including that there's a lint). In the admonition, we link to the relevant issue.
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.
ive gone ahead and moved this to be in the proc macro helper attribute section and setup a first pass attempt at documenting the intended behavior as I understand it, the admonition about deprecation, and an example.
| * [macro.decl.scope.path.ambiguity] | ||
| r[names.resolution.early.imports.errors.ambiguity.globvsouter] | ||
| * it is an error to shadow an outer name binding with a glob import | ||
| * This seems to only apply to early resolution (duh, I documented this as part of an early resolution codepath) |
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.
Most of the new text here need to be moved to name resolution, IMO.
I'd use src/items/use-declarations.md for things that happen at import definition time.
But most of ambiguity errors here do not happen at import definition time, but rather when someone tries to resolve a name from some unlucky point of view.
Only some situations create inherently ambiguous import definitions, like glob-vs-glob conflicts, and even then they are not reported at definition time.
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 don't mind moving this but the reason I put them alongside their items was because that seemed most consistent with how we documented other parts of name resolution, specifically how the names that are introduced by each item are documented next to their items and then theres an aggregated list linking to all those sections in the namespaces chapter.
My plan was to put ambiguity and shadowing sections alongside their items and aggregate links to all those sections in name-resolution.md.
You can see where I discussed this plan with eric starting here: #t-lang-docs/reference > name resolution @ 💬
src/names/name-resolution.md
Outdated
| * Names are resolved at three different stages of compilation. | ||
| * [Macros] and [use declarations] are resolved during macro expansion. | ||
| * This stage of resolution is known as "Early Resolution". | ||
| * Associated consts and functions, methods, and enum variants are resolved during type checking. |
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.
Trait::assoc_item, <Type as Trait>::assoc_item and Enum::Variant are resolved during late resolution, or even during early resolution if used in imports (traits and enums are "modules" in name resolution sense).
Type::assoc_item, <Type>::assoc_item, <Enum>::Variant and EnumTyAlias::Variant on the other hand are resolved during type-relative resolution.
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.
ACK
I went ahead and vaguely updated the associated section but I bet its still wrong. Don't worry about it too much until after I've had time to go thru and properly explore type-relative resolution and understand the difference between these cases.
|
|
||
| r[names.resolution.early.imports.shadowing] | ||
|
|
||
| The following is a list of situations where shadowing of use declarations is permitted: |
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.
| The following is a list of situations where shadowing of use declarations is permitted: | |
| The following is a list of situations where shadowing of use declarations is not permitted: |
?
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 think the original text is correct.
Use glob shadowing: https://doc.rust-lang.org/nightly/reference/items/use-declarations.html#r-items.use.glob.shadowing
macro textual scope shadowing: https://doc.rust-lang.org/nightly/reference/macros-by-example.html#r-macro.decl.scope.textual.shadow
In my mind the "not permitted" set is the list of ambiguity errors below
| * .visitation-order | ||
| * derive helpers | ||
| * not visited when resolving derive macros in the parent scope (starting scope) | ||
| * derive helpers compat |
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.
Same concern as above about this being deprecated and removed next year.
|
☔ The latest upstream changes (possibly 52ce896) made this pull request unmergeable. Please resolve the merge conflicts. |
|
@ehuss and I are looking at this together on the lang-docs office hours call, and we just wanted to express our appreciation to @petrochenkov for having been so responsive with @yaahc on working out the details here. This is a chapter that we've long wanted to exist, and we're thrilled and appreciative that @yaahc is digging in to shape this up. |
ff390be to
5307edc
Compare
currently mostly a skeleton of a draft so we can collaboratively massage it into shape more easily before filling in with proper reference verbiage.
hoping to take a significant chunk out of #568