Rust中如何使用宏内部定义的struct并在外部作用域构造实例
根本原因
两段代码运行结果差异的核心是宏展开后生成的代码块层级不同,受Rust作用域规则约束产生了不同的效果:
- 第一段报错代码中,
helper宏的展开内容被两层大括号包裹:=> {{ ... }},最外层的大括号是Rust表达式块的边界,内部定义的Person结构体属于这个块的局部作用域,超出这个块就无法被外部访问,因此你在宏调用外的main作用域里直接使用Person会报找不到类型的错误。 - 第二段可运行代码中,
r宏的展开内容只有一层大括号:=> { ... },宏展开后struct A的定义直接落在了调用它的main函数作用域下,没有额外的块边界隔离,因此后续在main里可以直接访问A类型。
具体展开对比
第一段报错代码的宏展开结果
helper!(5)展开后等价于以下代码:
let x = { #[derive(Debug)] struct Person { pub age: u64, } let p = Person { age: 5 }; p };
这里Person的定义被包在表达式块内部,块执行结束后这个类型就超出了作用域,自然无法在块外再构造Person实例。
第二段正常代码的宏展开结果
m::r! {}展开后等价于直接在main函数内插入了以下代码:
#[derive(Debug)] struct A; impl A { fn new() -> Self { A } }
没有额外的块做隔离,A的定义直接属于main函数的作用域,后续当然可以直接构造A{}实例。
补充说明
如果你需要宏定义的结构体可以在外部作用域使用,就不要把结构体的定义包在多余的表达式块里;如果你不希望宏内部的类型泄漏到外部作用域,就用两层大括号包裹宏展开内容,形成局部作用域隔离即可。
内容的提问来源于stack exchange,提问作者boundless-forest
相关产品推荐
相关产品推荐

