Rust宏展开忽略token `for`及后续内容,求解决方案
Rust宏展开忽略
for及后续内容的解决方法 问题描述
编写了一个用于发送命令并等待响应的Rust宏,代码如下:
/// send a command and wait for the response /// /// 'dirty' macro that relies on outside context macro_rules! send_and_receive { ($cmd: expr, $response_pat:pat => $r_block:block) => { send_command(&mut port, $cmd); for i in 0..3 { match receive_response(&mut port) { $response_pat => $r_block, r => { eprintln!("got response: {r:?}"); continue; } }; } panic!("missing response"); } }
调用示例:
send_and_receive!( Command::Thing { field: value /* etc */ }, Response::ThingResponse { response_field1, /* ... */ } => { do_stuff_here(); } );
宏展开时仅保留了开头的send_command调用,for循环及后续的错误处理代码被忽略。
问题原因
Rust宏解析器会误将模式参数(如Response::ThingResponse { response_field1, ... })内部的逗号判定为宏参数的分隔符,导致宏规则无法完整匹配$response_pat:pat => $r_block:block这部分参数,最终只展开了宏规则的前半部分。
解决方法
方法一:给模式与代码块整体添加括号
修改宏规则,将第二个参数用括号包裹,明确参数边界:
macro_rules! send_and_receive { ($cmd: expr, ($response_pat:pat => $r_block:block)) => { send_command(&mut port, $cmd); for i in 0..3 { match receive_response(&mut port) { $response_pat => $r_block, r => { eprintln!("got response: {r:?}"); continue; } }; } panic!("missing response"); } }
调用时对应给模式和代码块部分加括号:
send_and_receive!( Command::Thing { field: value /* etc */ }, (Response::ThingResponse { response_field1, /* ... */ } => { do_stuff_here(); }) );
方法二:改用=>分隔命令参数
调整宏规则的参数分隔逻辑,用=>替代逗号分隔命令与后续部分,彻底避免逗号冲突:
macro_rules! send_and_receive { ($cmd: expr => $response_pat:pat => $r_block:block) => { send_command(&mut port, $cmd); for i in 0..3 { match receive_response(&mut port) { $response_pat => $r_block, r => { eprintln!("got response: {r:?}"); continue; } }; } panic!("missing response"); } }
调用时对应调整格式:
send_and_receive!( Command::Thing { field: value /* etc */ } => Response::ThingResponse { response_field1, /* ... */ } => { do_stuff_here(); } );
内容的提问来源于stack exchange,提问作者Luctins
相关产品推荐
相关产品推荐

