Attributes on generic formals and split_for_impl
diff --git a/src/generics.rs b/src/generics.rs
index 3d7bd86..0a1dbec 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -9,7 +9,18 @@
     pub where_clause: WhereClause,
 }
 
+#[cfg(feature = "printing")]
+/// Returned by `Generics::split_for_impl`.
+#[derive(Debug)]
+pub struct ImplGenerics<'a>(&'a Generics);
+
+#[cfg(feature = "printing")]
+/// Returned by `Generics::split_for_impl`.
+#[derive(Debug)]
+pub struct TyGenerics<'a>(&'a Generics);
+
 impl Generics {
+    #[cfg(feature = "printing")]
     /// Split a type's generics into the pieces required for impl'ing a trait
     /// for that type.
     ///
@@ -29,50 +40,8 @@
     /// # ;
     /// # }
     /// ```
-    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)
+    pub fn split_for_impl(&self) -> (ImplGenerics, TyGenerics, &WhereClause) {
+        (ImplGenerics(self), TyGenerics(self), &self.where_clause)
     }
 }
 
@@ -96,6 +65,7 @@
 /// A lifetime definition, e.g. `'a: 'b+'c+'d`
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct LifetimeDef {
+    pub attrs: Vec<Attribute>,
     pub lifetime: Lifetime,
     pub bounds: Vec<Lifetime>,
 }
@@ -103,6 +73,7 @@
 impl LifetimeDef {
     pub fn new<T: Into<Ident>>(t: T) -> Self {
         LifetimeDef {
+            attrs: Vec::new(),
             lifetime: Lifetime::new(t),
             bounds: Vec::new(),
         }
@@ -111,6 +82,7 @@
 
 #[derive(Debug, Clone, Eq, PartialEq)]
 pub struct TyParam {
+    pub attrs: Vec<Attribute>,
     pub ident: Ident,
     pub bounds: Vec<TyParamBound>,
     pub default: Option<Ty>,
@@ -180,6 +152,7 @@
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
+    use attr::parsing::outer_attr;
     use ident::parsing::ident;
     use ty::parsing::{ty, poly_trait_ref};
 
@@ -213,12 +186,14 @@
     ));
 
     named!(pub lifetime_def -> LifetimeDef, do_parse!(
+        attrs: many0!(outer_attr) >>
         life: lifetime >>
         bounds: opt_vec!(preceded!(
             punct!(":"),
             separated_nonempty_list!(punct!("+"), lifetime)
         )) >>
         (LifetimeDef {
+            attrs: attrs,
             lifetime: life,
             bounds: bounds,
         })
@@ -233,6 +208,7 @@
     )));
 
     named!(ty_param -> TyParam, do_parse!(
+        attrs: many0!(outer_attr) >>
         id: ident >>
         bounds: opt_vec!(preceded!(
             punct!(":"),
@@ -243,6 +219,7 @@
             ty
         )) >>
         (TyParam {
+            attrs: attrs,
             ident: id,
             bounds: bounds,
             default: default,
@@ -300,6 +277,7 @@
 #[cfg(feature = "printing")]
 mod printing {
     use super::*;
+    use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
     impl ToTokens for Generics {
@@ -318,6 +296,50 @@
         }
     }
 
+    impl<'a> ToTokens for ImplGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            let has_lifetimes = !self.0.lifetimes.is_empty();
+            let has_ty_params = !self.0.ty_params.is_empty();
+            if has_lifetimes || has_ty_params {
+                tokens.append("<");
+                tokens.append_separated(&self.0.lifetimes, ",");
+                // Leave off the type parameter defaults
+                for (i, ty_param) in self.0.ty_params.iter().enumerate() {
+                    if i > 0 || has_lifetimes {
+                        tokens.append(",");
+                    }
+                    tokens.append_all(ty_param.attrs.outer());
+                    ty_param.ident.to_tokens(tokens);
+                    if !ty_param.bounds.is_empty() {
+                        tokens.append(":");
+                        tokens.append_separated(&ty_param.bounds, "+");
+                    }
+                }
+                tokens.append(">");
+            }
+        }
+    }
+
+    impl<'a> ToTokens for TyGenerics<'a> {
+        fn to_tokens(&self, tokens: &mut Tokens) {
+            let has_lifetimes = !self.0.lifetimes.is_empty();
+            let has_ty_params = !self.0.ty_params.is_empty();
+            if has_lifetimes || has_ty_params {
+                tokens.append("<");
+                // Leave off the lifetime bounds and attributes
+                let lifetimes = self.0.lifetimes.iter().map(|ld| &ld.lifetime);
+                tokens.append_separated(lifetimes, ",");
+                if has_lifetimes && has_ty_params {
+                    tokens.append(",");
+                }
+                // Leave off the type parameter bounds, defaults, and attributes
+                let ty_params = self.0.ty_params.iter().map(|tp| &tp.ident);
+                tokens.append_separated(ty_params, ",");
+                tokens.append(">");
+            }
+        }
+    }
+
     impl ToTokens for Lifetime {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.ident.to_tokens(tokens);
@@ -326,6 +348,7 @@
 
     impl ToTokens for LifetimeDef {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.lifetime.to_tokens(tokens);
             if !self.bounds.is_empty() {
                 tokens.append(":");
@@ -336,6 +359,7 @@
 
     impl ToTokens for TyParam {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            tokens.append_all(self.attrs.outer());
             self.ident.to_tokens(tokens);
             if !self.bounds.is_empty() {
                 tokens.append(":");
diff --git a/src/lib.rs b/src/lib.rs
index 40d4825..f331a0b 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -36,6 +36,8 @@
 mod generics;
 pub use generics::{Generics, Lifetime, LifetimeDef, TraitBoundModifier, TyParam, TyParamBound,
                    WhereBoundPredicate, WhereClause, WherePredicate, WhereRegionPredicate};
+#[cfg(feature = "printing")]
+pub use generics::{ImplGenerics, TyGenerics};
 
 #[cfg(feature = "full")]
 mod krate;