大家好,我最近写了一个声明宏。但我对 泛型
、dyn关键字
和 trait
使用什么片段说明符(fragment-specifier)
感到困惑。
我尝试使用 tt
来指定它们,虽然只编译宏通过,但使用时发生编译错误:
error: local ambiguity when calling macro `struct_new`: multiple parsing options: built-in NTs tt ('limit') or 1 other option.
解析
<
会导致此错误。
我的这个宏是为了简化结构体的创建和它的初始化 new() 关联函数。
这是完整的宏代码和用例:
macro_rules! struct_new {
($vis:vis struct $s_name:ident;) => {$vis struct $s_name;};
($(#[$attr:meta])* $vis:vis struct $s_name:ident $(<$($generic:tt),*>)? $(($($p_vis:vis $p_name:ident: $p_type:ty),* $(,)?))? $(where $($id:tt: $($limit:tt $(<$dyn:tt $traits:tt $(($($t:tt),*) $(-> ($($r:tt),*))?)?>)?)+*),*)? {
$($field_vis:vis $field:ident: $type:ty = $val:expr),* $(,)?
}
$($tail:tt)*) => {
$(#[$attr])*
$vis struct $s_name $(<$($generic),*>)? $(where $($id: $($limit $(<$dyn $traits $(($($t),*) $(-> ($($r),*))?)?>)?)+*),*)? {
$($($p_vis $p_name: $p_type,)*)?
$($field_vis $field: $type),*
}
impl $(<$($generic),*>)? $s_name $(<$($generic),*>)? $(where $($id: $($limit $(<$dyn $traits $(($($t),*) $(-> ($($r),*))?)?>)?)+*),*)? {
fn new($($($p_name: $p_type),*)?) -> Self {
$s_name {
$($($p_name,)*)?
$($field: $val),*
}
}
}
struct_new! {
$($tail)*
}
};
() => {}
}
struct_new!(
#[derive(Debug)]
pub struct A<'a, T, R>(foo: T, pub bar: &'a str,) where T: Box<dyn FnOnce(T) -> R> {
pub abc: u8 = 255,
xyz: &'a str = "xyz",
}
struct B {}
struct C;
);
1
共 2 条评论, 1 页
评论区
写评论我用过程宏做到了类似的功能(语法使用上不完全一样):struct_new2-multi.rs
https://github.com/zjp-CN/structs_new
想要简便的匹配方式,用 ty 分类符,但是在你的例子里不行,理由如下:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=bddd4fe5776be6ffeb1fc6abae68a1ff
简短地说,
$($t:tt)*
捕获的内容会超出你所控制的范围,让你期望范围之外的标记捕获进来,而且via The Little Book of Rust Macros