Skip to content

Commit 22aaa92

Browse files
committed
rewrite bullet points as prose
1 parent 5e2aeb0 commit 22aaa92

File tree

1 file changed

+165
-115
lines changed

1 file changed

+165
-115
lines changed

src/names/name-resolution.md

Lines changed: 165 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -10,54 +10,117 @@ without conflict. Each name is valid within a [scope], or a region of source
1010
text where that name may be referenced. Access to certain names may be
1111
restricted based on their [visibility].
1212

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-
* `Type::assoc_item`, `<Type>::assoc_item`, `<Enum>::Variant` and `EnumTyAlias::Variant` are resolved during type checking
17-
* `Trait::assoc_item`, `<Type as Trait>::assoc_item` and `Enum::Variant` are resolved during late resolution
18-
* This stage of resolution is known as type-relative resolution.
19-
* in reality this is never talked about so I doubt it has a name yet.
20-
* All other names are resolved during AST lowering.
21-
* This stage of resolution is known as "Late Resolution".
22-
* Note, late resolution occurs before type dependent resolution.
13+
Name resolution is split into three stages throughout the compilation process.
14+
The first stage, Expansion-time resolution, resolves all [use declarations] and
15+
[macro invocations]. The second stage, Primary resolution, resolves all names
16+
that have not yet been resolved that do not depend on type information to
17+
resolve. The last stage, Type-relative resolution, resolves the remaining names
18+
once type information is available.
19+
20+
> Note
21+
>
22+
> * Expansion-time resolution is also known as "Early Resolution"
23+
> * Primary resolution is also known as "Late Resolution"
24+
25+
r[names.resolution.expansion]
26+
## Expansion-time name resolution
27+
28+
r[names.resolution.expansion.intro]
29+
30+
Expansion-time name resolution is the stage of name resolution necessary to
31+
complete macro expansion and fully generate a crate's AST. This stage requires
32+
the resolution of macro invocations and use declarations. Resolving use
33+
declarations is required to resolve [path-based scope] macro invocations.
34+
Resolving macro invocations is required in order to expand them.
35+
36+
The expansion process is iterative, alternately resolving imports, resolving
37+
and expanding macro invocations, then repeating until there are no further
38+
macros invocations to resolve. Once this process is completed all the imports
39+
are resolved again to ensure that the macro expansion process did not introduce
40+
any new ambiguious imports.
41+
42+
TODO: do we want to talk about this? feels like an implementation detail but
43+
also really helps to understand certain kinds of ambiguity errors that users
44+
can run into.
45+
46+
> Note
47+
>
48+
> This causes so called time traveling ambiguities, such as when a glob import introduces an item that is ambiguous with its own base path.
49+
>
50+
```rust
51+
macro_rules! m {
52+
() => { mod bar {} }
53+
}
54+
55+
mod bar {
56+
pub(crate) use m;
57+
}
58+
59+
fn f() {
60+
// * initially speculatively resolve bar to the module in the crate root
61+
// * expansion of m introduces a second bar module inside the body of f
62+
// * expansion-time resolution finalizes resolutions by re-resolving all
63+
// imports and macro invocations, sees the introduced ambiguity
64+
// and reports it as an error
65+
bar::m!(); // ERROR `bar` is ambiguous
66+
}
67+
```
68+
69+
TODO I would like to be able to link to a path-based scope section that
70+
discusses the various kinds of macros that can be invoked via path-based scope.
71+
Right now the section I know of off of the top of my head lives in the macros
72+
by example chapter.
73+
74+
r[names.resolution.expansion.imports]
2375

24-
r[names.resolution.early]
25-
## Early name resolution
76+
All use declarations are fully resolved during this stage of resolution.
77+
Type-relative paths cannot be resolved at this stage of compilation and will
78+
produce an error.
2679

27-
r[names.resolution.early.intro]
80+
* `Type::assoc_item`, `<Type>::assoc_item`, `<Enum>::Variant` and `EnumTyAlias::Variant` are resolved during type checking
81+
* `Trait::assoc_item`, `<Type as Trait>::assoc_item` and `Enum::Variant` are resolved during late resolution
2882

29-
* early name resolution is the part of name resolution that happens during macro expansion
30-
* early name resolution includes the resolution of imports and macros
31-
* early name resolution is the minimum amount of resolution required to resolve macro invocations so they can be expanded.
32-
* resolving imports is necessary to resolve macro invocations
33-
* specifically for path-based scope macro resolutions, this can occur
34-
either because of a `#[macro_export]`, a proc macro definition, or a
35-
reexport of a macro in 2018 or later code.
36-
* resolving macro invocations and tying them to macro declarations is necessary so they can be expanded
37-
* this process is iterative and repeats until there are no remaining unexpanded macro invocations (fixed point algorithm)
38-
* Post expansion these resolutions are checked again to ensure no new ambiguities were introduced by the expansion process
39-
* This causes so called time traveling ambiguities, such as when a glob import introduces an item that is ambiguous with its own base path.
83+
```rust
84+
mod my_mod {
85+
pub const Const: () = ();
4086

41-
TODO Document some time traveling ambiguitie examples, place in relevant ambiguity section
87+
pub enum MyEnum {
88+
MyVariant
89+
}
4290

43-
r[names.resolution.early.imports]
91+
impl MyEnum {
92+
pub const Const: () = ();
93+
}
4494

45-
* All imports are fully resolved at this point.
46-
* 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.
95+
pub type TypeAlias = MyEnum;
96+
}
4797

48-
TODO example of unsupported type dependent import
98+
fn foo() {
99+
use my_mod::MyEnum; // OK
100+
use my_mod::MyEnum::MyVariant; // OK
101+
use my_mod::TypeAlias; // OK
102+
use my_mod::TypeAlias::MyVariant; // Doesn't work
103+
use my_mod::MyEnum::Const; // Doesn't work
104+
use my_mod::Const; // OK
105+
let _ = my_mod::TypeAlias::MyVariant; // OK
106+
let _ = my_mod::MyEnum::Const; // OK
107+
}
108+
```
49109

