Generics 如何实现为泛型枚举实现泛型特征的过程宏?
如何为这样的枚举实现过程宏Generics 如何实现为泛型枚举实现泛型特征的过程宏?,generics,enums,macros,rust,Generics,Enums,Macros,Rust,如何为这样的枚举实现过程宏 #[derive(Copy, Clone, Debug, MyProcMacro)] enum Enum<W, C, I, F> { A(W), B(C), C(I), D(F) } 和执行: #[proc_macro_derive(MyProcMacro)] pub fn my_proc_macro(input: TokenStream) -> TokenStream { // Construct a st
#[derive(Copy, Clone, Debug, MyProcMacro)]
enum Enum<W, C, I, F> {
A(W),
B(C),
C(I),
D(F)
}
和执行:
#[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
}
}
}
我觉得这个错误很奇怪,因为这个enum
确实派生了Copy
特性
UPD:
根据@Matthieu M.的评论,我通过向每个枚举类型添加Copy
要求,成功地编译了它:
enum CupState<W: Copy, C: Copy, I: Copy, F: Copy> { ... }
枚举状态{…}
但是,我仍在寻找一种不需要用户代码操作的更好的解决方案。如果需要派生的自类型来实现
Copy
,可以让派生宏向生成的impl块中的每个类型参数添加一个绑定的T:Copy
extern crate proc_macro;
use self::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics};
#[proc_macro_derive(MyProcMacro)]
pub fn my_proc_macro(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let generics = add_trait_bounds(ast.generics);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
TokenStream::from(quote! {
impl #impl_generics MyTrait<Self> for #name #ty_generics #where_clause {
fn change(&mut self, new_obj: Self) -> bool {
true
}
}
})
}
// Add a bound `T: Copy` to every type parameter T.
fn add_trait_bounds(mut generics: Generics) -> Generics {
for param in &mut generics.params {
if let GenericParam::Type(ref mut type_param) = *param {
type_param.bounds.push(parse_quote!(Copy));
}
}
generics
}
我觉得这个错误很奇怪,因为这个枚举肯定派生了复制特征。=>事实上并非如此。派生
复制
,克隆
。。。在泛型上,仅在所有数据成员也实现特征的条件下实现特征。因此,对于不受限于实现Copy
的泛型W
,整个泛型枚举不实现Copy
。那么如何修复它呢?通过添加:将复制到ty_generics
中的每个类型?如果我知道如何解决这个问题,我会发布一个答案,而不是评论。对不起:x
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
}
}
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 CupState<W: Copy, C: Copy, I: Copy, F: Copy> { ... }
extern crate proc_macro;
use self::proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, parse_quote, DeriveInput, GenericParam, Generics};
#[proc_macro_derive(MyProcMacro)]
pub fn my_proc_macro(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let name = &ast.ident;
let generics = add_trait_bounds(ast.generics);
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
TokenStream::from(quote! {
impl #impl_generics MyTrait<Self> for #name #ty_generics #where_clause {
fn change(&mut self, new_obj: Self) -> bool {
true
}
}
})
}
// Add a bound `T: Copy` to every type parameter T.
fn add_trait_bounds(mut generics: Generics) -> Generics {
for param in &mut generics.params {
if let GenericParam::Type(ref mut type_param) = *param {
type_param.bounds.push(parse_quote!(Copy));
}
}
generics
}
use my_proc_macro::MyProcMacro;
pub trait MyTrait<S> {
fn change(&mut self, new_obj: S) -> bool;
}
#[derive(Copy, Clone, Debug, MyProcMacro)]
enum Enum<W, C, I, F> {
A(W),
B(C),
C(I),
D(F),
}
impl<W: Copy, C: Copy, I: Copy, F: Copy> MyTrait<Self> for Enum<W, C, I, F> {
fn change(&mut self, new_obj: Self) -> bool {
true
}
}