Merge pull request #594 from dtolnay/span

Pretend to have `span` field on punctuation with single span
diff --git a/src/ident.rs b/src/ident.rs
index adc545f..f5a76a1 100644
--- a/src/ident.rs
+++ b/src/ident.rs
@@ -81,6 +81,6 @@
 
 impl From<Token![_]> for Ident {
     fn from(token: Token![_]) -> Ident {
-        Ident::new("_", token.spans[0])
+        Ident::new("_", token.span)
     }
 }
diff --git a/src/token.rs b/src/token.rs
index f1a2331..04d6967 100644
--- a/src/token.rs
+++ b/src/token.rs
@@ -95,6 +95,7 @@
 use std::fmt::{self, Debug};
 #[cfg(feature = "extra-traits")]
 use std::hash::{Hash, Hasher};
+use std::ops::{Deref, DerefMut};
 
 #[cfg(feature = "parsing")]
 use proc_macro2::Delimiter;
@@ -106,6 +107,7 @@
 #[cfg(feature = "printing")]
 use quote::{ToTokens, TokenStreamExt};
 
+use self::private::WithSpan;
 #[cfg(feature = "parsing")]
 use buffer::Cursor;
 #[cfg(feature = "parsing")]
@@ -136,9 +138,18 @@
     fn display() -> &'static str;
 }
 
-#[cfg(feature = "parsing")]
 mod private {
+    use proc_macro2::Span;
+
+    #[cfg(feature = "parsing")]
     pub trait Sealed {}
+
+    /// Support writing `token.span` rather than `token.spans[0]` on tokens that
+    /// hold a single span.
+    #[repr(C)]
+    pub struct WithSpan {
+        pub span: Span,
+    }
 }
 
 #[cfg(feature = "parsing")]
@@ -304,10 +315,31 @@
     };
 }
 
+macro_rules! impl_deref_if_len_is_1 {
+    ($name:ident/1) => {
+        impl Deref for $name {
+            type Target = WithSpan;
+
+            fn deref(&self) -> &Self::Target {
+                unsafe { &*(self as *const Self as *const WithSpan) }
+            }
+        }
+
+        impl DerefMut for $name {
+            fn deref_mut(&mut self) -> &mut Self::Target {
+                unsafe { &mut *(self as *mut Self as *mut WithSpan) }
+            }
+        }
+    };
+
+    ($name:ident/$len:tt) => {};
+}
+
 macro_rules! define_punctuation_structs {
     ($($token:tt pub struct $name:ident/$len:tt #[$doc:meta])*) => {
         $(
             #[cfg_attr(feature = "clone-impls", derive(Copy, Clone))]
+            #[repr(C)]
             #[$doc]
             ///
             /// Don't try to remember the name of this type -- use the [`Token!`]
@@ -355,6 +387,8 @@
             impl Hash for $name {
                 fn hash<H: Hasher>(&self, _state: &mut H) {}
             }
+
+            impl_deref_if_len_is_1!($name/$len);
         )*
     };
 }
@@ -469,7 +503,7 @@
 #[cfg(feature = "printing")]
 impl ToTokens for Underscore {
     fn to_tokens(&self, tokens: &mut TokenStream) {
-        tokens.append(Ident::new("_", self.spans[0]));
+        tokens.append(Ident::new("_", self.span));
     }
 }