Exporting a macro¶
Level: 301 · deep dive
One line: A macro_rules! macro exists only below its definition — textual scope, like a let — until pub(crate) use name; gives it a path inside the crate or #[macro_export] publishes it at the crate root for everyone.
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
What it has to cover¶
- Textual scope: a call above the definition is cannot find macro
twicein this scope, and 1.98.0 adds consider moving the definition oftwicebefore this call and points at the later definition. Textual scope also flows into child modules declared after the definition, even across files - Module order: a function in a
moddeclared beforemod helperscannot call a macro defined insidehelpersby name, and the help line on 1.98.0 suggests#[macro_use];helpers::double!(4)fails differently, withE0433 pub(crate) use double;written after the definition gives the macro path-based scope, socrate::helpers::double!(4)works from any module, including one earlier in the file- The implicit visibility: a macro is
pub(crate)until#[macro_export]makes itpub, sopub use private_m;is refused whilepub(crate) use private_m;is fine #[macro_export]places the macro at the crate root whichever module it is written in:crate::triple!inside the crate,your_crate::triple!from outside — and where does rustdoc list it?- The two
#[macro_use]s: on a module it stretches textual scope past the module's closing brace; onextern crateit is the pre-2018 way to import another crate's macros, which clippy'smacro_use_imports(pedantic) suggests replacing withuse #[macro_export(local_inner_macros)], which the Reference calls a migration aid discouraged in new code, against writing$crate::helper!yourself — see Hygiene
The trap it exists for¶
Moving a working macro into its own module file, getting cannot find macro at every call site, and fixing it with #[macro_export]. The errors go away, and the macro is now part of the crate's public API at the root, documented and semver-bound, when pub(crate) use name; was all the crate needed.
Where this sits¶
Modules and visibility and Bringing names in with use cover path-based scope for items; a macro follows those rules only after it has been given a path. One module per file is where the "moved it into a file" trap starts. This page is only how a macro's own name becomes reachable.
See also¶
- Modules and visibility —
pub(crate)and the module wall for ordinary items - Bringing names in with
use— the declaration that also re-exports a macro - One module per file — why moving code into a file changes declaration order
- Hygiene —
$crate, which an exported macro needs - Two versions of one crate in one binary — what depending on an exported macro commits a caller to
- Macros by example: scoping, exporting and importing ↗ — textual and path-based scope,
macro_useandmacro_export
If you are coming from another language¶
- C. A
#defineis visible from its line to the end of the translation unit, and it is shared by putting it in a header that others#include. Rust's textual scope ends where the enclosing module ends, and sharing is an attribute or ause, not a file copied into place. - C++. C++20 named modules do not export macros at all — importing a module brings in declarations only, and a header unit is needed to carry macros. Rust went the other way and gave macros paths.
Po polsku¶
Makro macro_rules! ma najpierw tylko zasięg tekstowy (textual scope): istnieje od miejsca definicji w dół, jak zmienna z let, więc wywołanie powyżej definicji albo z modułu zadeklarowanego wcześniej kończy się błędem cannot find macro. Ścieżkę dostaje dopiero przez pub(crate) use nazwa; (w obrębie crate'a) albo #[macro_export] (w korzeniu crate'a, publicznie dla wszystkich). Najczęstszy błąd to sięganie po #[macro_export] tylko po to, żeby uciszyć kompilator — makro staje się wtedy częścią publicznego API.
Szukaj po polsku: eksport makra · zasięg makr · rust macro_export vs pub use · rust cannot find macro in this scope · macro textual scope