50-
r[names.resolution.early.imports.shadowing]
110+
r[names.resolution.expansion.imports.shadowing]
51111

52112
The following is a list of situations where shadowing of use declarations is permitted:
53113

54114
* [use glob shadowing]
55115
* [macro textual scope shadowing]
56116

57-
r[names.resolution.early.imports.errors]
58-
r[names.resolution.early.imports.errors.ambiguity]
117+
r[names.resolution.expansion.imports.errors]
118+
r[names.resolution.expansion.imports.errors.ambiguity]
119+
120+
TODO shadowing and ambiguity may or may not represent the same section or one may be a subsection of the other
59121

60-
* shadowing and ambiguity may or may not represent the same section or one may be a subsection of the other
122+
The following is a list of situations where shadowing of use declarations is
123+
_NOT_ permitted, otherwise known as ambiguity errors:
61124

62125
* Builtin Attributes
63126
* Derive Helpers
@@ -70,34 +133,26 @@ r[names.resolution.early.imports.errors.ambiguity]
70133
r[names.resolution.expansion.imports.errors.ambiguity]
71134
## Ambiguities
72135

73-
> [!NOTE]
74-
> This section is incomplete.
75-
76136
r[items.use.ambiguities.intro]
77-
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.
137+
Some situations are an error when there is an ambiguity as to which name a
138+
`use` declaration refers. This happens when there are two name candidates that
139+
do not resolve to the same entity where neither import is
140+
[permitted](names.resolution.expansion.imports.shadowing) to shadow the other.
78141

79-
* except where shadowing is allowed
80142
r[names.resolution.early.imports.errors.ambiguity.globvsglob]
81143
* it is an error to name an item through ambiguous use declarations
82-
* two globs imports which both have an item matching that name where the items are different
83-
* this is not an error even if is a third non glob binding resolution to an item with the same name
144+
* two globs imports which both have an item matching that name where the items are different
145+
* this is not an error even if is a third non glob binding resolution to an item with the same name
84146
* 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
85147
* Should this live alongside use decls item page or in the name resolution page?
86148

87149
r[items.use.ambiguities.glob]
88-
Glob imports are allowed to import conflicting names in the same namespace as long as the name is not used.
89-
For example:
150+
Glob imports are allowed to import conflicting names in the same namespace as
151+
long as the name is not used. Names may not be resolved through ambiguous glob
152+
statements. Conflicting names from ambiguous glob statements may still be
153+
shadowed and used without producing an error.
90154

91-
TODO: move this section? It's documenting a situation that _isnt_ an ambiguity
92-
error. I've been working off of a pattern I think I saw in a few other
93-
locations, where we have specific error sections that document all of the
94-
reference relevant error cases associated with an some part of the language.
95-
* This section does technically document globvsglob ambituity errors, but
96-
it does so indirectly. We never explicitly mention "you can't resolve a
97-
name through a glob import when there are multiple candidate glob imports
98-
in scope that each resolve to different entities". We just say "you can
99-
do that if you don't actually use the ambiguious names" and have an
100-
example that shows that trying to use the name would be an error.
155+
For example:
101156

102157
```rust
103158
mod foo {
@@ -147,10 +202,11 @@ fn main() {
147202
```
148203

149204
r[names.resolution.early.imports.errors.ambiguity.builtin-attr]
150-
* it is an error to use a user defined attribute or derive macro with the same name as a builtin attribute (e.g. inline)
151-
* I think we may special case this one and allow certain kinds of
152-
ambiguities where the builtin-attr is shadowed by a user attribute (not
153-
sure if this actually exists or is just proposed, TODO investigate)
205+
It is an error to use a user defined attribute or derive macro with the same
206+
name as a builtin attribute (e.g. inline)
207+
* I think we may special case this one and allow certain kinds of ambiguities
208+
where the builtin-attr is shadowed by a user attribute (not sure if this
209+
actually exists or is just proposed, TODO investigate)
154210

