Macro hygiene
- Rust course
- Advanced
- Lesson 45/81
- 4 min
Learn macro hygiene.
Macro hygiene
Rust macros are hygienic: local variables defined inside a macro don't mix with same-named variables in the calling code. Each identifier remembers the "context" it came from:
macro_rules! ikile {
($x:expr) => {{
let gecici = $x;
gecici * 2
}};
}
let gecici = 5;
let s = ikile!(gecici + 1); // the outer gecici is used: 12
println!("{s} {gecici}"); // 12 5C preprocessor macros do text substitution and are open to such name clashes; Rust doesn't have this class of bugs.
Limits of hygiene
Hygiene applies to local variables and labels; not to functions, types or module paths. If a macro will be used in another module, paths must be written in full with $crate:::
#[macro_export]
macro_rules! hata {
($m:expr) => {
$crate::kayit::yaz("HATA", $m) // from the macro's crate
};
}A macro that intentionally wants to use one of the caller's variables must take the name as an argument ($ad:ident).
Practice Hygienic macro
Write the ikile! macro above. After defining let gecici = 5;, print the result of ikile!(gecici + 1) and the value of gecici separated by a space.
Starter code
fn main() {
// buraya yaz
}Sample solution
macro_rules! ikile {
($x:expr) => {{
let gecici = $x;
gecici * 2
}};
}
fn main() {
let gecici = 5;
let s = ikile!(gecici + 1);
println!("{} {}", s, gecici);
}Expected output
12 5
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 What do the double braces <code>{{ .. }}</code> in the body do?
- The outer pair delimits the macro body, the inner one opens a block expression Correct answer
- It's an escape
- It errors
- It has no meaning
Explanation: The inner block lets the macro return several statements as a single expression.
2 Crate path
#[macro_export]
macro_rules! hata {
($m:expr) => {
____::kayit::yaz("HATA", $m)
};
}
#[macro_export]
macro_rules! hata {
($m:expr) => {
$crate::kayit::yaz("HATA", $m)
};
}
Explanation: $crate expands to the root of the crate where the macro is defined.
3 Concept and meaning
| Term | Meaning |
|---|---|
Hijyen |
Local names don't mix |
{{ .. }} |
Returns a block expression |
$crate:: |
The macro's crate |
#[macro_export] |
Exposes outside the crate |