【发布时间】:2017-02-28 12:49:58
【问题描述】:
如何为这样的枚举实现过程宏?
#[derive(Copy, Clone, Debug, MyProcMacro)]
enum Enum<W, C, I, F> {
A(W),
B(C),
C(I),
D(F)
}
我尝试使用syn::Generics,但它无法编译并产生无效代码。这是我想要实现的特征:
pub trait MyTrait<S> {
fn change(&mut self, new_obj: S) -> bool;
}
及实施:
#[proc_macro_derive(MyProcMacro)]
pub fn my_proc_macro(input: TokenStream) -> TokenStream {
// Construct a string representation of the type definition
let s = input.to_string();
// Parse the string representation
let ast = syn::parse_derive_input(&s).unwrap();
// Build the impl
let gen = impl_macro(&ast);
// Return the generated impl
gen.parse().unwrap()
}
fn impl_macro(ast: &syn::DeriveInput) -> Tokens {
let name = &ast.ident;
let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl();
quote! {
impl #impl_generics mycrate::MyTrait<#name #ty_generics> for #name #ty_generics #where_clause {
fn change(&mut self, new_obj: #name #ty_generics) -> bool {
true
}
}
}
它给出了这个代码:
impl < W , C , I , F > mycrate :: MyTrait < Enum < W , C , I , F > > for Enum < W , C , I , F > {
fn change ( & mut self , new_obj : Enum < W , C , I , F > ) -> bool {
true
}
}
我觉得应该是这样的:
impl MyTrait<Enum<u64, u64, u64, u64>> for Enum<u64, u64, u64, u64> {
fn change(&mut self, new_obj: Enum<u64, u64, u64, u64>) {
true
}
}
据我了解,我们无法从过程宏上下文中获取有关所需类型的信息,对吗?我想这就是我在syn crate 中找不到此类信息的原因。
如果我不修改我编写的代码,我会收到此错误:
error[E0382]: use of moved value: `new_obj`
--> src/main.rs:28:30
|
28 | #[derive(Copy, Clone, Debug, MyProcMacro)]
| ^^^^^^^^^^^ value moved here in previous iteration of loop
|
= note: move occurs because `new_obj` has type `Enum<W, C, I, F>`, which does not implement the `Copy` trait
这个错误在我看来很奇怪,因为这个 enum 肯定派生了 Copy 特征。
更新:
根据@Matthieu M. 的评论,我能够通过向每个枚举类型添加Copy 要求来成功编译它:
enum CupState<W: Copy, C: Copy, I: Copy, F: Copy> { ... }
但是,我仍在寻找不需要用户代码操作的更好的解决方案。
【问题讨论】:
-
这个错误对我来说看起来很奇怪,因为这个枚举肯定派生了 Copy trait。 => 实际上并非如此。在泛型上派生
Copy,Clone, ... 仅在所有数据成员也实现该特征的条件下实现特征。因此,对于不受限制实现Copy的泛型W,整个泛型枚举不会实现Copy。 -
那么我该如何解决呢?通过将
: Copy添加到ty_generics中的每个类型? -
如果我知道如何解决这个问题,我会发布答案,而不是评论。对不起:x
标签: generics enums macros rust