Helper function split_impl_generics
diff --git a/src/generics.rs b/src/generics.rs
index bc96319..851a209 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -9,6 +9,61 @@
pub where_clause: WhereClause,
}
+impl Generics {
+ /// Split a type's generics into the pieces required for impl'ing a trait
+ /// for that type.
+ ///
+ /// ```
+ /// # extern crate syn;
+ /// # #[macro_use]
+ /// # extern crate quote;
+ /// # fn main() {
+ /// # let generics: syn::Generics = Default::default();
+ /// # let name = syn::Ident::new("MyType");
+ /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+ /// quote! {
+ /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
+ /// // ...
+ /// }
+ /// }
+ /// # ;
+ /// # }
+ /// ```
+ pub fn split_for_impl(&self) -> (Generics, Generics, WhereClause) {
+ // Remove where clause and type parameter defaults.
+ let impl_generics = Generics {
+ lifetimes: self.lifetimes.clone(),
+ ty_params: self.ty_params.iter().map(|ty_param| {
+ TyParam {
+ ident: ty_param.ident.clone(),
+ bounds: ty_param.bounds.clone(),
+ default: None,
+ }}).collect(),
+ where_clause: WhereClause::none(),
+ };
+
+ // Remove where clause, type parameter defaults, and bounds.
+ let ty_generics = Generics {
+ lifetimes: self.lifetimes.iter().map(|lifetime_def| {
+ LifetimeDef {
+ lifetime: lifetime_def.lifetime.clone(),
+ bounds: Vec::new(),
+ }}).collect(),
+ ty_params: self.ty_params.iter().map(|ty_param| {
+ TyParam {
+ ident: ty_param.ident.clone(),
+ bounds: Vec::new(),
+ default: None,
+ }}).collect(),
+ where_clause: WhereClause::none(),
+ };
+
+ let where_clause = self.where_clause.clone();
+
+ (impl_generics, ty_generics, where_clause)
+ }
+}
+
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Lifetime {
pub ident: Ident,
@@ -69,6 +124,14 @@
pub predicates: Vec<WherePredicate>,
}
+impl WhereClause {
+ pub fn none() -> Self {
+ WhereClause {
+ predicates: Vec::new(),
+ }
+ }
+}
+
/// A single predicate in a `where` clause
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum WherePredicate {
diff --git a/tests/test_generics.rs b/tests/test_generics.rs
new file mode 100644
index 0000000..c28f044
--- /dev/null
+++ b/tests/test_generics.rs
@@ -0,0 +1,113 @@
+extern crate syn;
+use syn::*;
+
+fn simple_path(name: &'static str) -> Path {
+ Path {
+ global: false,
+ segments: vec![
+ PathSegment {
+ ident: Ident::new(name),
+ parameters: PathParameters::none(),
+ },
+ ],
+ }
+}
+
+#[test]
+fn test_split_for_impl() {
+ // <'a, 'b: 'a, T: 'a = ()> where T: Debug
+ let generics = Generics {
+ lifetimes: vec![
+ LifetimeDef {
+ lifetime: Lifetime::new("'a"),
+ bounds: Vec::new(),
+ },
+ LifetimeDef {
+ lifetime: Lifetime::new("'b"),
+ bounds: vec![
+ Lifetime::new("'a"),
+ ],
+ },
+ ],
+ ty_params: vec![
+ TyParam {
+ ident: Ident::new("T"),
+ bounds: vec![
+ TyParamBound::Region(Lifetime::new("'a")),
+ ],
+ default: Some(Ty::Tup(Vec::new())),
+ },
+ ],
+ where_clause: WhereClause {
+ predicates: vec![
+ WherePredicate::BoundPredicate(WhereBoundPredicate {
+ bound_lifetimes: Vec::new(),
+ bounded_ty: Ty::Path(None, simple_path("T")),
+ bounds: vec![
+ TyParamBound::Trait(
+ PolyTraitRef {
+ bound_lifetimes: Vec::new(),
+ trait_ref: simple_path("Debug"),
+ },
+ TraitBoundModifier::None,
+ ),
+ ],
+ }),
+ ],
+ },
+ };
+
+ let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
+
+ // <'a, 'b: 'a, T: 'a>
+ let expected_impl_generics = Generics {
+ lifetimes: vec![
+ LifetimeDef {
+ lifetime: Lifetime::new("'a"),
+ bounds: Vec::new(),
+ },
+ LifetimeDef {
+ lifetime: Lifetime::new("'b"),
+ bounds: vec![
+ Lifetime::new("'a"),
+ ],
+ },
+ ],
+ ty_params: vec![
+ TyParam {
+ ident: Ident::new("T"),
+ bounds: vec![
+ TyParamBound::Region(Lifetime::new("'a")),
+ ],
+ default: None,
+ },
+ ],
+ where_clause: WhereClause::none(),
+ };
+
+ // <'a, 'b, T>
+ let expected_ty_generics = Generics {
+ lifetimes: vec![
+ LifetimeDef {
+ lifetime: Lifetime::new("'a"),
+ bounds: Vec::new(),
+ },
+ LifetimeDef {
+ lifetime: Lifetime::new("'b"),
+ bounds: Vec::new(),
+ },
+ ],
+ ty_params: vec![
+ TyParam {
+ ident: Ident::new("T"),
+ bounds: Vec::new(),
+ default: None,
+ },
+ ],
+ where_clause: WhereClause::none(),
+ };
+
+ assert_eq!(impl_generics, expected_impl_generics);
+ assert_eq!(ty_generics, expected_ty_generics);
+ assert_eq!(where_clause, generics.where_clause);
+}