Skip to content

Commit cfaf525

Browse files
authored
Merge pull request #1656 from GoldsteinE/mixed-site-hygiene
Document mixed-site hygiene
2 parents 458882b + 11ef502 commit cfaf525

File tree

1 file changed

+42
-5
lines changed

1 file changed

+42
-5
lines changed

src/macros-by-example.md

+42-5
Original file line numberDiff line numberDiff line change
@@ -416,11 +416,46 @@ by other crates, either by path or by `#[macro_use]` as described above.
416416
r[macro.decl.hygiene]
417417

418418
r[macro.decl.hygiene.intro]
419-
By default, all identifiers referred to in a macro are expanded as-is, and are
420-
looked up at the macro's invocation site. This can lead to issues if a macro
421-
refers to an item or macro which isn't in scope at the invocation site. To
422-
alleviate this, the `$crate` metavariable can be used at the start of a path to
423-
force lookup to occur inside the crate defining the macro.
419+
Macros by example have _mixed-site hygiene_. This means that [loop labels], [block labels], and local variables are looked up at the macro definition site while other symbols are looked up at the macro invocation site. For example:
420+
421+
```rust
422+
let x = 1;
423+
fn func() {
424+
unreachable!("this is never called")
425+
}
426+
427+
macro_rules! check {
428+
() => {
429+
assert_eq!(x, 1); // Uses `x` from the definition site.
430+
func(); // Uses `func` from the invocation site.
431+
};
432+
}
433+
434+
{
435+
let x = 2;
436+
fn func() { /* does not panic */ }
437+
check!();
438+
}
439+
```
440+
441+
Labels and local variables defined in macro expansion are not shared between invocations, so this code doesn’t compile:
442+
443+
```rust,compile_fail,E0425
444+
macro_rules! m {
445+
(define) => {
446+
let x = 1;
447+
};
448+
(refer) => {
449+
dbg!(x);
450+
};
451+
}
452+
453+
m!(define);
454+
m!(refer);
455+
```
456+
457+
r[macro.decl.hygiene.crate]
458+
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.
424459

425460
<!-- ignore: requires external crates -->
426461
```rust,ignore
@@ -565,6 +600,7 @@ expansions, taking separators into account. This means:
565600

566601
For more detail, see the [formal specification].
567602

603+
[block labels]: expressions/loop-expr.md#labelled-block-expressions
568604
[const block]: expressions/block-expr.md#const-blocks
569605
[Hygiene]: #hygiene
570606
[IDENTIFIER]: identifiers.md
@@ -580,6 +616,7 @@ For more detail, see the [formal specification].
580616
[_Expression_]: expressions.md
581617
[_Item_]: items.md
582618
[_LiteralExpression_]: expressions/literal-expr.md
619+
[loop labels]: expressions/loop-expr.md#loop-labels
583620
[_MetaListIdents_]: attributes.md#meta-item-attribute-syntax
584621
[_Pattern_]: patterns.md
585622
[_PatternNoTopAlt_]: patterns.md

0 commit comments

Comments
 (0)