Skip to content
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/glossary.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Glossary

r[glossary.ast]
### Abstract syntax tree

An ‘abstract syntax tree’, or ‘AST’, is an intermediate representation of
Expand Down
67 changes: 10 additions & 57 deletions src/items/use-declarations.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ They may create bindings for:
* [Built-in types]
* [Attributes]
* [Derive macros]
* [`macro_rules`]

r[items.use.path.disallowed]
They cannot import [associated items], [generic parameters], [local variables], paths with [`Self`], or [tool attributes]. More restrictions are described below.
Expand Down Expand Up @@ -302,6 +303,10 @@ mod clashing {
}
```

> [!NOTE]
>
> For areas where shadowing is not allowed, see [name resolution ambiguities].

r[items.use.glob.last-segment-only]
`*` cannot be used as the first or intermediate segments.

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

r[items.use.ambiguities]
## Ambiguities

> [!NOTE]
> This section is incomplete.

r[items.use.ambiguities.intro]
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.

r[items.use.ambiguities.glob]
Glob imports are allowed to import conflicting names in the same namespace as long as the name is not used.
For example:

```rust
mod foo {
pub struct Qux;
}

mod bar {
pub struct Qux;
}

use foo::*;
use bar::*; //~ OK, no name conflict.

fn main() {
// This would be an error, due to the ambiguity.
//let x = Qux;
}
```

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:

```rust
mod foo {
pub struct Qux;
}

mod bar {
pub use super::foo::Qux;
}

// These both import the same `Qux`. The visibility of `Qux`
// is `pub` because that is the maximum visibility between
// these two `use` declarations.
pub use bar::*;
use foo::*;

fn main() {
let _: Qux = Qux;
}
```

[`extern crate`]: extern-crates.md
[`macro_rules`]: ../macros-by-example.md
[`self`]: ../paths.md#self
[associated items]: associated-items.md
[Attributes]: ../attributes.md
[Built-in types]: ../types.md
[Derive macros]: macro.proc.derive
[Enum variants]: enumerations.md
[`extern crate`]: extern-crates.md
[`macro_rules`]: ../macros-by-example.md
[`self`]: ../paths.md#self
[associated items]: associated-items.md
[extern prelude]: ../names/preludes.md#extern-prelude
[generic parameters]: generics.md
[items]: ../items.md
[local variables]: ../variables.md
[name resolution ambiguities]: names.resolution.expansion.imports.ambiguity
[namespace]: ../names/namespaces.md
[namespaces]: ../names/namespaces.md
[paths]: ../paths.md
Expand Down
82 changes: 78 additions & 4 deletions src/macros-by-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,77 @@ fn foo() {
// m!(); // Error: m is not in scope.
```

r[macro.decl.scope.textual.shadow.path-based]
Textual scope name bindings for macros shadow path-based scope bindings to macros.

```rust
#[macro_export]
macro_rules! m2 {
() => {
println!("m2");
};
}

m!(); // prints "m2\n"

macro_rules! m {
() => {
println!("m");
};
}

use crate::m2 as m;

m!(); // prints "m\n"
```

> [!NOTE]
>
> For areas where shadowing is not allowed, see [name resolution ambiguities].

r[macro.decl.scope.path-based]
### Path-based scope

r[macro.decl.scope.path-based.intro]
By default, a macro has no path-based scope. Macros can gain path-based scope in two ways:

* [Use declaration re-export]
* [`macro_export`]

r[macro.decl.scope.path.reexport]
Macros can be re-exported to give them path-based scope from a module other than the crate root.

```rust
mac::m!(); // OK: Path-based lookup finds m in the mac module.

mod mac {
macro_rules! m {
() => {};
}
pub(crate) use m;
}
```

r[macro.decl.scope.path-based.visibility]
Macros have an implicit visibility of `pub(crate)`. `#[macro_export]` changes the implicit visibility to `pub`.

```rust,compile_fail,E0364
macro_rules! private_m {
() => {};
}

#[macro_export]
macro_rules! pub_m {
() => {};
}

pub(crate) use private_m as private_macro; // OK
pub use pub_m as pub_macro; // OK

pub use private_m; // ERROR: `private_m` is only public within
// the crate and cannot be re-exported outside
```

<!-- template:attributes -->
r[macro.decl.scope.macro_use]
### The `macro_use` attribute
Expand Down Expand Up @@ -713,14 +784,17 @@ expansions, taking separators into account. This means:

For more detail, see the [formal specification].

[Hygiene]: #hygiene
[Metavariables]: #metavariables
[Repetitions]: #repetitions
[Use declaration re-export]: items/use-declarations.md#use-visibility
[`macro_export`]: #the-macro_export-attribute
[`$crate`]: macro.decl.hygiene.crate
[`extern crate self`]: items.extern-crate.self
[`macro_use` prelude]: names/preludes.md#macro_use-prelude
[block labels]: expr.loop.block-labels
[delimiters]: tokens.md#delimiters
[formal specification]: macro-ambiguity.md
[Hygiene]: #hygiene
[loop labels]: expressions/loop-expr.md#loop-labels
[Metavariables]: #metavariables
[Repetitions]: #repetitions
[name resolution ambiguities]: names/name-resolution.md#r-names.resolution.expansion.imports.ambiguity
[token]: tokens.md
[`$crate`]: macro.decl.hygiene.crate
14 changes: 12 additions & 2 deletions src/macros.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,25 @@ macro_rules! example {
example!();
```

r[macro.invocation.name-resolution]

Macros invocations can be resolved via two kinds of scopes:

* Textual Scope
* [Textual scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.textual)
* Path-based scope
* [Path-based scope `macro_rules`](macros-by-example.md#r-macro.decl.scope.path-based)
* [Procedural macros]

[External blocks]: items/external-blocks.md
[Macros by Example]: macros-by-example.md
[Procedural Macros]: procedural-macros.md
[`macro_rules`]: macros-by-example.md
[associated items]: items/associated-items.md
[delimiters]: tokens.md#delimiters
[expressions]: expressions.md
[items]: items.md
[`macro_rules`]: macros-by-example.md
[patterns]: patterns.md
[statements]: statements.md
[types]: types.md
[visibility qualifiers]: visibility-and-privacy.md
[External blocks]: items/external-blocks.md
Loading
Loading