Skip to content

Commit 7d89142

Browse files
committed
Update the RFC with discussion from the comment thread
1 parent efa734d commit 7d89142

File tree

1 file changed

+204
-9
lines changed

1 file changed

+204
-9
lines changed

text/0000-name-resolution.md

+204-9
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,112 @@ At the same time, we should be able to accept more Rust programs by tweaking the
3636
current rules around imports and name shadowing. This should make programming
3737
using imports easier.
3838

39+
40+
## Some issues in Rust's name resolution
41+
42+
Whilst name resolution is sometimes considered a simple part of the compiler,
43+
there are some details in Rust which make it tricky to properly specify and
44+
implement. Some of these may seem obvious, but the distinctions will be
45+
important later.
46+
47+
* Imported vs declared names - a name can be imported (e.g., `use foo;`) or
48+
declared (e.g., `fn foo ...`).
49+
* Single vs glob imports - a name can be explicitly (e.g., `use a::foo;`) or
50+
implicitly imported (e.g., `use a::*;` where `foo` is declared in `a`).
51+
* Public vs private names - the visibility of names is somewhat tied up with
52+
name resolution, for example in current Rust `use a::*;` only imports the
53+
public names from `a`.
54+
* Lexical scoping - a name can be inherited from a surrounding scope, rather
55+
than being declared in the current one, e.g., `let foo = ...; { foo(); }`.
56+
* There are different kinds of scopes - at the item level, names are not
57+
inherited from outer modules into inner modules. Items may also be declared
58+
inside functions and blocks within functions, with different rules from modules.
59+
At the expression level, blocks (`{...}`) give explicit scope, however, from
60+
the point of view of macro hygiene and region inference, each `let` statement
61+
starts a new implicit scope.
62+
* Explicitly declared vs macro generated names - a name can be declared
63+
explicitly in the source text, or could be declared as the result of expanding
64+
a macro.
65+
* Rust has multiple namespaces - types, values, and macros exist in separate
66+
namespaces (some items produce names in multiple namespaces). Imports
67+
refer (implictly) to one or more names in different namespaces.
68+
69+
Note that all top-level (i.e., not parameters, etc.) path segments in a path
70+
other than the last must be in the type namespace, e.g., in `a::b::c`, `a` and
71+
`b` are assumed to be in the type namespace, and `c` may be in any namespace.
72+
* Rust has an implicit prelude - the prelude defines a set of names which are
73+
always (unless explicitly opted-out) nameable. The prelude includes macros.
74+
Names in the prelude can be shadowed by any other names.
75+
76+
3977
# Detailed design
4078
[design]: #detailed-design
4179

