Skip to content

Commit

Permalink
Fix issue with lifetimes being removed instead of simply being elided
Browse files Browse the repository at this point in the history
  • Loading branch information
althonos committed May 30, 2021
1 parent 1c8d859 commit 36dd907
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 19 deletions.
18 changes: 17 additions & 1 deletion src/derive/box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {

// we must however remove the generic type bounds, to avoid repeating them
let mut trait_generic_names = trait_generics.clone();
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params);
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params)?;

impl_generics.params.push(syn::GenericParam::Type(
parse_quote!(#generic_type: #trait_ident #trait_generic_names),
Expand Down Expand Up @@ -191,5 +191,21 @@ mod tests {
)
);
}

#[test]
fn generics_lifetime() {
let trait_ = parse_quote!(
trait MyTrait<'a, 'b: 'a, T: 'static + Send> {}
);
let derived = super::super::derive(&trait_).unwrap();

assert_eq!(
derived,
parse_quote!(
#[automatically_derived]
impl<'a, 'b: 'a, T: 'static + Send, MT: MyTrait<'a, 'b, T>> MyTrait<'a, 'b, T> for Box<MT> {}
)
);
}
}
}
21 changes: 20 additions & 1 deletion src/derive/mut.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {

// we must however remove the generic type bounds, to avoid repeating them
let mut trait_generic_names = trait_generics.clone();
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params);
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params)?;

impl_generics.params.push(syn::GenericParam::Type(
parse_quote!(#generic_type: #trait_ident #trait_generic_names + ?Sized),
Expand Down Expand Up @@ -155,5 +155,24 @@ mod tests {
)
);
}

#[test]
fn generics_lifetime() {
let trait_ = parse_quote!(
trait Trait<'a, 'b: 'a, T: 'static + Send> {}
);
let derived = super::super::derive(&trait_).unwrap();

assert_eq!(
derived,
parse_quote!(
#[automatically_derived]
impl<'a, 'b: 'a, T: 'static + Send, T_: Trait<'a, 'b, T> + ?Sized>
Trait<'a, 'b, T> for &mut T_
{
}
)
);
}
}
}
21 changes: 20 additions & 1 deletion src/derive/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {

// we must however remove the generic type bounds, to avoid repeating them
let mut trait_generic_names = trait_generics.clone();
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params);
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params)?;

impl_generics.params.push(syn::GenericParam::Type(
parse_quote!(#generic_type: #trait_ident #trait_generic_names + ?Sized),
Expand Down Expand Up @@ -168,5 +168,24 @@ mod tests {
)
);
}

#[test]
fn generics_lifetime() {
let trait_ = parse_quote!(
trait MyTrait<'a, 'b: 'a, T: 'static + Send> {}
);
let derived = super::super::derive(&trait_).unwrap();

assert_eq!(
derived,
parse_quote!(
#[automatically_derived]
impl<'a, 'b: 'a, T: 'static + Send, MT: MyTrait<'a, 'b, T> + ?Sized>
MyTrait<'a, 'b, T> for std::rc::Rc<MT>
{
}
)
);
}
}
}
21 changes: 20 additions & 1 deletion src/derive/ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ pub fn derive(trait_: &syn::ItemTrait) -> syn::Result<syn::ItemImpl> {

// we must however remove the generic type bounds, to avoid repeating them
let mut trait_generic_names = trait_generics.clone();
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params);
trait_generic_names.params = generics_declaration_to_generics(&trait_generics.params)?;

impl_generics.params.push(syn::GenericParam::Type(
parse_quote!(#generic_type: #trait_ident #trait_generic_names + ?Sized),
Expand Down Expand Up @@ -168,5 +168,24 @@ mod tests {
)
);
}

#[test]
fn generics_lifetime() {
let trait_ = parse_quote!(
trait MyTrait<'a, 'b: 'a, T: 'static + Send> {}
);
let derived = super::super::derive(&trait_).unwrap();

assert_eq!(
derived,
parse_quote!(
#[automatically_derived]
impl<'a, 'b: 'a, T: 'static + Send, MT: MyTrait<'a, 'b, T> + ?Sized>
MyTrait<'a, 'b, T> for &MT
{
}
)
);
}
}
}
35 changes: 20 additions & 15 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,24 +145,29 @@ pub fn trait_to_generic_ident(trait_: &syn::ItemTrait) -> syn::Ident {
/// Given a generic section `<T: 'static + Send>`, get simply `<T>`.
pub fn generics_declaration_to_generics(
generics: &Punctuated<GenericParam, Token![,]>,
) -> Punctuated<GenericParam, Token![,]> {
) -> syn::Result<Punctuated<GenericParam, Token![,]>> {
generics
.iter()
.filter_map(|gen| match gen {
syn::GenericParam::Type(t) => Some(t),
syn::GenericParam::Lifetime(_) => None,
syn::GenericParam::Const(_) => None,
})
.map(|t| syn::TypeParam {
attrs: t.attrs.clone(),
ident: t.ident.clone(),
colon_token: None,
bounds: syn::punctuated::Punctuated::new(),
eq_token: None,
default: None,
.map(|gen| match gen {
syn::GenericParam::Type(t) => Ok(syn::GenericParam::Type(syn::TypeParam {
attrs: t.attrs.clone(),
ident: t.ident.clone(),
colon_token: None,
bounds: Punctuated::new(),
eq_token: None,
default: None,
})),
syn::GenericParam::Lifetime(l) => Ok(syn::GenericParam::Lifetime(syn::LifetimeDef {
attrs: l.attrs.clone(),
lifetime: l.lifetime.clone(),
colon_token: None,
bounds: Punctuated::new(),
})),
syn::GenericParam::Const(c) => {
Err(syn::Error::new(c.span(), "cannot handle const generics"))
}
})
.map(|t| syn::GenericParam::Type(t))
.collect::<_>()
.collect()
}

#[cfg(test)]
Expand Down

0 comments on commit 36dd907

Please sign in to comment.