Make ToTokens more lenient when generating tokens for invalid ASTs
diff --git a/src/data.rs b/src/data.rs
index 937de27..4821a7a 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -212,8 +212,10 @@
             tokens.append_all(&self.attrs);
             self.ident.to_tokens(tokens);
             self.data.to_tokens(tokens);
-            self.eq_token.to_tokens(tokens);
-            self.discriminant.to_tokens(tokens);
+            if let Some(ref disc) = self.discriminant {
+                self.eq_token.unwrap_or_default().to_tokens(tokens);
+                disc.to_tokens(tokens);
+            }
         }
     }
 
@@ -239,8 +241,10 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(&self.attrs);
             self.vis.to_tokens(tokens);
-            self.ident.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
+            if let Some(ref ident) = self.ident {
+                ident.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.ty.to_tokens(tokens);
         }
     }
@@ -264,6 +268,8 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.pub_token.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
+                // XXX: If we have a path which is not "self" or "super",
+                // automatically add the "in" token.
                 self.in_token.to_tokens(tokens);
                 self.path.to_tokens(tokens);
             });
diff --git a/src/expr.rs b/src/expr.rs
index db3fb55..3d4fbb3 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -527,7 +527,7 @@
             pub hi: Box<Expr>,
             pub limits: RangeLimits,
         }),
-        /// `[a, b, ..i, y, z]` is represented as:
+        /// `[a, b, i.., y, z]` is represented as:
         pub Slice(PatSlice {
             pub front: Delimited<Pat, tokens::Comma>,
             pub middle: Option<Box<Pat>>,
@@ -622,6 +622,16 @@
     }
 }
 
+#[cfg(any(feature = "parsing", feature = "printing"))]
+#[cfg(feature = "full")]
+fn arm_requires_comma(arm: &Arm) -> bool {
+    if let ExprKind::Block(ExprBlock { unsafety: Unsafety::Normal, .. }) = arm.body.node {
+        false
+    } else {
+        true
+    }
+}
+
 #[cfg(feature = "parsing")]
 pub mod parsing {
     use super::*;
@@ -1497,15 +1507,6 @@
     }
 
     #[cfg(feature = "full")]
