Skip to content

Commit

Permalink
Document mixed-site hygiene.
Browse files Browse the repository at this point in the history
  • Loading branch information
GoldsteinE authored and traviscross committed Oct 22, 2024
1 parent 458882b commit d062154
Showing 1 changed file with 44 additions and 5 deletions.
49 changes: 44 additions & 5 deletions src/macros-by-example.md
Original file line number Diff line number Diff line change
Expand Up @@ -416,11 +416,48 @@ by other crates, either by path or by `#[macro_use]` as described above.
r[macro.decl.hygiene]

r[macro.decl.hygiene.intro]
By default, all identifiers referred to in a macro are expanded as-is, and are
looked up at the macro's invocation site. This can lead to issues if a macro
refers to an item or macro which isn't in scope at the invocation site. To
alleviate this, the `$crate` metavariable can be used at the start of a path to
force lookup to occur inside the crate defining the macro.

Macros by example have _mixed-site hygiene_. It means that [loop labels], [block labels] and local variables are looked up at the macro definition site, and other symbols are looked up at the macro invocation site. For example:

```rust
let x = 1;
fn func() {
unreachable!("this is never called")
}

macro_rules! check {
() => {
assert_eq!(x, 1); // Uses `x` from the declaration site.
func(); // Uses `func` from the invocation site.
};
}

{
let x = 2;
fn func() { /* does not panic */ }
check!();
}
```

Labels and local variables defined in macro expansion are not shared between invocations, so this code doesn’t compile:

```rust,compile_fail
macro_rules! m {
(define) => {
let x = 1;
};
(refer) => {
dbg!(x);
};
}
m!(define);
m!(refer);
```

r[macro.decl.hygiene.crate]

A special case is the `$crate` metavariable. It refers to the crate defining the macro, and can be used at the start of the path to look up items or macros which are not in scope at the invocation site.

<!-- ignore: requires external crates -->
```rust,ignore
Expand Down Expand Up @@ -565,6 +602,7 @@ expansions, taking separators into account. This means:

For more detail, see the [formal specification].

[block labels]: expressions/loop-expr.md#labelled-block-expressions
[const block]: expressions/block-expr.md#const-blocks
[Hygiene]: #hygiene
[IDENTIFIER]: identifiers.md
Expand All @@ -580,6 +618,7 @@ For more detail, see the [formal specification].
[_Expression_]: expressions.md
[_Item_]: items.md
[_LiteralExpression_]: expressions/literal-expr.md
[loop labels]: expressions/loop-expr.md#loop-labels
[_MetaListIdents_]: attributes.md#meta-item-attribute-syntax
[_Pattern_]: patterns.md
[_PatternNoTopAlt_]: patterns.md
Expand Down

0 comments on commit d062154

Please sign in to comment.