From ed9a5175f685fb6471e88e531bed55c588811d40 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 10 Jun 2025 16:43:05 -0700 Subject: [PATCH 1/5] Unwrap macro_use --- src/macros-by-example.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 33844e18c8..d1eb314d52 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -330,9 +330,7 @@ r[macro.decl.scope.macro_use] ### The `macro_use` attribute r[macro.decl.scope.macro_use.mod-decl] -The *`macro_use` attribute* has two purposes. First, it can be used to make a -module's macro scope not end when the module is closed, by applying it to a -module: +The *`macro_use` attribute* has two purposes. First, it can be used to make a module's macro scope not end when the module is closed, by applying it to a module: ```rust #[macro_use] @@ -346,14 +344,7 @@ m!(); ``` r[macro.decl.scope.macro_use.prelude] -Second, it can be used to import macros from another crate, by attaching it to -an `extern crate` declaration appearing in the crate's root module. Macros -imported this way are imported into the [`macro_use` prelude], not textually, -which means that they can be shadowed by any other name. While macros imported -by `#[macro_use]` can be used before the import statement, in case of a -conflict, the last macro imported wins. Optionally, a list of macros to import -can be specified using the [MetaListIdents] syntax; this is not supported -when `#[macro_use]` is applied to a module. +Second, it can be used to import macros from another crate, by attaching it to an `extern crate` declaration appearing in the crate's root module. Macros imported this way are imported into the [`macro_use` prelude], not textually, which means that they can be shadowed by any other name. While macros imported by `#[macro_use]` can be used before the import statement, in case of a conflict, the last macro imported wins. Optionally, a list of macros to import can be specified using the [MetaListIdents] syntax; this is not supported when `#[macro_use]` is applied to a module. ```rust,ignore @@ -365,8 +356,7 @@ lazy_static!{} ``` r[macro.decl.scope.macro_use.export] -Macros to be imported with `macro_use` must be exported with -[`macro_export`][macro.decl.scope.macro_export]. +Macros to be imported with `macro_use` must be exported with [`macro_export`][macro.decl.scope.macro_export]. r[macro.decl.scope.macro_export] From c5a577fb078de80518d8d9de6baaecf2ec557127 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 10 Jun 2025 17:05:23 -0700 Subject: [PATCH 2/5] Rework macro_use to use the attribute template --- src/macros-by-example.md | 66 ++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 19 deletions(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index d1eb314d52..9dc984c036 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -329,31 +329,59 @@ fn foo() { r[macro.decl.scope.macro_use] ### The `macro_use` attribute -r[macro.decl.scope.macro_use.mod-decl] -The *`macro_use` attribute* has two purposes. First, it can be used to make a module's macro scope not end when the module is closed, by applying it to a module: +r[macro.decl.scope.macro_use.intro] +The *`macro_use` [attribute][attributes]* has two purposes. It may be used on modules to extend the scope of macros defined within them, and it may be used on [`extern crate`][items.extern-crate] to import macros from another crate. -```rust -#[macro_use] -mod inner { - macro_rules! m { - () => {}; - } -} +r[macro.decl.scope.macro_use.syntax] +When used on a module, the `macro_use` attribute uses the [MetaWord] syntax and thus does not take any inputs. -m!(); -``` +When used on an `extern crate`, it uses either the [MetaWord] or [MetaListIdents] syntax. + +r[macro.decl.scope.macro_use.allowed-positions] +The `macro_use` attribute may be applied to modules or `extern crate`. + +> [!NOTE] +> `rustc` currently warns in other positions, but this may be rejected in the future. + +r[macro.decl.scope.macro_use.duplicates] +Duplicate instances of `macro_use` that are in the [MetaWord] syntax have no effect if there is already a `macro_use` with the [MetaWord] syntax. + +Multiple instances of `macro_use` that are in the [MetaListIdents] syntax may be specified. The union of all specified macros to import will be imported. + +> [!NOTE] +> `rustc` warns about duplicate [MetaWord] `macro_use` attributes. + +r[macro.decl.scope.macro_use.mod-decl] +When `macro_use` is used on a module, it causes the module's macro scope to not end when the module is closed. + +> [!EXAMPLE] +> ```rust +> #[macro_use] +> mod inner { +> macro_rules! m { +> () => {}; +> } +> } +> +> m!(); +> ``` r[macro.decl.scope.macro_use.prelude] -Second, it can be used to import macros from another crate, by attaching it to an `extern crate` declaration appearing in the crate's root module. Macros imported this way are imported into the [`macro_use` prelude], not textually, which means that they can be shadowed by any other name. While macros imported by `#[macro_use]` can be used before the import statement, in case of a conflict, the last macro imported wins. Optionally, a list of macros to import can be specified using the [MetaListIdents] syntax; this is not supported when `#[macro_use]` is applied to a module. +When `macro_use` is used on an `extern crate` declaration in the crate root, it imports exported macros from that crate. - -```rust,ignore -#[macro_use(lazy_static)] // Or #[macro_use] to import all macros. -extern crate lazy_static; +Macros imported this way are imported into the [`macro_use` prelude], not textually, which means that they can be shadowed by any other name. While macros imported by `macro_use` can be used before the import statement, in case of a conflict, the last macro imported wins. -lazy_static!{} -// self::lazy_static!{} // Error: lazy_static is not defined in `self` -``` +When using the [MetaWord] syntax, all exported macros are imported. When using the [MetaListIdents] syntax, only the specified macros are imported. + +> [!EXAMPLE] +> +> ```rust,ignore +> #[macro_use(lazy_static)] // Or #[macro_use] to import all macros. +> extern crate lazy_static; +> +> lazy_static!{} +> // self::lazy_static!{} // Error: lazy_static is not defined in `self` +> ``` r[macro.decl.scope.macro_use.export] Macros to be imported with `macro_use` must be exported with [`macro_export`][macro.decl.scope.macro_export]. From 21d94fe795a3b6a675e37d9c9a13678ce9468fb2 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 30 Jun 2025 15:03:53 -0700 Subject: [PATCH 3/5] Add macro.decl.scope.macro_use.extern-crate-self Closes https://github.com/rust-lang/reference/issues/586 --- src/macros-by-example.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 9dc984c036..b31ed5d0ce 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -343,6 +343,9 @@ The `macro_use` attribute may be applied to modules or `extern crate`. > [!NOTE] > `rustc` currently warns in other positions, but this may be rejected in the future. +r[macro.decl.scope.macro_use.extern-crate-self] +The `macro_use` attribute may not be used on [`extern crate self`]. + r[macro.decl.scope.macro_use.duplicates] Duplicate instances of `macro_use` that are in the [MetaWord] syntax have no effect if there is already a `macro_use` with the [MetaWord] syntax. @@ -687,6 +690,7 @@ expansions, taking separators into account. This means: For more detail, see the [formal specification]. +[`extern crate self`]: items.extern-crate.self [`macro_use` prelude]: names/preludes.md#macro_use-prelude [block labels]: expressions/loop-expr.md#labelled-block-expressions [delimiters]: tokens.md#delimiters From dca911798e5413655b1fca9d74e0416db0e874ff Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Mon, 22 Sep 2025 12:41:37 -0700 Subject: [PATCH 4/5] Minor update of macro_use More closely align with the template, and some minor word tweaks. --- src/macros-by-example.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index b31ed5d0ce..3b66db1ab3 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -326,6 +326,7 @@ fn foo() { // m!(); // Error: m is not in scope. ``` + r[macro.decl.scope.macro_use] ### The `macro_use` attribute @@ -333,21 +334,21 @@ r[macro.decl.scope.macro_use.intro] The *`macro_use` [attribute][attributes]* has two purposes. It may be used on modules to extend the scope of macros defined within them, and it may be used on [`extern crate`][items.extern-crate] to import macros from another crate. r[macro.decl.scope.macro_use.syntax] -When used on a module, the `macro_use` attribute uses the [MetaWord] syntax and thus does not take any inputs. +When used on a module, the `macro_use` attribute uses the [MetaWord] syntax. -When used on an `extern crate`, it uses either the [MetaWord] or [MetaListIdents] syntax. +When used on an `extern crate`, it uses either the [MetaWord] or [MetaListIdents] syntax (described in [macro.decl.scope.macro_use.prelude]). r[macro.decl.scope.macro_use.allowed-positions] The `macro_use` attribute may be applied to modules or `extern crate`. > [!NOTE] -> `rustc` currently warns in other positions, but this may be rejected in the future. +> `rustc` ignores use in other positions but lints against it. This may become an error in the future. r[macro.decl.scope.macro_use.extern-crate-self] The `macro_use` attribute may not be used on [`extern crate self`]. r[macro.decl.scope.macro_use.duplicates] -Duplicate instances of `macro_use` that are in the [MetaWord] syntax have no effect if there is already a `macro_use` with the [MetaWord] syntax. +The `macro_use` attribute may be used any number of times on a form. Multiple instances of `macro_use` that are in the [MetaListIdents] syntax may be specified. The union of all specified macros to import will be imported. @@ -370,7 +371,7 @@ When `macro_use` is used on a module, it causes the module's macro scope to not > ``` r[macro.decl.scope.macro_use.prelude] -When `macro_use` is used on an `extern crate` declaration in the crate root, it imports exported macros from that crate. +Specifying `macro_use` on an `extern crate` declaration in the crate root imports exported macros from that crate. Macros imported this way are imported into the [`macro_use` prelude], not textually, which means that they can be shadowed by any other name. While macros imported by `macro_use` can be used before the import statement, in case of a conflict, the last macro imported wins. From 4647e8702355489d9246434eedc8c985cef61ebb Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Mon, 20 Oct 2025 20:35:37 +0000 Subject: [PATCH 5/5] Revise `macro_use` text --- src/macros-by-example.md | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/macros-by-example.md b/src/macros-by-example.md index 3b66db1ab3..4edad491c3 100644 --- a/src/macros-by-example.md +++ b/src/macros-by-example.md @@ -331,12 +331,28 @@ r[macro.decl.scope.macro_use] ### The `macro_use` attribute r[macro.decl.scope.macro_use.intro] -The *`macro_use` [attribute][attributes]* has two purposes. It may be used on modules to extend the scope of macros defined within them, and it may be used on [`extern crate`][items.extern-crate] to import macros from another crate. +The *`macro_use` [attribute][attributes]* has two purposes: it may be used on modules to extend the scope of macros defined within them, and it may be used on [`extern crate`][items.extern-crate] to import macros from another crate into the [`macro_use` prelude]. + +> [!EXAMPLE] +> ```rust +> #[macro_use] +> mod inner { +> macro_rules! m { +> () => {}; +> } +> } +> m!(); +> ``` +> +> ```rust,ignore +> #[macro_use] +> extern crate log; +> ``` r[macro.decl.scope.macro_use.syntax] -When used on a module, the `macro_use` attribute uses the [MetaWord] syntax. +When used on modules, the `macro_use` attribute uses the [MetaWord] syntax. -When used on an `extern crate`, it uses either the [MetaWord] or [MetaListIdents] syntax (described in [macro.decl.scope.macro_use.prelude]). +When used on `extern crate`, it uses the [MetaWord] and [MetaListIdents] syntaxes. For more on how these syntaxes may be used, see [macro.decl.scope.macro_use.prelude]. r[macro.decl.scope.macro_use.allowed-positions] The `macro_use` attribute may be applied to modules or `extern crate`. @@ -350,13 +366,15 @@ The `macro_use` attribute may not be used on [`extern crate self`]. r[macro.decl.scope.macro_use.duplicates] The `macro_use` attribute may be used any number of times on a form. -Multiple instances of `macro_use` that are in the [MetaListIdents] syntax may be specified. The union of all specified macros to import will be imported. +Multiple instances of `macro_use` in the [MetaListIdents] syntax may be specified. The union of all specified macros will be imported. > [!NOTE] -> `rustc` warns about duplicate [MetaWord] `macro_use` attributes. +> On modules, `rustc` lints against any [MetaWord] `macro_use` attributes following the first. +> +> On `extern crate`, `rustc` lints against any `macro_use` attributes that have no effect due to not importing any macros not already imported by another `macro_use` attribute. If two or more [MetaListIdents] `macro_use` attributes import the same macro, the first is linted against. If any [MetaWord] `macro_use` attributes are present, all [MetaListIdents] `macro_use` attributes are linted against. If two or more [MetaWord] `macro_use` attributes are present, the ones following the first are linted against. r[macro.decl.scope.macro_use.mod-decl] -When `macro_use` is used on a module, it causes the module's macro scope to not end when the module is closed. +When `macro_use` is used on a module, the module's macro scope extends beyond the module's lexical scope. > [!EXAMPLE] > ```rust @@ -366,8 +384,7 @@ When `macro_use` is used on a module, it causes the module's macro scope to not > () => {}; > } > } -> -> m!(); +> m!(); // OK > ``` r[macro.decl.scope.macro_use.prelude] @@ -380,11 +397,11 @@ When using the [MetaWord] syntax, all exported macros are imported. When using t > [!EXAMPLE] > > ```rust,ignore -> #[macro_use(lazy_static)] // Or #[macro_use] to import all macros. +> #[macro_use(lazy_static)] // Or `#[macro_use]` to import all macros. > extern crate lazy_static; > > lazy_static!{} -> // self::lazy_static!{} // Error: lazy_static is not defined in `self` +> // self::lazy_static!{} // ERROR: lazy_static is not defined in `self`. > ``` r[macro.decl.scope.macro_use.export]