-    fn arm_requires_comma(arm: &Arm) -> bool {
-        if let ExprKind::Block(ExprBlock { unsafety: Unsafety::Normal, .. }) = arm.body.node {
-            false
-        } else {
-            true
-        }
-    }
-
-    #[cfg(feature = "full")]
     impl Synom for Arm {
         named!(parse -> Self, do_parse!(
             attrs: many0!(call!(Attribute::parse_outer)) >>
@@ -2265,6 +2266,19 @@
     use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
+    /// If the given expression is a bare `ExprStruct`, wraps it in parenthesis
+    /// before appending it to `Tokens`.
+    #[cfg(feature = "full")]
+    fn wrap_bare_struct(tokens: &mut Tokens, e: &Expr) {
+        if let ExprKind::Struct(_) = e.node {
+            tokens::Paren::default().surround(tokens, |tokens| {
+                e.to_tokens(tokens);
+            });
+        } else {
+            e.to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for Expr {
         #[cfg(feature = "full")]
         fn to_tokens(&self, tokens: &mut Tokens) {
@@ -2298,7 +2312,15 @@
                 InPlaceKind::In(ref _in) => {
                     _in.to_tokens(tokens);
                     self.place.to_tokens(tokens);
-                    self.value.to_tokens(tokens);
+                    // NOTE: The second operand must be in a block, add one if
+                    // it is not present.
+                    if let ExprKind::Block(_) = self.value.node {
+                        self.value.to_tokens(tokens);
+                    } else {
+                        tokens::Brace::default().surround(tokens, |tokens| {
+                            self.value.to_tokens(tokens);
+                        })
+                    }
                 }
             }
         }
@@ -2328,10 +2350,12 @@
             self.expr.to_tokens(tokens);
             self.dot_token.to_tokens(tokens);
             self.method.to_tokens(tokens);
-            self.colon2_token.to_tokens(tokens);
-            self.lt_token.to_tokens(tokens);
-            self.typarams.to_tokens(tokens);
-            self.gt_token.to_tokens(tokens);
+            if !self.typarams.is_empty() {
+                self.colon2_token.unwrap_or_default().to_tokens(tokens);
+                self.lt_token.unwrap_or_default().to_tokens(tokens);
+                self.typarams.to_tokens(tokens);
+                self.gt_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
             });
@@ -2343,6 +2367,15 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.paren_token.surround(tokens, |tokens| {
                 self.args.to_tokens(tokens);
+                // If we only have one argument, we need a trailing comma to
+                // distinguish ExprTup from ExprParen.
+                if self.args.len() == 1 && !self.args.trailing_delim() {
+                    tokens::Comma::default().to_tokens(tokens);
+                }
+                // XXX: Not sure how to handle this, but we never parse it yet.
+                // Is this for an expression like (0,)? Can't we use the
+                // trailing delimiter on Delimited for that? (,) isn't a valid
+                // expression as far as I know.
                 self.lone_comma.to_tokens(tokens);
             })
         }
@@ -2380,13 +2413,37 @@
     }
 
     #[cfg(feature = "full")]
+    fn maybe_wrap_else(tokens: &mut Tokens,
+                       else_token: &Option<tokens::Else>,
+                       if_false: &Option<Box<Expr>>)
+    {
+        if let Some(ref if_false) = *if_false {
+            else_token.unwrap_or_default().to_tokens(tokens);
+
+            // If we are not one of the valid expressions to exist in an else
+            // clause, wrap ourselves in a block.
+            match if_false.node {
+                ExprKind::If(_) |
+                ExprKind::IfLet(_) |
+                ExprKind::Block(_) => {
+                    if_false.to_tokens(tokens);
+                }
+                _ => {
+                    tokens::Brace::default().surround(tokens, |tokens| {
+                        if_false.to_tokens(tokens);
+                    });
+                }
+            }
+        }
+    }
+
+    #[cfg(feature = "full")]
     impl ToTokens for ExprIf {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.if_token.to_tokens(tokens);
-            self.cond.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.cond);
             self.if_true.to_tokens(tokens);
-            self.else_token.to_tokens(tokens);
-            self.if_false.to_tokens(tokens);
+            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
         }
     }
 
@@ -2397,20 +2454,21 @@
             self.let_token.to_tokens(tokens);
             self.pat.to_tokens(tokens);
             self.eq_token.to_tokens(tokens);
-            self.expr.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
             self.if_true.to_tokens(tokens);
-            self.else_token.to_tokens(tokens);
-            self.if_false.to_tokens(tokens);
+            maybe_wrap_else(tokens, &self.else_token, &self.if_false);
         }
     }
 
     #[cfg(feature = "full")]
     impl ToTokens for ExprWhile {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.label.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
+            if self.label.is_some() {
+                self.label.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.while_token.to_tokens(tokens);
-            self.cond.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.cond);
             self.body.to_tokens(tokens);
         }
     }
@@ -2418,13 +2476,15 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprWhileLet {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.label.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
+            if self.label.is_some() {
+                self.label.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.while_token.to_tokens(tokens);
             self.let_token.to_tokens(tokens);
             self.pat.to_tokens(tokens);
             self.eq_token.to_tokens(tokens);
-            self.expr.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
             self.body.to_tokens(tokens);
         }
     }
@@ -2432,12 +2492,14 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprForLoop {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.label.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
+            if self.label.is_some() {
+                self.label.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.for_token.to_tokens(tokens);
             self.pat.to_tokens(tokens);
             self.in_token.to_tokens(tokens);
-            self.expr.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
             self.body.to_tokens(tokens);
         }
     }
@@ -2445,8 +2507,10 @@
     #[cfg(feature = "full")]
     impl ToTokens for ExprLoop {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.label.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
+            if self.label.is_some() {
+                self.label.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+            }
             self.loop_token.to_tokens(tokens);
             self.body.to_tokens(tokens);
         }
