派生宏的名称-值帮助器属性中允许哪些表达式类型?

问题描述 投票:0回答:1

Rust 的派生宏允许 helper 属性,例如

#[derive(HelperAttr)]
struct Struct {
    #[helper] field: ()
}

根据

syn
文档,属性可以采用名称-值形式,其中值是 Rust 表达式:

Meta::NameValue — 路径后面带有 = 符号的属性,后跟 Rust 表达式。例如#[path = "sys/windows.rs"].

所以我尝试了:

#[values = ["a", "b"]]

这不起作用。字符串起作用。数字起作用。布尔有效。数组,好像没有。编译器错误。

error: unexpected expression: `["a", "b"]`
 --> tests/test1.rs:5:16
  |
5 |     #[values = ["a", "b"]]
  |   

但是

syn
文档的类型定义似乎表明应该支持任何 Rust 表达式。

哪里记录了支持的内容?名称-值属性中实际支持的值是什么?

rust macros
1个回答
0
投票

尽管 Rust 语言参考将

Expression
声明为属性中
=
之后的
SimplePath
后面的有效标记。大多数表达式(元组、闭包也属于族)在这里无效,我想这应该是
LiteralExpression

在库中,常见的模式是用

MetaList
术语代替数组之类的参数。 例如

#[derive(HelperAttr)]
struct MyStruct {
    #[values(1, 2, 3)] 
    my_field: u32,
}

可以通过以下定义用

syn
来读取

#[proc_macro_derive(HelperAttr, attributes(values))]
pub fn derive_example(item: TokenStream) -> TokenStream {

    let tokens = item.clone();
    let ast = parse_macro_input!(tokens as DeriveInput);

    let struct_: syn::DataStruct = match ast.data {
        syn::Data::Struct(data) => data,
        _ => panic!("Failed to parse HelperAttr, didn't parse struct"),
    };
   
    for field in struct_.fields.iter() {
        for attr in field.attrs.iter() {
            if attr.path().is_ident("values") {
                let meta_list = attr.meta.require_list();
                if let Ok(meta_list) = meta_list {
                    println!("{:#?}", meta_list.tokens);
                }
            }
        }
    }
    TokenStream::new()
}
© www.soinside.com 2019 - 2024. All rights reserved.