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;
diff --git a/tests/test_generics.rs b/tests/test_generics.rs
index c28f044..5c51630 100644
--- a/tests/test_generics.rs
+++ b/tests/test_generics.rs
@@ -1,28 +1,21 @@
 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(),
-            },
-        ],
-    }
-}
+#[macro_use]
+extern crate quote;
 
 #[test]
 fn test_split_for_impl() {
-    // <'a, 'b: 'a, T: 'a = ()> where T: Debug
+    // <'a, 'b: 'a, #[may_dangle] T: 'a = ()> where T: Debug
     let generics = Generics {
         lifetimes: vec![
             LifetimeDef {
+                attrs: Vec::new(),
                 lifetime: Lifetime::new("'a"),
                 bounds: Vec::new(),
             },
             LifetimeDef {
+                attrs: Vec::new(),
                 lifetime: Lifetime::new("'b"),
                 bounds: vec![
                     Lifetime::new("'a"),
@@ -31,6 +24,13 @@
         ],
         ty_params: vec![
             TyParam {
+                attrs: vec![
+                    Attribute {
+                        style: AttrStyle::Outer,
+                        value: MetaItem::Word("may_dangle".into()),
+                        is_sugared_doc: false,
+                    },
+                ],
                 ident: Ident::new("T"),
                 bounds: vec![
                     TyParamBound::Region(Lifetime::new("'a")),
@@ -42,12 +42,12 @@
             predicates: vec![
                 WherePredicate::BoundPredicate(WhereBoundPredicate {
                     bound_lifetimes: Vec::new(),
-                    bounded_ty: Ty::Path(None, simple_path("T")),
+                    bounded_ty: Ty::Path(None, "T".into()),
                     bounds: vec![
                         TyParamBound::Trait(
                             PolyTraitRef {
                                 bound_lifetimes: Vec::new(),
-                                trait_ref: simple_path("Debug"),
+                                trait_ref: "Debug".into(),
                             },
                             TraitBoundModifier::None,
                         ),
@@ -59,55 +59,15 @@
 
     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(),
+    let tokens = quote! {
+        impl #impl_generics MyTrait for Test #ty_generics #where_clause {}
     };
 
-    // <'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(),
-    };
+    let expected = concat!(
+        "impl < 'a , 'b : 'a , # [ may_dangle ] T : 'a > ",
+        "MyTrait for Test < 'a , 'b , T > ",
+        "where T : Debug { }"
+    );
 
-    assert_eq!(impl_generics, expected_impl_generics);
-    assert_eq!(ty_generics, expected_ty_generics);
-    assert_eq!(where_clause, generics.where_clause);
+    assert_eq!(expected, tokens.to_string());
 }
diff --git a/tests/test_macro_input.rs b/tests/test_macro_input.rs
index 1c25a99..8a0c395 100644
--- a/tests/test_macro_input.rs
+++ b/tests/test_macro_input.rs
@@ -110,11 +110,13 @@
             lifetimes: Vec::new(),
             ty_params: vec![
                 TyParam {
+                    attrs: Vec::new(),
                     ident: "T".into(),
                     bounds: Vec::new(),
                     default: None,
                 },
                 TyParam {
+                    attrs: Vec::new(),
                     ident: "E".into(),
                     bounds: Vec::new(),
                     default: None,