From 09bd42a15b4bd46bd12b7a222e44676ca0391f84 Mon Sep 17 00:00:00 2001 From: bsh98 Date: Sat, 6 Jan 2024 22:46:31 -0800 Subject: [PATCH 1/4] fix generics --- trait-variant/examples/variant.rs | 4 +++- trait-variant/src/variant.rs | 18 ++++++------------ 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/trait-variant/examples/variant.rs b/trait-variant/examples/variant.rs index 428e737..f175bb7 100644 --- a/trait-variant/examples/variant.rs +++ b/trait-variant/examples/variant.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::future::Future; +use std::{future::Future, ops::Add}; #[trait_variant::make(IntFactory: Send)] pub trait LocalIntFactory { @@ -36,6 +36,8 @@ where { const CONST: usize = 3; type F; + type A; + type B: Add; async fn take(&self, s: S); } diff --git a/trait-variant/src/variant.rs b/trait-variant/src/variant.rs index c2cb9c6..8e36a99 100644 --- a/trait-variant/src/variant.rs +++ b/trait-variant/src/variant.rs @@ -15,9 +15,9 @@ use syn::{ parse_macro_input, punctuated::Punctuated, token::{Comma, Plus}, - Error, FnArg, GenericParam, Generics, Ident, ItemTrait, Lifetime, Pat, PatType, Result, - ReturnType, Signature, Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn, - TraitItemType, Type, TypeImplTrait, TypeParamBound, + Error, FnArg, GenericParam, Ident, ItemTrait, Lifetime, Pat, PatType, Result, ReturnType, + Signature, Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, + TypeImplTrait, TypeParamBound, }; struct Attrs { @@ -256,17 +256,11 @@ fn blanket_impl_item( } } TraitItem::Type(TraitItemType { - ident, - generics: - Generics { - params, - where_clause, - .. - }, - .. + ident, generics, .. }) => { + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { - type #ident<#params> = >::#ident<#params> #where_clause; + type #ident #impl_generics = >::#ident #ty_generics #where_clause; } } _ => Error::new_spanned(item, "unsupported item type").into_compile_error(), From 708e01930f71b1d7d120abe148a2e98d033a3424 Mon Sep 17 00:00:00 2001 From: bsh98 Date: Sun, 7 Jan 2024 01:12:59 -0800 Subject: [PATCH 2/4] clean up generics with split_for_impl --- trait-variant/src/variant.rs | 66 ++++++++++-------------------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/trait-variant/src/variant.rs b/trait-variant/src/variant.rs index 8e36a99..27d6b0f 100644 --- a/trait-variant/src/variant.rs +++ b/trait-variant/src/variant.rs @@ -9,15 +9,15 @@ use std::iter; use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; +use quote::quote; use syn::{ parse::{Parse, ParseStream}, - parse_macro_input, + parse_macro_input, parse_quote, punctuated::Punctuated, - token::{Comma, Plus}, - Error, FnArg, GenericParam, Ident, ItemTrait, Lifetime, Pat, PatType, Result, ReturnType, - Signature, Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, - TypeImplTrait, TypeParamBound, + token::Plus, + Error, FnArg, Ident, ItemTrait, Pat, PatType, Result, ReturnType, Signature, Token, TraitBound, + TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, TypeGenerics, TypeImplTrait, + TypeParamBound, }; struct Attrs { @@ -162,59 +162,29 @@ fn transform_item(item: &TraitItem, bounds: &Vec) -> TraitItem { fn mk_blanket_impl(attrs: &Attrs, tr: &ItemTrait) -> TokenStream { let orig = &tr.ident; - let generics = &tr.generics.params; - let mut generic_names = tr - .generics - .params - .iter() - .map(|generic| match generic { - GenericParam::Lifetime(lt) => GenericParamName::Lifetime(<.lifetime), - GenericParam::Type(ty) => GenericParamName::Type(&ty.ident), - GenericParam::Const(co) => GenericParamName::Const(&co.ident), - }) - .collect::>(); - let trailing_comma = if !generic_names.is_empty() { - generic_names.push_punct(Comma::default()); - quote! { , } - } else { - quote! {} - }; let variant = &attrs.variant.name; + let (_impl, orig_ty_generics, _where) = &tr.generics.split_for_impl(); let items = tr .items .iter() - .map(|item| blanket_impl_item(item, variant, &generic_names)); - let where_clauses = tr.generics.where_clause.as_ref().map(|wh| &wh.predicates); + .map(|item| blanket_impl_item(item, variant, orig_ty_generics)); + let mut blanket_generics = tr.generics.to_owned(); + blanket_generics + .params + .push(parse_quote!(TraitVariantBlanketType: #variant #orig_ty_generics)); + let (blanket_impl_generics, _ty, blanket_where_clause) = &blanket_generics.split_for_impl(); quote! { - impl<#generics #trailing_comma TraitVariantBlanketType> #orig<#generic_names> - for TraitVariantBlanketType - where TraitVariantBlanketType: #variant<#generic_names>, #where_clauses + impl #blanket_impl_generics #orig #orig_ty_generics for TraitVariantBlanketType #blanket_where_clause { #(#items)* } } } -enum GenericParamName<'s> { - Lifetime(&'s Lifetime), - Type(&'s Ident), - Const(&'s Ident), -} - -impl ToTokens for GenericParamName<'_> { - fn to_tokens(&self, tokens: &mut TokenStream) { - match self { - GenericParamName::Lifetime(lt) => lt.to_tokens(tokens), - GenericParamName::Type(ty) => ty.to_tokens(tokens), - GenericParamName::Const(co) => co.to_tokens(tokens), - } - } -} - fn blanket_impl_item( item: &TraitItem, variant: &Ident, - generic_names: &Punctuated, Comma>, + trait_ty_generics: &TypeGenerics<'_>, ) -> TokenStream { // impl IntFactory for T where T: SendIntFactory { // const NAME: &'static str = ::NAME; @@ -231,7 +201,7 @@ fn blanket_impl_item( .. }) => { quote! { - const #ident #generics: #ty = >::#ident; + const #ident #generics: #ty = ::#ident; } } TraitItem::Fn(TraitItemFn { sig, .. }) => { @@ -251,7 +221,7 @@ fn blanket_impl_item( }; quote! { #sig { - >::#ident(#(#args),*)#maybe_await + ::#ident(#(#args),*)#maybe_await } } } @@ -260,7 +230,7 @@ fn blanket_impl_item( }) => { let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); quote! { - type #ident #impl_generics = >::#ident #ty_generics #where_clause; + type #ident #impl_generics = ::#ident #ty_generics #where_clause; } } _ => Error::new_spanned(item, "unsupported item type").into_compile_error(), From 5f5cb14cc8a806bf4cb9dec65993a2540e81eecc Mon Sep 17 00:00:00 2001 From: bsh98 Date: Sun, 7 Jan 2024 01:24:10 -0800 Subject: [PATCH 3/4] minor cleanup --- trait-variant/src/variant.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/trait-variant/src/variant.rs b/trait-variant/src/variant.rs index 27d6b0f..f7f0d27 100644 --- a/trait-variant/src/variant.rs +++ b/trait-variant/src/variant.rs @@ -15,9 +15,9 @@ use syn::{ parse_macro_input, parse_quote, punctuated::Punctuated, token::Plus, - Error, FnArg, Ident, ItemTrait, Pat, PatType, Result, ReturnType, Signature, Token, TraitBound, - TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, TypeGenerics, TypeImplTrait, - TypeParamBound, + Error, FnArg, GenericParam, Ident, ItemTrait, Pat, PatType, Result, ReturnType, Signature, + Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, TypeGenerics, + TypeImplTrait, TypeParam, TypeParamBound, }; struct Attrs { @@ -168,13 +168,16 @@ fn mk_blanket_impl(attrs: &Attrs, tr: &ItemTrait) -> TokenStream { .items .iter() .map(|item| blanket_impl_item(item, variant, orig_ty_generics)); - let mut blanket_generics = tr.generics.to_owned(); + let blanket_bound: TypeParam = + parse_quote!(TraitVariantBlanketType: #variant #orig_ty_generics); + let blanket = &blanket_bound.ident.clone(); + let mut blanket_generics = tr.generics.clone(); blanket_generics .params - .push(parse_quote!(TraitVariantBlanketType: #variant #orig_ty_generics)); + .push(GenericParam::Type(blanket_bound)); let (blanket_impl_generics, _ty, blanket_where_clause) = &blanket_generics.split_for_impl(); quote! { - impl #blanket_impl_generics #orig #orig_ty_generics for TraitVariantBlanketType #blanket_where_clause + impl #blanket_impl_generics #orig #orig_ty_generics for #blanket #blanket_where_clause { #(#items)* } From 2d8fe98a0177f5db0397cfb39de3536274e30169 Mon Sep 17 00:00:00 2001 From: bsh98 Date: Sun, 7 Jan 2024 10:16:41 -0800 Subject: [PATCH 4/4] add better example --- trait-variant/examples/variant.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/trait-variant/examples/variant.rs b/trait-variant/examples/variant.rs index f175bb7..04bcc6a 100644 --- a/trait-variant/examples/variant.rs +++ b/trait-variant/examples/variant.rs @@ -6,7 +6,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::{future::Future, ops::Add}; +use std::{fmt::Display, future::Future}; #[trait_variant::make(IntFactory: Send)] pub trait LocalIntFactory { @@ -37,9 +37,10 @@ where const CONST: usize = 3; type F; type A; - type B: Add; + type B: FromIterator; async fn take(&self, s: S); + fn build(&self, items: impl Iterator) -> Self::B; } fn main() {}