Skip to content

Commit 4af8acb

Browse files
committed
Expand name resolution stub
1 parent 2585fd6 commit 4af8acb

File tree

4 files changed

+286
-2
lines changed

4 files changed

+286
-2
lines changed

src/items/use-declarations.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,13 @@ r[items.use.ambiguities]
398398
r[items.use.ambiguities.intro]
399399
Some situations are an error when there is an ambiguity as to which name a `use` declaration refers. This happens when there are two name candidates that do not resolve to the same entity.
400400

401+
* except where shadowing is allowed
402+
r[names.resolution.early.imports.errors.ambiguity.globvsglob]
403+
* it is an error to name an item through ambiguous use declarations
404+
* two globs imports which both have an item matching that name where the items are different
405+
* this is still an error even if there is a third non glob binding resolution to an item with the same name
406+
* 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
407+
401408
r[items.use.ambiguities.glob]
402409
Glob imports are allowed to import conflicting names in the same namespace as long as the name is not used.
403410
For example:
@@ -442,6 +449,111 @@ fn main() {
442449
}
443450
```
444451

452+
r[names.resolution.early.imports.errors.ambiguity.builtin-attr]
453+
* it is an error to have a user defined attribute or derive macro with the same name as a builtin attribute (e.g. inline)
454+
* I think we may special case this one and allow certain kinds of
455+
ambiguities where the builtin-attr is shadowed by a user attribute (not
456+
sure if this actually exists or is just proposed, TODO investigate)
457+
* TODO example? This ones harder to do concisely afaik
458+
r[names.resolution.early.imports.errors.ambiguity.derivehelper]
459+
* derive helpers used before their associated derive may not shadow other attributes or other derive helpers that are otherwise in scope after their derive
460+
* TODO example? This ones harder to do concisely afaik
461+
r[names.resolution.early.imports.errors.ambiguity.textualvspathbasedscope]
462+
* path-based scope bindings for macros may not shadow textual scope bindings to macros
463+
* This is sort of an intersection between macros and imports, because at
464+
least in stable rust you can only get path-based macro resolutions from
465+
imports of mbe macros (and presumably from proc macro crates), but you
466+
can only get textual scope of macros from macro declarations
467+
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces.use-shadow
468+
* [macro.decl.scope.path.ambiguity]
469+
r[names.resolution.early.imports.errors.ambiguity.globvsouter]
470+
* it is an error to shadow an outer name binding with a glob import
471+
* This seems to only apply to early resolution (duh, I documented this as part of an early resolution codepath)
472+
* // Below we report various ambiguity errors.
473+
// We do not need to report them if we are either in speculative resolution,
474+
// or in late resolution when everything is already imported and expanded
475+
// and no ambiguities exist.
476+
* I attempted to produce an example using structs and it allowed the outer import to shadow the inner glob just fine
477+
```rust
478+
mod bar {
479+
pub struct Name;
480+
}
481+
482+
mod baz {
483+
pub struct Name;
484+
}
485+
486+
use baz::Name;
487+
488+
pub fn foo() {
489+
use bar::*;
490+
Name;
491+
}
492+
```
493+
494+
* I'd like to have a better understanding of why this doesn't trigger ambiguity errors.
495+
* I'm taking a guess but I think it has to do with how and when we resolve
496+
names during early resolution. We resolve all the imports but ambiguities
497+
only occur when observed, so we'd need to try to resolve Name during
498+
early resolution which simply won't happen because it is a struct so it
499+
will never be visited for resolution during expansion.
500+
* We will end up resolving the imports themselves, but they'll resolve fine
501+
because the imports themselves aren't ambiguous
502+
* By the time we get to late resolution we no longer expect there to be any
503+
ambiguities, so we will happily return the first resolution result and
504+
never search for additional ambiguities, so we resolve directly to
505+
`bar::Name` through the glob import
506+
507+
* doing it with macros produced the expected error
508+
```rust
509+
mod bar {
510+
macro_rules! name {
511+
() => {}
512+
}
513+
pub(crate) use name;
514+
}
515+
516+
mod baz {
517+
macro_rules! name {
518+
() => {}
519+
}
520+
pub(crate) use name;
521+
}
522+
523+
use baz::name;
524+
525+
pub fn foo() {
526+
use bar::*;
527+
name!(); // ERROR `name` is ambiguous
528+
}
529+
```
530+
531+
* how does it work with imports? The same as macros, same error during early resolution
532+
533+
```rust
534+
mod bar {
535+
pub mod foo {
536+
pub struct Name;
537+
}
538+
}
539+
540+
mod baz {
541+
pub mod foo {
542+
pub struct Name;
543+
}
544+
}
545+
546+
use baz::foo;
547+
548+
pub fn foo() {
549+
use bar::*;
550+
use foo::Name; // `foo` is ambiguous
551+
}
552+
```
553+
554+
r[names.resolution.early.imports.errors.ambiguity.globvsexpanded]
555+
* Grey Area
556+
445557
[`extern crate`]: extern-crates.md
446558
[`macro_rules`]: ../macros-by-example.md
447559
[`self`]: ../paths.md#self
@@ -460,3 +572,4 @@ fn main() {
460572
[tool attributes]: ../attributes.md#tool-attributes
461573
[type alias]: type-aliases.md
462574
[type namespace]: ../names/namespaces.md
575+
[macro.decl.scope.path.ambiguity]: ../macros-by-example.md#macro.decl.scope.path.ambiguity

src/macros-by-example.md

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,50 @@ fn foo() {
326326
// m!(); // Error: m is not in scope.
327327
```
328328

