Skip to content

Commit 4d81027

Browse files
authored
Merge pull request #2055 from yaahc/name-res
Add section on expansion-time (early) name resolution
2 parents ff6b74d + ce32028 commit 4d81027

File tree

7 files changed

+714
-66
lines changed

7 files changed

+714
-66
lines changed

src/glossary.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Glossary
22

3+
r[glossary.ast]
34
### Abstract syntax tree
45

56
An ‘abstract syntax tree’, or ‘AST’, is an intermediate representation of

src/items/use-declarations.md

Lines changed: 9 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ They may create bindings for:
116116
* [Built-in types]
117117
* [Attributes]
118118
* [Derive macros]
119+
* [`macro_rules`]
119120

120121
r[items.use.path.disallowed]
121122
They cannot import [associated items], [generic parameters], [local variables], paths with [`Self`], or [tool attributes]. More restrictions are described below.
@@ -302,6 +303,9 @@ mod clashing {
302303
}
303304
```
304305

306+
> [!NOTE]
307+
> For areas where shadowing is not allowed, see [name resolution ambiguities].
308+
305309
r[items.use.glob.last-segment-only]
306310
`*` cannot be used as the first or intermediate segments.
307311

@@ -389,71 +393,19 @@ r[items.use.restrictions.variant]
389393
use TypeAlias::MyVariant; //~ ERROR
390394
```
391395

392-
r[items.use.ambiguities]
393-
## Ambiguities
394-
395-
> [!NOTE]
396-
> This section is incomplete.
397-
398-
r[items.use.ambiguities.intro]
399-
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.
400-
401-
r[items.use.ambiguities.glob]
402-
Glob imports are allowed to import conflicting names in the same namespace as long as the name is not used.
403-
For example:
404-
405-
```rust
406-
mod foo {
407-
pub struct Qux;
408-
}
409-
410-
mod bar {
411-
pub struct Qux;
412-
}
413-
414-
use foo::*;
415-
use bar::*; //~ OK, no name conflict.
416-
417-
fn main() {
418-
// This would be an error, due to the ambiguity.
419-
//let x = Qux;
420-
}
421-
```
422-
423-
Multiple glob imports are allowed to import the same name, and that name is allowed to be used, if the imports are of the same item (following re-exports). The visibility of the name is the maximum visibility of the imports. For example:
424-
425-
```rust
426-
mod foo {
427-
pub struct Qux;
428-
}
429-
430-
mod bar {
431-
pub use super::foo::Qux;
432-
}
433-
434-
// These both import the same `Qux`. The visibility of `Qux`
435-
// is `pub` because that is the maximum visibility between
436-
// these two `use` declarations.
437-
pub use bar::*;
438-
use foo::*;
439-
440-
fn main() {
441-
let _: Qux = Qux;
442-
}
443-
```
444-
445-
[`extern crate`]: extern-crates.md
446-
[`macro_rules`]: ../macros-by-example.md
447-
[`self`]: ../paths.md#self
448-
[associated items]: associated-items.md
449396
[Attributes]: ../attributes.md
450397
[Built-in types]: ../types.md
451398
[Derive macros]: macro.proc.derive
452399
[Enum variants]: enumerations.md
400+
[`extern crate`]: extern-crates.md
401+
[`macro_rules`]: ../macros-by-example.md
402+
[`self`]: ../paths.md#self
403+
[associated items]: associated-items.md
453404
[extern prelude]: ../names/preludes.md#extern-prelude
454405
[generic parameters]: generics.md
455406
[items]: ../items.md
456407
[local variables]: ../variables.md
408+
[name resolution ambiguities]: names.resolution.expansion.imports.ambiguity
457409
[namespace]: ../names/namespaces.md
458410
[namespaces]: ../names/namespaces.md
459411
[paths]: ../paths.md

src/macros-by-example.md

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

