Skip to content

Commit 4e09b47

Browse files
yaahcpetrochenkovehusstshepang
committed
Add section on expansion-time (early) name resolution
Co-authored-by: Vadim Petrochenkov <[email protected]> Co-authored-by: Eric Huss <[email protected]> Co-authored-by: Tshepang Mbambo <[email protected]>
1 parent fbdc22a commit 4e09b47

File tree

6 files changed

+497
-90
lines changed

6 files changed

+497
-90
lines changed

src/items/use-declarations.md

Lines changed: 10 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,10 @@ mod clashing {
302303
}
303304
```
304305

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

@@ -389,71 +394,19 @@ r[items.use.restrictions.variant]
389394
use TypeAlias::MyVariant; //~ ERROR
390395
```
391396

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
449397
[Attributes]: ../attributes.md
450398
[Built-in types]: ../types.md
451399
[Derive macros]: macro.proc.derive
452400
[Enum variants]: enumerations.md
401+
[`extern crate`]: extern-crates.md
402+
[`macro_rules`]: ../macros-by-example.md
403+
[`self`]: ../paths.md#self
404+
[associated items]: associated-items.md
453405
[extern prelude]: ../names/preludes.md#extern-prelude
454406
[generic parameters]: generics.md
455407
[items]: ../items.md
456408
[local variables]: ../variables.md
409+
[name resolution ambiguities]: names.resolution.expansion.imports.ambiguity
457410
[namespace]: ../names/namespaces.md
458411
[namespaces]: ../names/namespaces.md
459412
[paths]: ../paths.md

src/macros-by-example.md

Lines changed: 78 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,77 @@ 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_export]
334+
macro_rules! m2 {
335+
() => {
336+
println!("m2");
337+
};
338+
}
339+
340+
m!(); // prints "m2\n"
341+
342+
macro_rules! m {
343+
() => {
344+
println!("m");
345+
};
346+
}
347+
348+
use crate::m2 as m;
349+
350+
m!(); // prints "m\n"
351+
```
352+
353+
> [!NOTE]
354+
>
355+
> For areas where shadowing is not allowed, see [name resolution ambiguities].
356+
357+
r[macro.decl.scope.path-based]
358+
### Path-based scope
359+
360+
r[macro.decl.scope.path-based.intro]
361+
By default, a macro has no path-based scope. Macros can gain path-based scope in two ways:
362+
363+
* [Use declaration re-export]
364+
* [`macro_export`]
365+
366+
r[macro.decl.scope.path.reexport]
367+
Macros can be re-exported to give them path-based scope from a module other than the crate root.
368+
369+
```rust
370+
mac::m!(); // OK: Path-based lookup finds m in the mac module.
371+
372+
mod mac {
373+
macro_rules! m {
374+
() => {};
375+
}
376+
pub(crate) use m;
377+
}
378+
```
379+
380+
r[macro.decl.scope.path-based.visibility]
381+
Macros have an implicit visibility of `pub(crate)`. `#[macro_export]` changes the implicit visibility to `pub`.
382+
383+
```rust,compile_fail,E0364
384+
macro_rules! private_m {
385+
() => {};
386+
}
387+
388+
#[macro_export]
389+
macro_rules! pub_m {
390+
() => {};
391+
}
392+
393+
pub(crate) use private_m as private_macro; // OK
394+
pub use pub_m as pub_macro; // OK
395+
396+
pub use private_m; // ERROR: `private_m` is only public within
397+
// the crate and cannot be re-exported outside
398+
```
399+
329400
<!-- template:attributes -->
330401
r[macro.decl.scope.macro_use]
331402
### The `macro_use` attribute
@@ -713,14 +784,17 @@ expansions, taking separators into account. This means:
713784

714785
For more detail, see the [formal specification].
715786

787+
[Hygiene]: #hygiene
788+
[Metavariables]: #metavariables
789+
[Repetitions]: #repetitions
790+
[Use declaration re-export]: items/use-declarations.md#use-visibility
791+
[`macro_export`]: #the-macro_export-attribute
792+
[`$crate`]: macro.decl.hygiene.crate
716793
[`extern crate self`]: items.extern-crate.self
717794
[`macro_use` prelude]: names/preludes.md#macro_use-prelude
718795
[block labels]: expr.loop.block-labels
719796
[delimiters]: tokens.md#delimiters
720797
[formal specification]: macro-ambiguity.md
721-
[Hygiene]: #hygiene
722798
[loop labels]: expressions/loop-expr.md#loop-labels
723-
[Metavariables]: #metavariables
724-
[Repetitions]: #repetitions
799+
[name resolution ambiguities]: names/name-resolution.md#r-names.resolution.expansion.imports.ambiguity
725800
[token]: tokens.md
726-
[`$crate`]: macro.decl.hygiene.crate

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)