Rust proc_macro_derive:如何检查字段是否为基本类型,如布尔类型?

Rust proc_macro_derive:如何检查字段是否为基本类型,如布尔类型?,rust,rust-proc-macros,Rust,Rust Proc Macros,我试图过滤掉结构的所有类型为bool的字段。但是syn::Typeenum似乎没有这样的理由,或者我读错了定义: pub枚举类型{ 数组(TypeArray), BareFn(类型BareFn), 组(类型组), ImplTrait(类型ImplTrait), 推断(类型推断), 宏(TypeMacro), 从不(打字从不), Paren(类型Paren), 路径(类型路径), Ptr(类型Ptr), 参考(类型参考), 切片(TypeSlice), TraitObject(类型TraitObj

我试图过滤掉结构的所有类型为
bool
的字段。但是
syn::Type
enum似乎没有这样的理由,或者我读错了定义:

pub枚举类型{
数组(TypeArray),
BareFn(类型BareFn),
组(类型组),
ImplTrait(类型ImplTrait),
推断(类型推断),
宏(TypeMacro),
从不(打字从不),
Paren(类型Paren),
路径(类型路径),
Ptr(类型Ptr),
参考(类型参考),
切片(TypeSlice),
TraitObject(类型TraitObject),
元组(TypeTuple),
逐字(令牌流),
//省略了一些变体
}
我通过
syn::Types
source查看了哪些变体位于ommited的位置,但这并没有让我进一步了解。以下是我到目前为止所拥有的:

#[proc_macro_派生(创建者)]
发布fn派生\u创建者(\u项:TokenStream)->TokenStream{
让item=parse_macro_input!(_itemas syn::DeriveInput);
设item_ident=item.ident;
let fields=如果让syn::Data::Struct(syn::DataStruct{
字段:syn::fields::Named(syn::FieldsNamed{ref Named,…}),
..
})=item.data
{
命名
}否则{
恐慌!(“您只能在结构上派生创建者!”)
};
设bool_fields=fields.iter().filter(| field |
比赛场地{
//字段类型为bool=>true时的情况
_=>错误
}
);
未执行!()
}

我走错路了吗?还是这根本不可能?还是我遗漏了什么?

我觉得可能有一种更干净的方法(不必克隆和分配字符串),但过去我做过类似的事情:

match field.ty {
    Type::Path(type_path) if type_path.clone().into_token_stream().to_string() == "bool" => {
        true
    }
    _ => false
}

您可以定义一次
bool
类型,然后比较它是否相等:

let bool_ty = Type::Path(TypePath {
    qself: None,
    path: Path::from(Ident::new("bool", Span::call_site())),
});

if field.ty == bool_ty {
    // it's a bool
}
但我不确定跨度的差异是否会影响平等
Span
似乎没有实现
PartialEq
,所以我猜这是可以的*


*欢迎编辑以澄清这一点。

另一种方式:

让bool_fields=fields.iter().filter(| field |{
如果let Type::Path(tp)=&field.ty{
让分段=&tp.path.segments;
//选中len以避免“bool::SomeOtherType”。
如果segments.len()==1{
返回段[0]。标识==“bool”;
}
}
假的
});
记住:


值得指出的是,这检查名称是否相等。类型别名、单个字段元组或core::primitive::bool将不匹配,尽管它们在类型解析后都是bool用户2722968


proc宏实际上无法知道什么是
bool
Type
引用语法规则(例如,“这是一个元组,因为它看起来像一个元组”),但proc宏实际上不能进行类型解析。根据定义,如果我做
type Foo=bool
struct Foo(bool)
,proc宏只会看到名为
Foo
的类型。您可以使用名为
bool
的类型的特殊情况,并希望这将解析为
core::primitive::bool
。这还将匹配一个限定的类型
bool::SomeOtherType
。啊,很好。让我看看它是否是可修复的。不过,公平地说,如果有人定义一个名为
bool
的模块,那就不太可能/奇怪了。值得指出的是,这个模块通过名称检查是否相等。类型别名、单字段元组或
core::primitive::bool
将不匹配,尽管它们在类型解析后都是
bool
。我喜欢您的第一个解决方案。我要看看这是否有效:
rust let bool_fields=fields.iter().filter(|field | match&field.ty{syn::Type::Path(Type_Path),如果Type_Path.Path.is_ident(“bool”)=>true,=>false,})就像一个魅力!谢谢你给我指明了正确的方向。你可以使用
is_ident
来回避克隆思想。