80+
## Guiding principles
81+
82+
We would like the following principles to hold. There may be edge cases where
83+
they do not, but we would like these to be as small as possible (and prefer they
84+
don't exist at all).
85+
86+
#### Avoid 'time-travel' ambiguities, or different results of resolution if names
87+
are resolved in different orders.
88+
89+
Due to macro expansion, it is possible for a name to be resolved and then to
90+
become ambiguous, or (with rules formulated in a certain way) for a name to be
91+
resolved, then to be amiguous, then to be resolvable again (possibly to
92+
different bindings).
93+
94+
Furthermore, there is some flexibility in the order in which macros can be
95+
expanded. How a name resolves should be consistent under any ordering.
96+
97+
The strongest form of this principle, I believe, is that at any stage of
98+
macro expansion, and under any ordering of expansions, if a name resolves to a
99+
binding then it should always (i.e., at any other stage of any other expansion
100+
series) resolve to that binding, and if resolving a name produces an error
101+
(n.b., distinct from not being able to resolve), it should always produce an
102+
error.
103+
104+
105+
#### Avoid errors due to the resolver being stuck.
106+
107+
Errors with concrete causes and explanations are easier for the user to
108+
understand and to correct. If an error is caused by name resolution getting
109+
stuck, rather than by a concrete problem, this is hard to explain or correct.
110+
111+
For example, if we support a rule that means that a certain glob can't be
112+
expanded before a macro is, but the macro can only be named via that glob
113+
import, then there is an obvious resolution that can't be reached due to our
114+
ordering constraints.
115+
116+
117+
#### The order of declarations of items should be irrelevant.
118+
119+
I.e., names should be able to be used before they are declared. Note that this
120+
clearly does not hold for declarations of variables in statements inside
121+
function bodies.
122+
123+
124+
#### Macros should be manually expandable.
125+
126+
Compiling a program should have the same result before and after expanding a
127+
macro 'by hand', so long as hygiene is accounted for.
128+
129+
130+
#### Glob imports should be manually expandable.
131+
132+
A programmer should be able to replace a glob import with a list import that
133+
imports any names imported by the glob and used in the current scope, without
134+
changing name resolution behaviour.
135+
136+
137+
#### Visibility should not affect name resolution.
138+
139+
Clearly, visibility affects whether a name can be used or not. However, it
140+
should not affect the mechanics of name resolution. I.e., changing a name from
141+
public to private (or vice versa), should not cause more or fewer name
142+
resolution errors (it may of course cause more or fewer accessibility errors).
143+
144+
42145
## Changes to name resolution rules
43146

44147
### Multiple unused imports
@@ -142,9 +245,12 @@ Note that in combination with the above rule, this means non-public imports are
142245
imported by globs where they are private but accessible.
143246

144247

145-
### Globs and explicit names
248+
### Explicit names may shadow implicit names
146249

147-
An explicit name may shadow a glob imported name without causing a name
250+
Here, an implicit name means a name imported via a glob or inherited from an
251+
outer scope (as opposed to being declared or imported directly in an inner scope).
252+
253+
An explicit name may shadow an implicit name without causing a name
148254
resolution error. E.g.,
149255

150256
```
@@ -168,6 +274,19 @@ mod boz {
168274
}
169275
```
170276

277+
or
278+
279+
```
280+
fn main() {
281+
struct Foo; // 1.
282+
{
283+
struct Foo; // 2.
284+
285+
let x = Foo; // Ok and refers to declaration 2.
286+
}
287+
}
288+
```
289+
171290
Note that shadowing is namespace specific. I believe this is consistent with our
172291
general approach to name spaces. E.g.,
173292

@@ -218,7 +337,61 @@ the name will continue to be valid, or there will be an error. Without this
218337
caveat, a name could be valid, and then after further expansion, become shadowed
219338
by a higher priority name.
220339

221-
This change is discussed in [issue 31337](https://github.com/rust-lang/rust/issues/31337).
340+
An error is reported if there is an ambiguity between names due to the lack of
341+
shadowing, e.g., (this example assumes modularised macros),
342+
343+
```
344+
macro_rules! foo {
345+
() => {
346+
macro! bar { ... }
347+
}
348+
}
349+
350+
mod a {
351+
macro! bar { ... }
352+
}
353+
354+
mod b {
355+
use a::*;
356+
357+
foo!(); // Expands to `macro! bar { ... }`.
358+
359+
bar!(); // ERROR: bar is ambiguous.
360+
}
361+
```
362+
363+
Note on the caveat: there will only be an error emitted if an ambiguous name is
364+
used directly or indirectly in a macro use. I.e., is the name of a macro that is
365+
used, or is the name of a module that is used to name a macro either in a macro
366+
use or in an import.
367+
368+
Alternatives: we could emit an error even if the ambiguous name is not used, or
369+
as a compromise between these two, we could emit an error if the name is in the
370+
type or macro namespace (a name in the value namespace can never cause problems).
371+
372+
This change is discussed in [issue 31337](https://github.com/rust-lang/rust/issues/31337)
373+
and on this RFC PR's comment thread.
374+
375+
376+
### Re-exports, namespaces, and visibility.
377+
378+
(This is something of a clarification point, rather than explicitly new behaviour.
379+
See also discussion on [issue 31783](https://github.com/rust-lang/rust/issues/31783)).
380+
381+
An import (`use`) or re-export (`pub use`) imports a name in all available
382+
namespaces. E.g., `use a::foo;` will import `foo` in the type and value
383+
namespaces if it is declared in those namespaces in `a`.
384+
385+
For a name to be re-exported, it must be public, e.g, `pub use a::foo;` requires
386+
that `foo` is declared publicly in `a`. This is complicated by namespaces. The
387+
following behaviour should be followed for a re-export of `foo`:
388+
389+
* `foo` is private in all namespaces in which it is declared - emit an error.
390+
* `foo` is public in all namespaces in which it is declared - `foo` is
391+
re-exported in all namespaces.
392+
* `foo` is mixed public/private - `foo` is re-exported in the namespaces in which
393+
it is declared publicly and imported but not re-exported in namespaces in which
394+
it is declared privately.
222395

223396

224397
## Changes to the implementation
@@ -243,11 +416,11 @@ the supplying module, we can add it for the importing module.
243416

244417
We then loop over the work list and try to lookup names. If a name has exactly
245418
one best binding then we use it (and record the binding on a list of resolved
246-
names). If there are zero, or more than one possible binding, then we put it
247-
back on the work list. When we reach a fixed point, i.e., the work list no
248-
longer changes, then we are done. If the work list is empty, then
249-
expansion/import resolution succeeded, otherwise there are names not found, or
250-
ambiguous names, and we failed.
419+
names). If there are zero then we put it back on the work list. If there is more
420+
than one binding, then we record an ambiguity error. When we reach a fixed
421+
point, i.e., the work list no longer changes, then we are done. If the work list
422+
is empty, then expansion/import resolution succeeded, otherwise there are names
423+
not found, or ambiguous names, and we failed.
251424

252425
As we are looking up names, we record the resolutions in the binding table. If
253426
the name we are looking up is for a glob import, we add bindings for every
@@ -270,8 +443,8 @@ In pseudo-code:
270443
// pass.
271444
fn parse_expand_and_resolve() {
272445
loop until fixed point {
446+
process_names()
273447
loop until fixed point {
274-
process_names()
275448
process_work_list()
276449
}
277450
expand_macros()
@@ -337,6 +510,24 @@ naming, also the macro namespace), and that we must record whether a name is due
337510
to macro expansion or not to abide by the caveat to the 'explicit names shadow
338511
glob names' rule.
339512

513+
If Rust had a single namespace (or had some other properties), we would not have
514+
to distinguish between failed and unresolved imports. However, it does and we
515+
must. This is not clear from the pseudo-code because it elides namespaces, but
516+
consider the following small example:
517+
518+
```
519+
use a::foo; // foo exists in the value namespace of a.
520+
use b::*; // foo exists in the type namespace of b.
521+
```
522+
523+
Can we resolve a use fo `foo` in type position to the import from `b`? That
524+
depends on whether `foo` exists in the type namespace in `a`. If we can prove
525+
that it does not (i.e., resolution fails) then we can use the glob import. If we
526+
cannot (i.e., the name is unresolved but we can't prove it will not resolve
527+
later), then it is not safe to use the glob import because it may be shadowed by
528+
the explicit import. (Note, since `foo` exists in at least the value namespace
529+
in `a`, there will be no error due to a bad import).
530+
340531
In order to keep macro expansion comprehensible to programmers, we must enforce
341532
that all macro uses resolve to the same binding at the end of resolution as they
342533
do when they were resolved.
@@ -358,6 +549,10 @@ If import resolution succeeds, then we check our record of name resolutions. We
358549
re-resolve and check we get the same result. We can also check for un-used
359550
macros at this point.
360551

552+
Note that the rules in the previous section have been carefully formulated to
553+
ensure that this check is sufficient to prevent temporal ambiguities. There are
554+
many slight variations for which this check would not be enough.
555+
361556
### Privacy
362557

363558
In order to resolve imports (and in the future for macro privacy), we must be

0 commit comments

Comments
 (0)