329+
* textual scope name bindings for macros may shadow path-based scope bindings
330+
to macros
331+
332+
```rust
333+
macro_rules! m {
334+
() => {
335+
println!("m");
336+
};
337+
}
338+
339+
#[macro_export]
340+
macro_rules! m2 {
341+
() => {
342+
println!("m2");
343+
};
344+
}
345+
346+
use crate::m2 as m;
347+
348+
m!(); // prints "m\n"
349+
```
350+
351+
r[macro.decl.scope.textual.ambiguity.moreexpandedvsouter]
352+
* it is an error for name bindings from macro expansions to shadow name bindings from outside of those expansions
353+
354+
```rust
355+
macro_rules! name {
356+
() => {}
357+
}
358+
359+
macro_rules! define_name {
360+
() => {
361+
macro_rules! name {
362+
() => {}
363+
}
364+
}
365+
}
366+
367+
fn foo() {
368+
define_name!();
369+
name!(); // ERROR `name` is ambiguous
370+
}
371+
```
372+
329373
r[macro.decl.scope.macro_use]
330374
### The `macro_use` attribute
331375

@@ -397,6 +441,30 @@ r[macro.decl.scope.path.export]
397441
Macros labeled with `#[macro_export]` are always `pub` and can be referred to
398442
by other crates, either by path or by `#[macro_use]` as described above.
399443

444+
r[macro.decl.scope.path.ambiguity]
445+
* path-based scope bindings for macros may not shadow textual scope bindings to macros
446+
* This is sort of an intersection between macros and imports, because at
447+
least in stable rust you can only get path-based macro resolutions from
448+
imports of mbe macros (and presumably from proc macro crates), but you
449+
can only get textual scope of macros from macro declarations
450+
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces.use-shadow
451+
452+
```rust
453+
#[macro_export]
454+
macro_rules! m2 {
455+
() => {}
456+
}
457+
458+
macro_rules! m {
459+
() => {}
460+
}
461+
462+
pub fn foo() {
463+
m!(); // ERROR `m` is ambiguous
464+
use crate::m2 as m;
465+
}
466+
```
467+
400468
r[macro.decl.hygiene]
401469
## Hygiene
402470

src/names/name-resolution.md

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,106 @@
1+
r[names.resolution]
12
# Name resolution
23

