我想使用宏为多个具体类型生成相同的impl块。我的代码目前看起来如下所示:
macro_rules! impl_methods {
($ty:ty, { $($method:item);+} ) => {
impl $ty { $($method)+ }
};
($ty:ty, $($more:ty),+ {$($method:item);+}) => {
impl_methods!($ty, {$($method);+});
impl_methods!($($more),+, {$($method);+});
};
}
struct Hi;
struct Hello;
impl_methods!(Hi, Hello {
/// `true` if it works, good
fn works_good(&self) -> bool {
true
};
/// `true` if rustfmt is working
fn gets_rustfmt(&self) -> bool {
false
}
});
assert!(Hi.works_good() && Hello.works_good());
assert!(!(Hi.gets_rustfmt() | Hello.gets_rustfmt()));这已经足够好了(生成了内嵌),但是它有一个令人沮丧的问题;在宏中定义的方法不会被rustfmt格式化。
这是一个小问题,但它够烦人的,我对一个解决方案很好奇。我知道,rustfmt将格式化宏的内容,如果这些内容有某种形式(是表达式吗?)因此,例如,将格式化以下宏的内容:
macro_rules! fmt_me {
($inner:item) => {
$inner
};
}
fmt_me!(fn will_get_formatted() -> bool { true });所以我希望能有一些方法来写我的宏,
impl_methods!(Hi, Hello {
fmt_me!(fn my_method(&self) -> bool { true });
fmt_me!(fn my_other_method(&self) -> bool { false });
});让每个方法都被锈蚀覆盖。
这个是可能的吗?有什么神奇的咒语能给我带来我想要的可爱的格式吗?
回答
由于下面的答案(来自@seiichi-uchida),我可以使用以下代码来处理这个问题:
macro_rules! impl_methods {
($ty:ty, { $($method:item)+} ) => {
impl $ty { $($method)+ }
};
($ty:ty, $($more:ty),+, {$($method:item)+}) => {
impl_methods!($ty, {$($method)+});
impl_methods!($($more),+, {$($method)+});
};
}
macro_rules! fmt_me {
($inner:item) => {
$inner
};
}
// called like:
impl_methods!(Hi, Hello, {
fmt_me!(fn this_is_a_method(&self) -> bool { true });
fmt_me!(fn this_is_another_method(&self) -> bool { true });
});发布于 2020-05-29 00:53:19
在最后一个类型和impl块之间添加一个逗号应该可以做到这一点:
impl_methods!(Hi, Hello, {
fmt_me!(fn my_method(&self) -> bool { true });
fmt_me!(fn my_other_method(&self) -> bool { false });
});这将被格式化为:
impl_methods!(Hi, Hello, {
- fmt_me!(fn my_method(&self) -> bool { true });
- fmt_me!(fn my_other_method(&self) -> bool { false });
+ fmt_me!(
+ fn my_method(&self) -> bool {
+ true
+ }
+ );
+ fmt_me!(
+ fn my_other_method(&self) -> bool {
+ false
+ }
+ );
});通常,rustfmt只能格式化其参数可以解析为有效的Rust AST节点的宏调用(除了一些例外)。
https://stackoverflow.com/questions/62070972
复制相似问题