Skip to content

Commit f1e171e

Browse files
authored
Merge pull request #26 from bsh98/fix/generics
Fix associated type generic bounds not in where clause
2 parents db73d60 + 2d8fe98 commit f1e171e

File tree

2 files changed

+27
-57
lines changed

2 files changed

+27
-57
lines changed

trait-variant/examples/variant.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
// option. This file may not be copied, modified, or distributed
77
// except according to those terms.
88

9-
use std::future::Future;
9+
use std::{fmt::Display, future::Future};
1010

1111
#[trait_variant::make(IntFactory: Send)]
1212
pub trait LocalIntFactory {
@@ -36,8 +36,11 @@ where
3636
{
3737
const CONST: usize = 3;
3838
type F;
39+
type A<const ANOTHER_CONST: u8>;
40+
type B<T: Display>: FromIterator<T>;
3941

4042
async fn take(&self, s: S);
43+
fn build<T: Display>(&self, items: impl Iterator<Item = T>) -> Self::B<T>;
4144
}
4245

4346
fn main() {}

trait-variant/src/variant.rs

+23-56
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@
99
use std::iter;
1010

1111
use proc_macro2::TokenStream;
12-
use quote::{quote, ToTokens};
12+
use quote::quote;
1313
use syn::{
1414
parse::{Parse, ParseStream},
15-
parse_macro_input,
15+
parse_macro_input, parse_quote,
1616
punctuated::Punctuated,
17-
token::{Comma, Plus},
18-
Error, FnArg, GenericParam, Generics, Ident, ItemTrait, Lifetime, Pat, PatType, Result,
19-
ReturnType, Signature, Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn,
20-
TraitItemType, Type, TypeImplTrait, TypeParamBound,
17+
token::Plus,
18+
Error, FnArg, GenericParam, Ident, ItemTrait, Pat, PatType, Result, ReturnType, Signature,
19+
Token, TraitBound, TraitItem, TraitItemConst, TraitItemFn, TraitItemType, Type, TypeGenerics,
20+
TypeImplTrait, TypeParam, TypeParamBound,
2121
};
2222

2323
struct Attrs {
@@ -162,59 +162,32 @@ fn transform_item(item: &TraitItem, bounds: &Vec<TypeParamBound>) -> TraitItem {
162162

163163
fn mk_blanket_impl(attrs: &Attrs, tr: &ItemTrait) -> TokenStream {
164164
let orig = &tr.ident;
165-
let generics = &tr.generics.params;
166-
let mut generic_names = tr
167-
.generics
168-
.params
169-
.iter()
170-
.map(|generic| match generic {
171-
GenericParam::Lifetime(lt) => GenericParamName::Lifetime(&lt.lifetime),
172-
GenericParam::Type(ty) => GenericParamName::Type(&ty.ident),
173-
GenericParam::Const(co) => GenericParamName::Const(&co.ident),
174-
})
175-
.collect::<Punctuated<_, Comma>>();
176-
let trailing_comma = if !generic_names.is_empty() {
177-
generic_names.push_punct(Comma::default());
178-
quote! { , }
179-
} else {
180-
quote! {}
181-
};
182165
let variant = &attrs.variant.name;
166+
let (_impl, orig_ty_generics, _where) = &tr.generics.split_for_impl();
183167
let items = tr
184168
.items
185169
.iter()
186-
.map(|item| blanket_impl_item(item, variant, &generic_names));
187-
let where_clauses = tr.generics.where_clause.as_ref().map(|wh| &wh.predicates);
170+
.map(|item| blanket_impl_item(item, variant, orig_ty_generics));
171+
let blanket_bound: TypeParam =
172+
parse_quote!(TraitVariantBlanketType: #variant #orig_ty_generics);
173+
let blanket = &blanket_bound.ident.clone();
174+
let mut blanket_generics = tr.generics.clone();
175+
blanket_generics
176+
.params
177+
.push(GenericParam::Type(blanket_bound));
178+
let (blanket_impl_generics, _ty, blanket_where_clause) = &blanket_generics.split_for_impl();
188179
quote! {
189-
impl<#generics #trailing_comma TraitVariantBlanketType> #orig<#generic_names>
190-
for TraitVariantBlanketType
191-
where TraitVariantBlanketType: #variant<#generic_names>, #where_clauses
180+
impl #blanket_impl_generics #orig #orig_ty_generics for #blanket #blanket_where_clause
192181
{
193182
#(#items)*
194183
}
195184
}
196185
}
197186

198-
enum GenericParamName<'s> {
199-
Lifetime(&'s Lifetime),
200-
Type(&'s Ident),
201-
Const(&'s Ident),
202-
}
203-
204-
impl ToTokens for GenericParamName<'_> {
205-
fn to_tokens(&self, tokens: &mut TokenStream) {
206-
match self {
207-
GenericParamName::Lifetime(lt) => lt.to_tokens(tokens),
208-
GenericParamName::Type(ty) => ty.to_tokens(tokens),
209-
GenericParamName::Const(co) => co.to_tokens(tokens),
210-
}
211-
}
212-
}
213-
214187
fn blanket_impl_item(
215188
item: &TraitItem,
216189
variant: &Ident,
217-
generic_names: &Punctuated<GenericParamName<'_>, Comma>,
190+
trait_ty_generics: &TypeGenerics<'_>,
218191
) -> TokenStream {
219192
// impl<T> IntFactory for T where T: SendIntFactory {
220193
// const NAME: &'static str = <Self as SendIntFactory>::NAME;
@@ -231,7 +204,7 @@ fn blanket_impl_item(
231204
..
232205
}) => {
233206
quote! {
234-
const #ident #generics: #ty = <Self as #variant<#generic_names>>::#ident;
207+
const #ident #generics: #ty = <Self as #variant #trait_ty_generics>::#ident;
235208
}
236209
}
237210
TraitItem::Fn(TraitItemFn { sig, .. }) => {
@@ -251,22 +224,16 @@ fn blanket_impl_item(
251224
};
252225
quote! {
253226
#sig {
254-
<Self as #variant<#generic_names>>::#ident(#(#args),*)#maybe_await
227+
<Self as #variant #trait_ty_generics>::#ident(#(#args),*)#maybe_await
255228
}
256229
}
257230
}
258231
TraitItem::Type(TraitItemType {
259-
ident,
260-
generics:
261-
Generics {
262-
params,
263-
where_clause,
264-
..
265-
},
266-
..
232+
ident, generics, ..
267233
}) => {
234+
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
268235
quote! {
269-
type #ident<#params> = <Self as #variant<#generic_names>>::#ident<#params> #where_clause;
236+
type #ident #impl_generics = <Self as #variant #trait_ty_generics>::#ident #ty_generics #where_clause;
270237
}
271238
}
272239
_ => Error::new_spanned(item, "unsupported item type").into_compile_error(),

0 commit comments

Comments
 (0)