@@ -2456,9 +2520,17 @@
     impl ToTokens for ExprMatch {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.match_token.to_tokens(tokens);
-            self.expr.to_tokens(tokens);
+            wrap_bare_struct(tokens, &self.expr);
             self.brace_token.surround(tokens, |tokens| {
-                tokens.append_all(&self.arms);
+                for (i,  arm) in self.arms.iter().enumerate() {
+                    arm.to_tokens(tokens);
+                    // Ensure that we have a comma after a non-block arm, except
+                    // for the last one.
+                    let is_last = i == self.arms.len() - 1;
+                    if !is_last && arm_requires_comma(arm) && arm.comma.is_none() {
+                        tokens::Comma::default().to_tokens(tokens);
+                    }
+                }
             });
         }
     }
@@ -2531,6 +2603,8 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.expr.to_tokens(tokens);
             self.dot_token.to_tokens(tokens);
+            // XXX: I don't think we can do anything if someone shoves a
+            // nonsense Lit in here.
             self.field.to_tokens(tokens);
         }
     }
@@ -2608,8 +2682,10 @@
             self.path.to_tokens(tokens);
             self.brace_token.surround(tokens, |tokens| {
                 self.fields.to_tokens(tokens);
-                self.dot2_token.to_tokens(tokens);
-                self.rest.to_tokens(tokens);
+                if self.rest.is_some() {
+                    self.dot2_token.unwrap_or_default().to_tokens(tokens);
+                    self.rest.to_tokens(tokens);
+                }
             })
         }
     }
@@ -2653,8 +2729,11 @@
     impl ToTokens for FieldValue {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.ident.to_tokens(tokens);
+            // XXX: Override self.is_shorthand if expr is not an IdentExpr with
+            // the ident self.ident?
             if !self.is_shorthand {
-                self.colon_token.to_tokens(tokens);
+                self.colon_token.unwrap_or_default()
+                    .to_tokens(tokens);
                 self.expr.to_tokens(tokens);
             }
         }
@@ -2665,8 +2744,10 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(&self.attrs);
             self.pats.to_tokens(tokens);
-            self.if_token.to_tokens(tokens);
-            self.guard.to_tokens(tokens);
+            if self.guard.is_some() {
+                self.if_token.unwrap_or_default().to_tokens(tokens);
+                self.guard.to_tokens(tokens);
+            }
             self.rocket_token.to_tokens(tokens);
             self.body.to_tokens(tokens);
             self.comma.to_tokens(tokens);
@@ -2685,8 +2766,10 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.mode.to_tokens(tokens);
             self.ident.to_tokens(tokens);
-            self.at_token.to_tokens(tokens);
-            self.subpat.to_tokens(tokens);
+            if self.subpat.is_some() {
+                self.at_token.unwrap_or_default().to_tokens(tokens);
+                self.subpat.to_tokens(tokens);
+            }
         }
     }
 
@@ -2696,6 +2779,10 @@
             self.path.to_tokens(tokens);
             self.brace_token.surround(tokens, |tokens| {
                 self.fields.to_tokens(tokens);
+                // NOTE: We need a comma before the dot2 token if it is present.
+                if !self.fields.empty_or_trailing() && self.dot2_token.is_some() {
+                    tokens::Comma::default().to_tokens(tokens);
+                }
                 self.dot2_token.to_tokens(tokens);
             });
         }
@@ -2722,13 +2809,17 @@
             self.paren_token.surround(tokens, |tokens| {
                 for (i, token) in self.pats.iter().enumerate() {
                     if Some(i) == self.dots_pos {
-                        self.dot2_token.to_tokens(tokens);
-                        self.comma_token.to_tokens(tokens);
+                        self.dot2_token.unwrap_or_default().to_tokens(tokens);
+                        self.comma_token.unwrap_or_default().to_tokens(tokens);
                     }
                     token.to_tokens(tokens);
                 }
 
                 if Some(self.pats.len()) == self.dots_pos {
+                    // Ensure there is a comma before the .. token.
+                    if !self.pats.empty_or_trailing() {
+                        tokens::Comma::default().to_tokens(tokens);
+                    }
                     self.dot2_token.to_tokens(tokens);
                 }
             });