3-
> [!NOTE]
4-
> This is a placeholder for future expansion.
4+
r[names.resolution.intro]
5+
6+
_Name resolution_ is the process of tying paths and other identifiers to the
7+
declarations of those entities. Names are segregated into different
8+
[namespaces], allowing entities in different namespaces to share the same name
9+
without conflict. Each name is valid within a [scope], or a region of source
10+
text where that name may be referenced. Access to certain names may be
11+
restricted based on their [visibility].
12+
13+
* Names are resolved at three different stages of compilation.
14+
* [Macros] and [use declarations] are resolved during macro expansion.
15+
* This stage of resolution is known as "Early Resolution".
16+
* Associated consts and functions, methods, and enum variants are resolved during type checking.
17+
* This stage of resolution is known as type dependent resolution.
18+
* in reality this is never talked about so I doubt it has a name yet.
19+
* All other names are resolved during AST lowering.
20+
* This stage of resolution is known as "Late Resolution".
21+
* Note, late resolution occurs before type dependent resolution.
22+
23+
r[names.resolution.early]
24+
## Early name resolution
25+
26+
r[names.resolution.early.intro]
27+
28+
* early name resolution is the part of name resolution that happens during macro expansion
29+
* early name resolution includes the resolution of imports and macros
30+
* early name resolution is the minimum amount of resolution required to resolve macro invocations so they can be expanded.
31+
* 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)
32+
* resolving macro invocations and tying them to macro declarations is necessary so they can be expanded
33+
* this process is iterative and repeats until there are no remaining unexpanded macro invocations (fixed point algorithm)
34+
* Post expansion these resolutions are checked again to ensure no new ambiguities were introduced by the expansion process
35+
* This causes so called time traveling ambiguities, such as when a glob import introduces an item that is ambiguous with its own base path.
36+
37+
TODO Document some time traveling ambiguitie examples, place in relevant ambiguity section
38+
39+
r[names.resolution.early.imports]
40+
41+
* All imports are fully resolved at this point.
42+
* imports of names that cannot be fully resolved during macro expansion, such as those depending on type information, are not supported and will produce an error.
43+
44+
TODO example of unsupported type dependent import
45+
46+
r[names.resolution.early.imports.shadowing]
47+
48+
The following is a list of situations where shadowing of use declarations is permitted:
49+
50+
* [use glob shadowing]
51+
* [macro textual scope shadowing]
52+
53+
r[names.resolution.early.imports.errors]
54+
r[names.resolution.early.imports.errors.ambiguity]
55+
56+
* shadowing and ambiguity may or may not represent the same section or one may be a subsection of the other
57+
58+
* Builtin Attributes
59+
* Derive Helpers
60+
* Textual Vs Path-based Scope
61+
* Glob vs Outer
62+
* Glob vs Glob
63+
* ~~Glob vs Expanded~~ pretty certain we don't want to mention this one
64+
* More Expanded vs Outer
65+
66+
r[names.resolution.early.macros]
67+
68+
* .visitation-order
69+
* derive helpers
70+
* not visited when resolving derive macros in the parent scope (starting scope)
71+
* derive helpers compat
72+
* always visited
73+
* macro rules bindings (textual scope macros)
74+
* always visited
75+
* modules (path-based scope macros)
76+
* always visited
77+
* macrouseprelude
78+
* not visited in 2018 and later when `#[no_implicit_prelude]` is present
79+
* stdlibprelude
80+
* always visited for macro resolutions
81+
* builtinattrs
82+
* always visited
83+
* .subnamespaces
84+
* macros are split into two subnamespaces, one for bang macros, and the other for attributes and derives. Resolution candidates from the incorrect subnamespace are ignored
85+
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces
86+
87+
r[names.resolution.early.macros.errors.reserved-names]
88+
89+
the names cfg and cfg_attr are reserved in the macro attribute sub-namespace
90+
91+
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces
92+
93+
94+
r[names.resolution.late]
95+
96+
r[names.resolution.type-dependent]
97+
98+
[use glob shadowing]: ../items/use-declarations.md#items.use.glob.shadowing
99+
[Macros]: ../macros.md
100+
[use declarations]: ../items/use-declarations.md
101+
[macro textual scope shadowing]: ../macros-by-example.md#macro.decl.scope.textual.shadow
102+
[`let` bindings]: ../statements.md#let-statements
103+
[item definitions]: ../items.md
104+
[namespaces]: ../names/namespaces.md
105+
[scope]: ../names/scopes.md
106+
[visibility]: ../visibility-and-privacy.md

src/names/namespaces.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ For example, the [`cfg` attribute] and the [`cfg` macro] are two different entit
119119

120120
r[names.namespaces.sub-namespaces.use-shadow]
121121
It is still an error for a [`use` import] to shadow another macro, regardless of their sub-namespaces.
122+
* TODO revisit
122123

123124
[`cfg` attribute]: ../conditional-compilation.md#the-cfg-attribute
124125
[`cfg` macro]: ../conditional-compilation.md#the-cfg-macro

0 commit comments

Comments
 (0)