为什么编译器不会自动在声明性宏中添加双括号?

J. *_*Doe 1 rust rust-macros

在声明性宏中创建标识符时,必须在宏中添加额外的括号(双括号)。我想知道为什么编译器不只是(总是)添加额外的括号。

示例 1:此代码将无法编译,因为在必须使用双括号的情况下仅使用单括号:

macro_rules! some_macro {
    () => {
        let mut x = 1;

        x += 1;

        x
    };
}

fn main() {
    let y = some_macro!();
}
Run Code Online (Sandbox Code Playgroud)

添加双括号解决了编译错误。

示例 2:无论使用单括号还是双括号,此代码都会编译:

macro_rules! some_macro {
    () => {{
        1
    }};
}

fn main() {
    let y = some_macro!();
}
Run Code Online (Sandbox Code Playgroud)

是否存在带有双括号的宏破坏单括号宏的情况?如果没有,为什么编译器不总是添加双括号?

Apl*_*123 5

有一种情况,双大括号会失败。由于内大括号创建了一个范围,如果您想声明任何标识符,它们将不会被“导出”:

// 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);
}
Run Code Online (Sandbox Code Playgroud)

也可能存在不允许直接使用大括号的情况,例如顶级定义。以这个创建重复Deref实现的宏为例:

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))
}
Run Code Online (Sandbox Code Playgroud)