@@ -2771,12 +2862,34 @@
     #[cfg(feature = "full")]
     impl ToTokens for PatSlice {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            // XXX: This is a mess, and it will be so easy to screw it up. How
+            // do we make this correct itself better?
             self.bracket_token.surround(tokens, |tokens| {
                 self.front.to_tokens(tokens);
-                self.middle.to_tokens(tokens);
-                self.dot2_token.to_tokens(tokens);
-                self.comma_token.to_tokens(tokens);
-                self.back.to_tokens(tokens);
+
+                // If we need a comma before the middle or standalone .. token,
+                // then make sure it's present.
+                if !self.front.empty_or_trailing() &&
+                    (self.middle.is_some() || self.dot2_token.is_some())
+                {
+                    tokens::Comma::default().to_tokens(tokens);
+                }
+
+                // If we have an identifier, we always need a .. token.
+                if self.middle.is_some() {
+                    self.middle.to_tokens(tokens);
+                    self.dot2_token.unwrap_or_default().to_tokens(tokens);
+                } else if self.dot2_token.is_some() {
+                    self.dot2_token.to_tokens(tokens);
+                }
+
+                // Make sure we have a comma before the back half.
+                if !self.back.is_empty() {
+                    self.comma_token.unwrap_or_default().to_tokens(tokens);
+                    self.back.to_tokens(tokens);
+                } else {
+                    self.comma_token.to_tokens(tokens);
+                }
             })
         }
     }
@@ -2794,9 +2907,10 @@
     #[cfg(feature = "full")]
     impl ToTokens for FieldPat {
         fn to_tokens(&self, tokens: &mut Tokens) {
+            // XXX: Override is_shorthand if it was wrong?
             if !self.is_shorthand {
                 self.ident.to_tokens(tokens);
-                self.colon_token.to_tokens(tokens);
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
             }
             self.pat.to_tokens(tokens);
         }
@@ -2870,10 +2984,14 @@
             tokens.append_all(self.attrs.outer());
             self.let_token.to_tokens(tokens);
             self.pat.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
-            self.ty.to_tokens(tokens);
-            self.eq_token.to_tokens(tokens);
-            self.init.to_tokens(tokens);
+            if self.ty.is_some() {
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+                self.ty.to_tokens(tokens);
+            }
+            if self.init.is_some() {
+                self.eq_token.unwrap_or_default().to_tokens(tokens);
+                self.init.to_tokens(tokens);
+            }
             self.semi_token.to_tokens(tokens);
         }
     }
diff --git a/src/generics.rs b/src/generics.rs
index 7cb6c82..b169f8a 100644
--- a/src/generics.rs
+++ b/src/generics.rs
@@ -357,54 +357,85 @@
     use attr::FilterAttrs;
     use quote::{Tokens, ToTokens};
 
