Polish Punctuated api
diff --git a/src/attr.rs b/src/attr.rs
index 5cb0fd0..96d96e5 100644
--- a/src/attr.rs
+++ b/src/attr.rs
@@ -188,9 +188,9 @@
             None => return None,
         };
         if let Some(comma) = prev_comma {
-            nested_meta_items.push_trailing(comma);
+            nested_meta_items.push_punct(comma);
         }
-        nested_meta_items.push(nested);
+        nested_meta_items.push_item(nested);
         tts = rest;
     }
 
diff --git a/src/expr.rs b/src/expr.rs
index 3cf9fa6..bf4bdb8 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -2677,7 +2677,7 @@
                 self.elems.to_tokens(tokens);
                 // If we only have one argument, we need a trailing comma to
                 // distinguish ExprTuple from ExprParen.
-                if self.elems.len() == 1 && !self.elems.trailing_delim() {
+                if self.elems.len() == 1 && !self.elems.trailing_punct() {
                     <Token![,]>::default().to_tokens(tokens);
                 }
             })
diff --git a/src/punctuated.rs b/src/punctuated.rs
index e8e6bd7..dc8c4ea 100644
--- a/src/punctuated.rs
+++ b/src/punctuated.rs
@@ -52,6 +52,12 @@
         }
     }
 
+    pub fn iter_mut(&mut self) -> IterMut<T, P> {
+        IterMut {
+            inner: self.inner.iter_mut(),
+        }
+    }
+
     pub fn elements(&self) -> Elements<T, P> {
         Elements {
             inner: self.inner.iter(),
@@ -70,12 +76,12 @@
         }
     }
 
-    pub fn push(&mut self, token: T) {
+    pub fn push_item(&mut self, item: T) {
         assert!(self.empty_or_trailing());
-        self.inner.push((token, None));
+        self.inner.push((item, None));
     }
 
-    pub fn push_trailing(&mut self, punctuation: P) {
+    pub fn push_punct(&mut self, punctuation: P) {
         assert!(!self.is_empty());
         let last = self.inner.last_mut().unwrap();
         assert!(last.1.is_none());
@@ -86,19 +92,31 @@
         self.inner.pop().map(|(t, d)| Element::new(t, d))
     }
 
-    pub fn trailing_delim(&self) -> bool {
+    pub fn trailing_punct(&self) -> bool {
         self.inner.last().map(|last| last.1.is_some()).unwrap_or(false)
     }
 
     /// Returns true if either this `Punctuated` is empty, or it has a trailing
     /// punctuation.
     ///
-    /// Equivalent to `punctuated.is_empty() || punctuated.trailing_delim()`.
+    /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
     pub fn empty_or_trailing(&self) -> bool {
         self.inner.last().map(|last| last.1.is_some()).unwrap_or(true)
     }
 }
 
+impl<T, P> Punctuated<T, P>
+where
+    P: Default,
+{
+    pub fn push(&mut self, item: T) {
+        if !self.empty_or_trailing() {
+            self.push_punct(Default::default());
+        }
+        self.push_item(item);
+    }
+}
+
 #[cfg(feature = "extra-traits")]
 impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@@ -145,6 +163,15 @@
     }
 }
 
+impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
+    type Item = &'a mut T;
+    type IntoIter = IterMut<'a, T, P>;
+
+    fn into_iter(self) -> Self::IntoIter {
+        Punctuated::iter_mut(self)
+    }
+}
+
 impl<T, P> Default for Punctuated<T, P> {
     fn default() -> Self {
         Punctuated::new()
@@ -220,6 +247,18 @@
     }
 }
 
+pub struct IterMut<'a, T: 'a, P: 'a> {
+    inner: slice::IterMut<'a, (T, Option<P>)>,
+}
+
+impl<'a, T, P> Iterator for IterMut<'a, T, P> {
+    type Item = &'a mut T;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.inner.next().map(|pair| &mut pair.0)
+    }
+}
+
 pub enum Element<T, P> {
     Punctuated(T, P),
     End(T),
@@ -349,7 +388,7 @@
                         return parse_error();
                     }
                     input = i;
-                    res.push(o);
+                    res.push_item(o);
 
                     // get the separator first
                     while let Ok((s, i2)) = P::parse(input) {
@@ -362,8 +401,8 @@
                             if i3 == i2 {
                                 break;
                             }
-                            res.push_trailing(s);
-                            res.push(o3);
+                            res.push_punct(s);
+                            res.push_item(o3);
                             input = i3;
                         } else {
                             break;
@@ -371,7 +410,7 @@
                     }
                     if terminated {
                         if let Ok((sep, after)) = P::parse(input) {
-                            res.push_trailing(sep);
+                            res.push_punct(sep);
                             input = after;
                         }
                     }
@@ -393,7 +432,7 @@
         P: ToTokens,
     {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            tokens.append_all(self.iter())
+            tokens.append_all(self.elements())
         }
     }
 
diff --git a/src/ty.rs b/src/ty.rs
index b504b47..c8d7e87 100644
--- a/src/ty.rs
+++ b/src/ty.rs
@@ -156,7 +156,7 @@
             leading_colon: None,
             segments: Punctuated::new(),
         };
-        path.segments.push(segment.into());
+        path.segments.push_item(segment.into());
         path
     }
 }
@@ -582,7 +582,7 @@
                 let (pos, as_, path) = match path {
                     Some((as_, mut path)) => {
                         let pos = path.segments.len();
-                        path.segments.push_trailing(colon2);
+                        path.segments.push_punct(colon2);
                         path.segments.extend(rest.into_elements());
                         (pos, Some(as_), path)
                     }
@@ -657,7 +657,7 @@
                 |
                 syn!(TypeParamBound) => {|x| {
                     let mut bounds = Punctuated::new();
-                    bounds.push(x);
+                    bounds.push_item(x);
                     bounds
                 }}
             ) >>