我有一个在unsafe
块内调用的宏,它具有以下模式:
( $mrb:expr, $sig:expr, $args:ident, $name:ident : $t:tt) => {
let $args = uninitialized::<*const MRValue>();
let count = uninitialized::<i32>();
mrb_get_args($mrb, $sig, args!($name, $t), &$args as *const *const MRValue,
&count as *const i32);
};
我用--pretty expanded,hygiene
扩展了宏,它给了我:
let args /* 77#30 */ =
uninitialized /* 789#28
*/::<*const MRValue /* 793#28 */>();
let count /* 807#31 */ =
uninitialized /* 789#28 */::<i32 /* 68#28 */>();
mrb_get_args /* 805#28
*/(mrb /* 804#29 */, sig /* 797#29 */,
&v /* 76#33 */ as *const i32 /* 68#34 */,
&args /* 77#27 */ as
*const *const MRValue /* 793#28 */,
&count /* 807#28 */ as *const i32 /* 68#28 */);
args
似乎是相同的(77
),而且计数似乎也相同(807
),但我仍然收到以下错误:
<mrusty macros>:24:20: 24:21 error: unresolved name `args`. Did you mean the macro `args!`? [E0425]
<mrusty macros>:24 mrb , sig , $ args , $ ( $ name : $ t ) , * ) ; conv ! (
^
<mrusty macros>:23:29: 24:48 note: in this expansion of args_rest! (defined in <mrusty macros>)
src/main.rs:12:47: 16:7 note: in this expansion of mrfn! (defined in <mrusty macros>)
<mrusty macros>:24:20: 24:21 help: run `rustc --explain E0425` to see a detailed explanation
<mrusty macros>:6:5: 6:10 error: unresolved name `count` [E0425]
<mrusty macros>:6 , & count as * const i32 ) ; } ; (
^~~~~
<mrusty macros>:23:29: 24:48 note: in this expansion of args_rest! (defined in <mrusty macros>)
src/main.rs:12:47: 16:7 note: in this expansion of mrfn! (defined in <mrusty macros>)
<mrusty macros>:6:5: 6:10 help: run `rustc --explain E0425` to see a detailed explanation
这看起来很可疑而且看起来像是一个错误,但在我提交Rust问题之前,我想要另外一双眼睛。
答案 0 :(得分:4)
试试这个:
( $mrb:expr, $sig:expr, $args:ident, $name:ident : $t:tt) => {{
let $args = uninitialized::<*const MRValue>();
let count = uninitialized::<i32>();
mrb_get_args($mrb, $sig, args!($name, $t), &$args as *const *const MRValue,
&count as *const i32);
}};
(注意宏扩展的主体被包裹在第二组大括号中)
我不记得你需要它的确切原因,但基本的想法是宏扩展块中的每个语句都扩展了它自己的卫生上下文,因此第一行中的$args
不是与最后一行中的$args
相同。但是,如果将所有语句放入单个块中,则卫生上下文将被共享,$args
的两个扩展现在都引用相同的标识符。所以,这可能不是一个错误;这就是Rust的宏扩展如何运作。
答案 1 :(得分:0)
这不起作用的基本原因是因为多语句宏被破坏了。任何不返回值的宏(例如块)都只返回第一个语句。
macro_rules! example {
( $name:ident ) => {
let mut $name = 0;
let mut $name = 1;
}
}
fn main() {
example!(x);
println!("{}", x);
}
此示例打印0
,而不是1
。 bug已关闭,但它可能会落在Rust 1.10。
同时,在适用的情况下使用块。