+    /// Returns true if the generics object has no lifetimes or ty_params.
+    fn empty_normal_generics(generics: &Generics) -> bool {
+        generics.lifetimes.is_empty() && generics.ty_params.is_empty()
+    }
+
+    /// We need a comma between the lifetimes list and the ty_params list if
+    /// there are more than 0 lifetimes, the lifetimes list didn't have a
+    /// trailing delimiter, and there are more than 0 type parameters. This is a
+    /// helper method for adding that comma.
+    fn maybe_add_lifetime_params_comma(tokens: &mut Tokens, generics: &Generics) {
+        // We may need to require a trailing comma if we have any ty_params.
+        if !generics.lifetimes.empty_or_trailing() && !generics.ty_params.is_empty() {
+            tokens::Comma::default().to_tokens(tokens);
+        }
+    }
+
     impl ToTokens for Generics {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.lt_token.to_tokens(tokens);
+            if empty_normal_generics(self) {
+                return;
+            }
+
+            self.lt_token.unwrap_or_default().to_tokens(tokens);
             self.lifetimes.to_tokens(tokens);
+            maybe_add_lifetime_params_comma(tokens, self);
             self.ty_params.to_tokens(tokens);
-            self.gt_token.to_tokens(tokens);
+            self.gt_token.unwrap_or_default().to_tokens(tokens);
         }
     }
 
     impl<'a> ToTokens for ImplGenerics<'a> {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.0.lt_token.to_tokens(tokens);
+            if empty_normal_generics(&self.0) {
+                return;
+            }
+
+            self.0.lt_token.unwrap_or_default().to_tokens(tokens);
             self.0.lifetimes.to_tokens(tokens);
+            maybe_add_lifetime_params_comma(tokens, &self.0);
             for param in self.0.ty_params.iter() {
                  // Leave off the type parameter defaults
                 let item = param.item();
                 tokens.append_all(item.attrs.outer());
                 item.ident.to_tokens(tokens);
-                item.colon_token.to_tokens(tokens);
-                item.bounds.to_tokens(tokens);
+                if !item.bounds.is_empty() {
+                    item.colon_token.unwrap_or_default().to_tokens(tokens);
+                    item.bounds.to_tokens(tokens);
+                }
                 param.delimiter().to_tokens(tokens);
             }
-            self.0.gt_token.to_tokens(tokens);
+            self.0.gt_token.unwrap_or_default().to_tokens(tokens);
         }
     }
 
     impl<'a> ToTokens for TyGenerics<'a> {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.0.lt_token.to_tokens(tokens);
+            if empty_normal_generics(&self.0) {
+                return;
+            }
+
+            self.0.lt_token.unwrap_or_default().to_tokens(tokens);
             // Leave off the lifetime bounds and attributes
             for param in self.0.lifetimes.iter() {
                 param.item().lifetime.to_tokens(tokens);
                 param.delimiter().to_tokens(tokens);
             }
+            maybe_add_lifetime_params_comma(tokens, &self.0);
             // Leave off the type parameter defaults
             for param in self.0.ty_params.iter() {
                 param.item().ident.to_tokens(tokens);
                 param.delimiter().to_tokens(tokens);
             }
-            self.0.gt_token.to_tokens(tokens);
+            self.0.gt_token.unwrap_or_default().to_tokens(tokens);
         }
     }
 
     impl<'a> ToTokens for Turbofish<'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 {
+            if !empty_normal_generics(&self.0) {
                 tokens::Colon2::default().to_tokens(tokens);
                 TyGenerics(self.0).to_tokens(tokens);
             }
@@ -424,8 +455,10 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
             self.lifetime.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
-            self.bounds.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
         }
     }
 
@@ -433,10 +466,14 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             tokens.append_all(self.attrs.outer());
             self.ident.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
-            self.bounds.to_tokens(tokens);
-            self.eq_token.to_tokens(tokens);
-            self.default.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
+            if self.default.is_some() {
+                self.eq_token.unwrap_or_default().to_tokens(tokens);
+                self.default.to_tokens(tokens);
+            }
         }
     }
 
@@ -463,8 +500,10 @@
 
     impl ToTokens for WhereClause {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            self.where_token.to_tokens(tokens);
-            self.predicates.to_tokens(tokens);
+            if !self.predicates.is_empty() {
+                self.where_token.unwrap_or_default().to_tokens(tokens);
+                self.predicates.to_tokens(tokens);
+            }
         }
     }
 
@@ -480,8 +519,10 @@
     impl ToTokens for WhereRegionPredicate {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.lifetime.to_tokens(tokens);
-            self.colon_token.to_tokens(tokens);
-            self.bounds.to_tokens(tokens);
+            if !self.bounds.is_empty() {
+                self.colon_token.unwrap_or_default().to_tokens(tokens);
+                self.bounds.to_tokens(tokens);
+            }
         }
     }
 
diff --git a/src/item.rs b/src/item.rs
index 618c20b..dca8543 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -1366,8 +1366,9 @@
                             tokens.append_all(self.attrs.inner());
                             tokens.append_all(items);
                         });
+                    } else {
+                        item.semi.unwrap_or_default().to_tokens(tokens);
                     }
-                    item.semi.to_tokens(tokens);
                 }
                 ItemKind::ForeignMod(ref item) => {
                     item.abi.to_tokens(tokens);
@@ -1408,12 +1409,13 @@
                         VariantData::Tuple(..) => {
                             item.data.to_tokens(tokens);
                             item.generics.where_clause.to_tokens(tokens);
+                            item.semi_token.unwrap_or_default().to_tokens(tokens);
                         }
                         VariantData::Unit => {
                             item.generics.where_clause.to_tokens(tokens);
+                            item.semi_token.unwrap_or_default().to_tokens(tokens);
                         }
                     }
