Hygiene
Hygiene is an important concept for macros. It describes the ability for a macro to work in its own syntax context, not affecting nor being affected by its surroundings. In other words this means that a syntax extension should be invocable anywhere without interfering with its surrounding context.
In a perfect world all syntax extensions in Rust would be fully hygienic, unfortunately this isn't the case, so care should be taken to avoid writing syntax extensions that aren't fully hygienic. We will go into general hygiene concepts here which will be touched upon in the corresponding hygiene chapters for the different syntax extensions Rust has to offer.
Hygiene mainly affects identifiers and paths emitted by syntax extensions. In short, if an identifier created by a syntax extension cannot be accessed by the environment where the syntax extension has been invoked it is hygienic in regards to that identifier. Likewise, if an identifier used in a syntax extension cannot reference something defined outside of a syntax extension it is considered hygienic.
Note: The terms
create
anduse
refer to the position the identifier is in. That is theFoo
instruct Foo {}
or thefoo
inlet foo = …;
are created in the sense that they introduce something new under the name, but theFoo
infn foo(_: Foo) {}
or thefoo
infoo + 3
are usages in the sense that they are referring to something existing.
This is best shown by example.
Let's assume we have some syntax extension make_local
that expands to let local = 0;
, that is it creates the identifier local
.
Then given the following snippet:
make_local!();
assert_eq!(local, 0);
If the local
in assert_eq!(local, 0);
resolves to the local defined by the syntax extension, the syntax extension is not hygienic (at least in regards to local names/bindings).
Now let's assume we have some syntax extension use_local
that expands to local = 42;
, that is it makes use of the identifier local
.
Then given the following snippet:
let mut local = 0;
use_local!();
If the local
inside of the syntax extension for the given invocation resolves to the local defined before its invocation, the syntax extension is not hygienic either.
This is a rather short introduction to the general concept of hygiene.
It will be explained in more depth in the corresponding macro_rules!
hygiene
and proc-macro hygiene
chapters, with their specific peculiarities.