以下是我正在尝试为我正在处理的RPC库实现的宏的简化版本:
#[macro_export]
macro_rules! msgpack_rpc {
(
$(
rpc $name:ident ( $( $arg:ident : $arg_ty:ty ),* ) -> $ret_ty:ty | $err_ty:ty;
)+
) => (
pub trait Service {
$(
fn $name ( &self, $( $arg : $arg_ty ),* ) -> Result<$ret_ty, $err_ty>;
)+
}
pub struct Server;
impl Server {
pub fn listen<S>(handle: &(), address: (), service: S)
-> ::std::io::Result<()>
where S: Service + Send + Sync + 'static {
let service = move |msg: &str| {
let result = match msg {
$(
stringify!($name) => {
service.$name($( $arg ),*)
.map(String::from)
.map_err(String::from)
}
),+,
_ => String::from("method not supported".into()),
};
};
Ok(())
}
}
)
}
msgpack_rpc! {
rpc echo(arg: i64) -> i64 | ();
}
宏扩展无法使用此错误进行编译:
error: unresolved name `arg` [--explain E0425]
--> <anon>:40:17
|>
40 |> rpc echo(arg: i64) -> i64 | ();
|> ^
<anon>:39:1: 41:2: note: in this expansion of msgpack_rpc! (defined in <anon>)
通过阅读类似的问题,我知道macro_rules
有时会在扩展陈述方面遇到问题。但是,我很困惑为什么在这种情况下无法扩展项目。
是否有解决方法来修复扩展?
答案 0 :(得分:3)
在调用函数的上下文中没有名为arg
的变量。这是编译器抱怨的“未解析的arg
”。
stringify!($name) => {
$( let $arg = Default::default(); )*
service.$name($( $arg ),*)
.map(String::from)
.map_err(String::from)
}