-                    item.semi_token.to_tokens(tokens);
                 }
                 ItemKind::Union(ref item) => {
                     item.vis.to_tokens(tokens);
@@ -1421,6 +1423,8 @@
                     item.ident.to_tokens(tokens);
                     item.generics.to_tokens(tokens);
                     item.generics.where_clause.to_tokens(tokens);
+                    // XXX: Should we handle / complain when using a
+                    // non-VariantData::Struct Variant in Union?
                     item.data.to_tokens(tokens);
                 }
                 ItemKind::Trait(ref item) => {
@@ -1429,8 +1433,10 @@
                     item.trait_token.to_tokens(tokens);
                     item.ident.to_tokens(tokens);
                     item.generics.to_tokens(tokens);
-                    item.colon_token.to_tokens(tokens);
-                    item.supertraits.to_tokens(tokens);
+                    if !item.supertraits.is_empty() {
+                        item.colon_token.unwrap_or_default().to_tokens(tokens);
+                        item.supertraits.to_tokens(tokens);
+                    }
                     item.generics.where_clause.to_tokens(tokens);
                     item.brace_token.surround(tokens, |tokens| {
                         tokens.append_all(&item.items);
@@ -1475,8 +1481,10 @@
     impl ToTokens for PathSimple {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.path.to_tokens(tokens);
-            self.as_token.to_tokens(tokens);
-            self.rename.to_tokens(tokens);
+            if self.rename.is_some() {
+                self.as_token.unwrap_or_default().to_tokens(tokens);
+                self.rename.to_tokens(tokens);
+            }
         }
     }
 
@@ -1501,8 +1509,10 @@
     impl ToTokens for PathListItem {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.name.to_tokens(tokens);
-            self.as_token.to_tokens(tokens);
-            self.rename.to_tokens(tokens);
+            if self.rename.is_some() {
+                self.as_token.unwrap_or_default().to_tokens(tokens);
+                self.rename.to_tokens(tokens);
+            }
         }
     }
 
@@ -1531,15 +1541,17 @@
                             });
                         }
                         None => {
-                            item.semi_token.to_tokens(tokens);
+                            item.semi_token.unwrap_or_default().to_tokens(tokens);
                         }
                     }
                 }
                 TraitItemKind::Type(ref item) => {
                     item.type_token.to_tokens(tokens);
                     item.ident.to_tokens(tokens);
-                    item.colon_token.to_tokens(tokens);
-                    item.bounds.to_tokens(tokens);
+                    if !item.bounds.is_empty() {
+                        item.colon_token.unwrap_or_default().to_tokens(tokens);
+                        item.bounds.to_tokens(tokens);
+                    }
                     if let Some((ref eq_token, ref default)) = item.default {
                         eq_token.to_tokens(tokens);
                         default.to_tokens(tokens);
@@ -1638,7 +1650,13 @@
             self.0.generics.to_tokens(tokens);
             self.0.paren_token.surround(tokens, |tokens| {
                 self.0.inputs.to_tokens(tokens);
-                self.0.dot_tokens.to_tokens(tokens);
+
+                if self.0.variadic {
+                    if !self.0.inputs.empty_or_trailing() {
+                        tokens::Comma::default().to_tokens(tokens);
+                    }
+                    self.0.dot_tokens.unwrap_or_default().to_tokens(tokens);
+                }
             });
             self.0.output.to_tokens(tokens);
             self.0.generics.where_clause.to_tokens(tokens);
diff --git a/src/mac.rs b/src/mac.rs
index 55b33cf..6645c00 100644
--- a/src/mac.rs
+++ b/src/mac.rs
@@ -177,6 +177,7 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.path.to_tokens(tokens);
             self.bang_token.to_tokens(tokens);
+            self.ident.to_tokens(tokens);
             tokens.append_all(&self.tokens);
         }
     }