155211
<!-- ignore: test doesn't support proc-macro -->
156212
```rust,ignore
@@ -179,57 +235,50 @@ pub fn bar() {}
179235
pub fn baz() {}
180236
181237
#[inline] // ERROR `inline` is ambiguous
182-
pub fn quix() {}
238+
pub fn qux() {}
239+
```
240+
241+
r[names.resolution.early.imports.errors.ambiguity.pathvstextualmacro]
242+
Path-based scope bindings for macros may not shadow textual scope bindings to macros.
243+
244+
```rust
245+
#[macro_export]
246+
macro_rules! m2 {
247+
() => {}
248+
}
249+
macro_rules! m {
250+
() => {}
251+
}
252+
pub fn foo() {
253+
m!(); // ERROR `m` is ambiguous
254+
use crate::m2 as m; // in scope for entire function body
255+
}
183256
```
184257

185-
r[names.resolution.early.imports.errors.ambiguity.textualvspathbasedscope]
186-
* path-based scope bindings for macros may not shadow textual scope bindings to macros
187-
* This is sort of an intersection between macros and imports, because at
188-
least in stable rust you can only get path-based macro resolutions from
189-
imports of mbe macros (and presumably from proc macro crates), but you
190-
can only get textual scope of macros from macro declarations
191-
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces.use-shadow
192-
* [macro.decl.scope.path.ambiguity]
193258
r[names.resolution.early.imports.errors.ambiguity.globvsouter]
194-
* it is an error to shadow an outer name binding with a glob import
195-
* This seems to only apply to early resolution (duh, I documented this as part of an early resolution codepath)
196-
* // Below we report various ambiguity errors.
197-
// We do not need to report them if we are either in speculative resolution,
198-
// or in late resolution when everything is already imported and expanded
199-
// and no ambiguities exist.
200-
* I attempted to produce an example using structs and it allowed the outer import to shadow the inner glob just fine
259+
it is an error to shadow an outer name binding with a glob import.
201260

202261
```rust
203262
mod bar {
204-
pub struct Name;
263+
pub mod foo {
264+
pub struct Name;
265+
}
205266
}
206267

207268
mod baz {
208-
pub struct Name;
269+
pub mod foo {
270+
pub struct Name;
271+
}
209272
}
210273

211-
use baz::Name;
274+
use baz::foo;
212275

213-
pub fn foo() {
276+
pub fn qux() {
214277
use bar::*;
215-
Name;
278+
use foo::Name; // `foo` is ambiguous
216279
}
217280
```
218281

219-
* I'd like to have a better understanding of why this doesn't trigger ambiguity errors.
220-
* I'm taking a guess but I think it has to do with how and when we resolve
221-
names during early resolution. We resolve all the imports but ambiguities
222-
only occur when observed, so we'd need to try to resolve Name during
223-
early resolution which simply won't happen because it is a struct so it
224-
will never be visited for resolution during expansion.
225-
* We will end up resolving the imports themselves, but they'll resolve fine
226-
because the imports themselves aren't ambiguous
227-
* By the time we get to late resolution we no longer expect there to be any
228-
ambiguities, so we will happily return the first resolution result and
229-
never search for additional ambiguities, so we resolve directly to
230-
`bar::Name` through the glob import
231-
232-
* doing it with macros produced the expected error
233282
```rust
234283
mod bar {
235284
macro_rules! name {
@@ -253,33 +302,34 @@ pub fn foo() {
253302
}
254303
```
255304

256-
* how does it work with imports? The same as macros, same error during early resolution
257-
258-
```rust
259-
mod bar {
260-
pub mod foo {
261-
pub struct Name;
262-
}
263-
}
264-
265-
mod baz {
266-
pub mod foo {
267-
pub struct Name;
268-
}
269-
}
270-
271-
use baz::foo;
272-
273-
pub fn foo() {
274-
use bar::*;
275-
use foo::Name; // `foo` is ambiguous
276-
}
277-
```
305+
> **NOTE** These ambiguity errors are specific to imports, even though they are
306+
> only observed when those imports are used, having multiple candidates
307+
> available for a given name during later stages of resolution is not
308+
> considered an error, so long as none of the imports themselves are ambiguous,
309+
> there will always be a single unambiguous closest resolution during later
310+
> stages.
311+
>
312+
> ```rust
313+
> mod bar {
314+
> pub struct Name;
315+
> }
316+
>
317+
> mod baz {
318+
> pub struct Name;
319+
> }
320+
>
321+
> use baz::Name;
322+
>
323+
> pub fn foo() {
324+
> use bar::*;
325+
> Name; // resolves to bar::Name
326+
> }
327+
> ```
278328
279329
r[names.resolution.early.imports.errors.ambiguity.globvsexpanded]
280330
* Grey Area
281331
282-
r[names.resolution.early.macros]
332+
r[names.resolution.expansion.macros]
283333
284334
* .visitation-order
285335
* derive helpers
@@ -301,7 +351,7 @@ r[names.resolution.early.macros]
301351
* 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
302352
* https://doc.rust-lang.org/nightly/reference/names/namespaces.html#r-names.namespaces.sub-namespaces
303353
304-
r[names.resolution.early.macros.errors.reserved-names]
354+
r[names.resolution.expansion.macros.errors.reserved-names]
305355
306356
the names cfg and cfg_attr are reserved in the macro attribute sub-namespace
307357

0 commit comments

Comments
 (0)