When creating an identifier in a declarative macro, it is mandatory to put additional brackets in the macro (double brackets). I was wondering why the compiler does not just (always) add the additional brackets.
Example 1: this code will not compile because only single brackets are used where double brackets are mandatory:
macro_rules! some_macro {
() => {
let mut x = 1;
x += 1;
x
};
}
fn main() {
let y = some_macro!();
}
Adding double brackets solves the compile error.
Example 2: this code will compile regardless of using single or double brackets:
macro_rules! some_macro {
() => {{
1
}};
}
fn main() {
let y = some_macro!();
}
Are there cases in which a macro with double brackets breaks single brackets macros? If not, why doesn't the compiler always adds double brackets?
There is a case where double braces would fail. Since the inside braces create a scope, if you want to declare any identifiers, they won't be "exported":
// compiles with single braces but not double braces
macro_rules! set_ident_to_1 {
($var: ident) => {
let $var = 1;
}
}
fn main() {
set_ident_to_1!(foo);
println!("{}", foo);
}
There may also be cases where braces just straight up aren't allowed, like top level definitions. Take, for example, this macro that crates a repetitive Deref
implementation:
struct Foo {
x: i32
}
struct Bar {
y: u32
}
// compiles with single braces but not double braces
macro_rules! create_repetitive_impl {
($prop: ident, $typ: ty, $target: ty) => {
impl std::ops::Deref for $typ {
type Target = $target;
fn deref(&self) -> &Self::Target {
&self.$prop
}
}
}
}
create_repetitive_impl!(x, Foo, i32);
create_repetitive_impl!(y, Bar, u32);
fn main() {
println!("{:?}", Foo {x: 5}.checked_mul(6))
}