diff --git a/src/ty.rs b/src/ty.rs
index 83aecd4..cc9d2c8 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -258,7 +258,8 @@
     pub struct QSelf {
         pub lt_token: tokens::Lt,
         pub ty: Box<Ty>,
-        pub position: Option<(tokens::As, usize)>,
+        pub position: usize,
+        pub as_token: Option<tokens::As>,
         pub gt_token: tokens::Gt,
     }
 }
@@ -547,7 +548,7 @@
             colon2: syn!(Colon2) >>
             rest: call!(Delimited::parse_separated_nonempty) >>
             ({
-                let (pos, path) = match path {
+                let (pos, as_, path) = match path {
                     Some((as_, mut path)) => {
                         let pos = path.segments.len();
                         if !path.segments.is_empty() && !path.segments.trailing_delim() {
@@ -556,10 +557,10 @@
                         for item in rest {
                             path.segments.push(item);
                         }
-                        (Some((as_, pos)), path)
+                        (pos, Some(as_), path)
                     }
                     None => {
-                        (None, Path {
+                        (0, None, Path {
                             leading_colon: Some(colon2),
                             segments: rest,
                         })
@@ -569,6 +570,7 @@
                     lt_token: lt,
                     ty: Box::new(this),
                     position: pos,
+                    as_token: as_,
                     gt_token: gt,
                 }), path)
             })
@@ -835,8 +837,12 @@
     impl ToTokens for TyPtr {
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.star_token.to_tokens(tokens);
-            self.const_token.to_tokens(tokens);
-            self.ty.mutability.to_tokens(tokens);
+            match self.ty.mutability {
+                Mutability::Mutable(ref tok) => tok.to_tokens(tokens),
+                Mutability::Immutable => {
+                    self.const_token.unwrap_or_default().to_tokens(tokens);
+                }
+            }
             self.ty.ty.to_tokens(tokens);
         }
     }
@@ -866,6 +872,7 @@
         fn to_tokens(&self, tokens: &mut Tokens) {
             self.paren_token.surround(tokens, |tokens| {
                 self.tys.to_tokens(tokens);
+                // XXX: I don't think (,) is a thing.
                 self.lone_comma.to_tokens(tokens);
             })
         }
@@ -885,9 +892,16 @@
             };
             qself.lt_token.to_tokens(tokens);
             qself.ty.to_tokens(tokens);
+
+            // XXX: Gross.
+            let pos = if qself.position > 0 && qself.position >= self.1.segments.len() {
+                self.1.segments.len() - 1
+            } else {
+                qself.position
+            };
             let mut segments = self.1.segments.iter();
-            if let Some((ref as_token, pos)) = qself.position {
-                as_token.to_tokens(tokens);
+            if pos > 0 {
+                qself.as_token.unwrap_or_default().to_tokens(tokens);
                 self.1.leading_colon.to_tokens(tokens);
                 for (i, segment) in (&mut segments).take(pos).enumerate() {
                     if i + 1 == pos {
@@ -984,7 +998,21 @@
             self.turbofish.to_tokens(tokens);
             self.lt_token.to_tokens(tokens);
             self.lifetimes.to_tokens(tokens);
+            if !self.lifetimes.empty_or_trailing() && !self.types.is_empty() {
+                tokens::Comma::default().to_tokens(tokens);
+            }
             self.types.to_tokens(tokens);
+            if (
+                // If we have no trailing delimiter after a non-empty types list, or
+                !self.types.empty_or_trailing() ||
+                // If we have no trailing delimiter after a non-empty lifetimes
+                // list before an empty types list, and
+                (self.types.is_empty() && !self.lifetimes.empty_or_trailing())) &&
+                // We have some bindings, then we need a comma.
+                !self.bindings.is_empty()
+            {
+                tokens::Comma::default().to_tokens(tokens);
+            }
             self.bindings.to_tokens(tokens);
             self.gt_token.to_tokens(tokens);
         }
@@ -1034,6 +1062,9 @@
             self.fn_token.to_tokens(tokens);
             self.paren_token.surround(tokens, |tokens| {
                 self.inputs.to_tokens(tokens);
+                if self.variadic.is_some() && !self.inputs.empty_or_trailing() {
+                    tokens::Comma::default().to_tokens(tokens);
+                }
                 self.variadic.to_tokens(tokens);
             });
             self.output.to_tokens(tokens);