329+
r[macro.decl.scope.textual.shadow.path-based]
330+
Textual scope name bindings for macros shadow path-based scope bindings to macros.
331+
332+
```rust
333+
macro_rules! m2 {
334+
() => {
335+
println!("m2");
336+
};
337+
}
338+
339+
// Resolves to path-based candidate from use declaration below.
340+
m!(); // prints "m2\n"
341+
342+
// Introduce second candidate for `m` with textual scope.
343+
//
344+
// This shadows path-based candidate from below for the rest of this
345+
// example.
346+
macro_rules! m {
347+
() => {
348+
println!("m");
349+
};
350+
}
351+
352+
// Introduce `m2` macro as path-based candidate.
353+
//
354+
// This item is in scope for this entire example, not just below the
355+
// use declaration.
356+
use m2 as m;
357+
358+
// Resolves to the textual macro candidate from above the use
359+
// declaration.
360+
m!(); // prints "m\n"
361+
```
362+
363+
> [!NOTE]
364+
> For areas where shadowing is not allowed, see [name resolution ambiguities].
365+
366+
r[macro.decl.scope.path-based]
367+
### Path-based scope
368+
369+
r[macro.decl.scope.path-based.intro]
370+
By default, a macro has no path-based scope. Macros can gain path-based scope in two ways:
371+
372+
- [Use declaration re-export]
373+
- [`macro_export`]
374+
375+
r[macro.decl.scope.path.reexport]
376+
Macros can be re-exported to give them path-based scope from a module other than the crate root.
377+
378+
```rust
379+
mac::m!(); // OK: Path-based lookup finds `m` in the mac module.
380+
381+
mod mac {
382+
// Introduce macro `m` with textual scope.
383+
macro_rules! m {
384+
() => {};
385+
}
386+
387+
// Reexport with path-based scope from within `m`'s textual scope.
388+
pub(crate) use m;
389+
}
390+
```
391+
392+
r[macro.decl.scope.path-based.visibility]
393+
Macros have an implicit visibility of `pub(crate)`. `#[macro_export]` changes the implicit visibility to `pub`.
394+
395+
```rust
396+
// Implicit visibility is `pub(crate)`.
397+
macro_rules! private_m {
398+
() => {};
399+
}
400+
401+
// Implicit visibility is `pub`.
402+
#[macro_export]
403+
macro_rules! pub_m {
404+
() => {};
405+
}
406+
407+
pub(crate) use private_m as private_macro; // OK.
408+
pub use pub_m as pub_macro; // OK.
409+
```
410+
411+
```rust,compile_fail,E0364
412+
# // Implicit visibility is `pub(crate)`.
413+
# macro_rules! private_m {
414+
# () => {};
415+
# }
416+
#
417+
# // Implicit visibility is `pub`.
418+
# #[macro_export]
419+
# macro_rules! pub_m {
420+
# () => {};
421+
# }
422+
#
423+
# pub(crate) use private_m as private_macro; // OK.
424+
# pub use pub_m as pub_macro; // OK.
425+
#
426+
pub use private_m; // ERROR: `private_m` is only public within
427+
// the crate and cannot be re-exported outside.
428+
```
429+
329430
<!-- template:attributes -->
330431
r[macro.decl.scope.macro_use]
331432
### The `macro_use` attribute
@@ -713,14 +814,16 @@ expansions, taking separators into account. This means:
713814

714815
For more detail, see the [formal specification].
715816

817+
[Metavariables]: #metavariables
818+
[Repetitions]: #repetitions
819+
[`macro_export`]: #the-macro_export-attribute
820+
[`$crate`]: macro.decl.hygiene.crate
716821
[`extern crate self`]: items.extern-crate.self
717822
[`macro_use` prelude]: names/preludes.md#macro_use-prelude
718823
[block labels]: expr.loop.block-labels
719824
[delimiters]: tokens.md#delimiters
720825
[formal specification]: macro-ambiguity.md
721-
[Hygiene]: #hygiene
722826
[loop labels]: expressions/loop-expr.md#loop-labels
723-
[Metavariables]: #metavariables
724-
[Repetitions]: #repetitions
827+
[name resolution ambiguities]: names/name-resolution.md#r-names.resolution.expansion.imports.ambiguity
725828
[token]: tokens.md
726-
[`$crate`]: macro.decl.hygiene.crate
829+
[use declaration re-export]: items/use-declarations.md#use-visibility

src/macros.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,15 +106,25 @@ macro_rules! example {
106106
example!();
107107
```
108108

109+
r[macro.invocation.name-resolution]
110+
111+
Macros invocations can be resolved via two kinds of scopes:
112+
113+
- Textual Scope
114+
- [Textual scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.textual)
115+
- Path-based scope
116+
- [Path-based scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.path-based)
117+
- [Procedural macros]
118+
119+
[External blocks]: items/external-blocks.md
109120
[Macros by Example]: macros-by-example.md
110121
[Procedural Macros]: procedural-macros.md
122+
[`macro_rules`]: macros-by-example.md
111123
[associated items]: items/associated-items.md
112124
[delimiters]: tokens.md#delimiters
113125
[expressions]: expressions.md
114126
[items]: items.md
115-
[`macro_rules`]: macros-by-example.md
116127
[patterns]: patterns.md
117128
[statements]: statements.md
118129
[types]: types.md
119130
[visibility qualifiers]: visibility-and-privacy.md
120-
[External blocks]: items/external-blocks.md

0 commit comments

Comments
 (0)