Merge pull request #86 from alexcrichton/work-everywhere

Fix the `nightly` feature outside of rustc
diff --git a/.travis.yml b/.travis.yml
index 78942c4..cbf61e0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -11,10 +11,10 @@
         - pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
       script:
         - cargo test
-        - cargo build --features nightly
-        - cargo build --no-default-features
+        - cargo test --features nightly
+        - cargo test --no-default-features
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
-        - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build --features nightly
+        - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --features nightly
         - RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo doc --no-deps
       after_success:
         - travis-cargo --only nightly doc-upload
diff --git a/src/lib.rs b/src/lib.rs
index 91b3add..11ec549 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -48,8 +48,6 @@
 
 #[cfg(feature = "proc-macro")]
 extern crate proc_macro;
-
-#[cfg(not(feature = "nightly"))]
 extern crate unicode_xid;
 
 use std::fmt;
@@ -59,12 +57,11 @@
 use std::str::FromStr;
 
 #[macro_use]
-#[cfg(not(feature = "nightly"))]
 mod strnom;
+mod stable;
 
-#[path = "stable.rs"]
 #[cfg(not(feature = "nightly"))]
-mod imp;
+use stable as imp;
 #[path = "unstable.rs"]
 #[cfg(feature = "nightly")]
 mod imp;
@@ -88,6 +85,13 @@
         }
     }
 
+    fn _new_stable(inner: stable::TokenStream) -> TokenStream {
+        TokenStream {
+            inner: inner.into(),
+            _marker: marker::PhantomData,
+        }
+    }
+
     pub fn empty() -> TokenStream {
         TokenStream::_new(imp::TokenStream::empty())
     }
@@ -201,6 +205,13 @@
         }
     }
 
+    fn _new_stable(inner: stable::Span) -> Span {
+        Span {
+            inner: inner.into(),
+            _marker: marker::PhantomData,
+        }
+    }
+
     pub fn call_site() -> Span {
         Span::_new(imp::Span::call_site())
     }
@@ -525,6 +536,13 @@
         }
     }
 
+    fn _new_stable(inner: stable::Literal) -> Literal {
+        Literal {
+            inner: inner.into(),
+            _marker: marker::PhantomData,
+        }
+    }
+
     int_literals! {
         u8_suffixed => u8,
         u16_suffixed => u16,
diff --git a/src/stable.rs b/src/stable.rs
index 2fb422a..9222793 100644
--- a/src/stable.rs
+++ b/src/stable.rs
@@ -65,7 +65,7 @@
                 if skip_whitespace(input).len() != 0 {
                     Err(LexError)
                 } else {
-                    Ok(output.inner)
+                    Ok(output)
                 }
             }
             Err(LexError) => Err(LexError),
@@ -89,7 +89,7 @@
                         Delimiter::Bracket => ("[", "]"),
                         Delimiter::None => ("", ""),
                     };
-                    if tt.stream().inner.inner.len() == 0 {
+                    if tt.stream().into_iter().next().is_none() {
                         write!(f, "{} {}", start, end)?
                     } else {
                         write!(f, "{} {} {}", start, tt.stream(), end)?
@@ -167,24 +167,24 @@
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FileName(String);
 
-#[cfg(procmacro2_semver_exempt)]
+pub fn file_name(s: String) -> FileName {
+    FileName(s)
+}
+
 impl fmt::Display for FileName {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         self.0.fmt(f)
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, PartialEq, Eq)]
 pub struct SourceFile {
     name: FileName,
 }
 
-#[cfg(procmacro2_semver_exempt)]
 impl SourceFile {
     /// Get the path to this source file as a string.
     pub fn path(&self) -> &FileName {
@@ -197,14 +197,12 @@
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 impl AsRef<FileName> for SourceFile {
     fn as_ref(&self) -> &FileName {
         self.path()
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 impl fmt::Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.debug_struct("SourceFile")
@@ -214,7 +212,6 @@
     }
 }
 
-#[cfg(procmacro2_semver_exempt)]
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct LineColumn {
     pub line: usize,
@@ -660,7 +657,7 @@
     }
 }
 
-fn token_stream(mut input: Cursor) -> PResult<::TokenStream> {
+fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
     let mut trees = Vec::new();
     loop {
         let input_no_ws = skip_whitespace(input);
@@ -680,7 +677,7 @@
         trees.push(tt);
         input = a;
     }
-    Ok((input, ::TokenStream::_new(TokenStream { inner: trees })))
+    Ok((input, TokenStream { inner: trees }))
 }
 
 #[cfg(not(procmacro2_semver_exempt))]
@@ -689,7 +686,7 @@
     f: fn(Cursor<'a>) -> PResult<'a, T>,
 ) -> PResult<'a, (T, ::Span)> {
     let (a, b) = f(skip_whitespace(input))?;
-    Ok((a, ((b, ::Span::_new(Span {})))))
+    Ok((a, ((b, ::Span::_new_stable(Span {})))))
 }
 
 #[cfg(procmacro2_semver_exempt)]
@@ -701,7 +698,7 @@
     let lo = input.off;
     let (a, b) = f(input)?;
     let hi = a.off;
-    let span = ::Span::_new(Span { lo: lo, hi: hi });
+    let span = ::Span::_new_stable(Span { lo: lo, hi: hi });
     Ok((a, (b, span)))
 }
 
@@ -714,7 +711,7 @@
 named!(token_kind -> TokenTree, alt!(
     map!(group, TokenTree::Group)
     |
-    map!(literal, TokenTree::Literal) // must be before symbol
+    map!(literal, |l| TokenTree::Literal(::Literal::_new_stable(l))) // must be before symbol
     |
     symbol
     |
@@ -726,19 +723,19 @@
         punct!("("),
         token_stream,
         punct!(")")
-    ) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
+    ) => { |ts| Group::new(Delimiter::Parenthesis, ::TokenStream::_new_stable(ts)) }
     |
     delimited!(
         punct!("["),
         token_stream,
         punct!("]")
-    ) => { |ts| Group::new(Delimiter::Bracket, ts) }
+    ) => { |ts| Group::new(Delimiter::Bracket, ::TokenStream::_new_stable(ts)) }
     |
     delimited!(
         punct!("{"),
         token_stream,
         punct!("}")
-    ) => { |ts| Group::new(Delimiter::Brace, ts) }
+    ) => { |ts| Group::new(Delimiter::Brace, ::TokenStream::_new_stable(ts)) }
 ));
 
 fn symbol(mut input: Cursor) -> PResult<TokenTree> {
@@ -792,7 +789,7 @@
     "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
 ];
 
-fn literal(input: Cursor) -> PResult<::Literal> {
+fn literal(input: Cursor) -> PResult<Literal> {
     let input_no_ws = skip_whitespace(input);
 
     match literal_nocapture(input_no_ws) {
@@ -802,7 +799,7 @@
             let end = start + len;
             Ok((
                 a,
-                ::Literal::_new(Literal::_new(input.rest[start..end].to_string())),
+                Literal::_new(input.rest[start..end].to_string()),
             ))
         }
         Err(LexError) => Err(LexError),
diff --git a/src/strnom.rs b/src/strnom.rs
index f5dd145..e465b03 100644
--- a/src/strnom.rs
+++ b/src/strnom.rs
@@ -4,7 +4,7 @@
 
 use unicode_xid::UnicodeXID;
 
-use imp::LexError;
+use stable::LexError;
 
 #[derive(Copy, Clone, Eq, PartialEq)]
 pub struct Cursor<'a> {
diff --git a/src/unstable.rs b/src/unstable.rs
index 85698aa..d709f88 100644
--- a/src/unstable.rs
+++ b/src/unstable.rs
@@ -3,23 +3,63 @@
 use std::fmt;
 use std::iter;
 use std::str::FromStr;
+use std::panic;
 
 use proc_macro;
+use stable;
 
 use {Delimiter, Group, Op, Spacing, TokenTree};
 
 #[derive(Clone)]
-pub struct TokenStream(proc_macro::TokenStream);
+pub enum TokenStream {
+    Nightly(proc_macro::TokenStream),
+    Stable(stable::TokenStream),
+}
 
-pub struct LexError(proc_macro::LexError);
+pub enum LexError {
+    Nightly(proc_macro::LexError),
+    Stable(stable::LexError),
+}
+
+fn nightly_works() -> bool {
+    use std::sync::atomic::*;
+    static WORKS: AtomicUsize = ATOMIC_USIZE_INIT;
+
+    match WORKS.load(Ordering::SeqCst) {
+        1 => return false,
+        2 => return true,
+        _ => {}
+    }
+    let works = panic::catch_unwind(|| proc_macro::Span::call_site()).is_ok();
+    WORKS.store(works as usize + 1, Ordering::SeqCst);
+    works
+}
+
+fn mismatch() -> ! {
+    panic!("stable/nightly mismatch")
+}
 
 impl TokenStream {
     pub fn empty() -> TokenStream {
-        TokenStream(proc_macro::TokenStream::empty())
+        if nightly_works() {
+            TokenStream::Nightly(proc_macro::TokenStream::empty())
+        } else {
+            TokenStream::Stable(stable::TokenStream::empty())
+        }
     }
 
     pub fn is_empty(&self) -> bool {
-        self.0.is_empty()
+        match self {
+            TokenStream::Nightly(tts) => tts.is_empty(),
+            TokenStream::Stable(tts) => tts.is_empty(),
+        }
+    }
+
+    fn unwrap_nightly(self) -> proc_macro::TokenStream {
+        match self {
+            TokenStream::Nightly(s) => s,
+            TokenStream::Stable(_) => mismatch(),
+        }
     }
 }
 
@@ -27,30 +67,49 @@
     type Err = LexError;
 
     fn from_str(src: &str) -> Result<TokenStream, LexError> {
-        Ok(TokenStream(src.parse().map_err(LexError)?))
+        if nightly_works() {
+            Ok(TokenStream::Nightly(src.parse()?))
+        } else {
+            Ok(TokenStream::Stable(src.parse()?))
+        }
     }
 }
 
 impl fmt::Display for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        match self {
+            TokenStream::Nightly(tts) => tts.fmt(f),
+            TokenStream::Stable(tts) => tts.fmt(f),
+        }
     }
 }
 
 impl From<proc_macro::TokenStream> for TokenStream {
     fn from(inner: proc_macro::TokenStream) -> TokenStream {
-        TokenStream(inner)
+        TokenStream::Nightly(inner)
     }
 }
 
 impl From<TokenStream> for proc_macro::TokenStream {
     fn from(inner: TokenStream) -> proc_macro::TokenStream {
-        inner.0
+        match inner {
+            TokenStream::Nightly(inner) => inner,
+            TokenStream::Stable(inner) => inner.to_string().parse().unwrap(),
+        }
+    }
+}
+
+impl From<stable::TokenStream> for TokenStream {
+    fn from(inner: stable::TokenStream) -> TokenStream {
+        TokenStream::Stable(inner)
     }
 }
 
 impl From<TokenTree> for TokenStream {
     fn from(token: TokenTree) -> TokenStream {
+        if !nightly_works() {
+            return TokenStream::Stable(token.into())
+        }
         let tt: proc_macro::TokenTree = match token {
             TokenTree::Group(tt) => {
                 let delim = match tt.delimiter() {
@@ -60,8 +119,8 @@
                     Delimiter::None => proc_macro::Delimiter::None,
                 };
                 let span = tt.span();
-                let mut group = proc_macro::Group::new(delim, tt.stream.inner.0);
-                group.set_span(span.inner.0);
+                let mut group = proc_macro::Group::new(delim, tt.stream.inner.unwrap_nightly());
+                group.set_span(span.inner.unwrap_nightly());
                 group.into()
             }
             TokenTree::Op(tt) => {
@@ -70,43 +129,78 @@
                     Spacing::Alone => proc_macro::Spacing::Alone,
                 };
                 let mut op = proc_macro::Op::new(tt.op(), spacing);
-                op.set_span(tt.span().inner.0);
+                op.set_span(tt.span().inner.unwrap_nightly());
                 op.into()
             }
-            TokenTree::Term(tt) => tt.inner.term.into(),
-            TokenTree::Literal(tt) => tt.inner.lit.into(),
+            TokenTree::Term(tt) => tt.inner.unwrap_nightly().into(),
+            TokenTree::Literal(tt) => tt.inner.unwrap_nightly().into(),
         };
-        TokenStream(tt.into())
+        TokenStream::Nightly(tt.into())
     }
 }
 
 impl iter::FromIterator<TokenTree> for TokenStream {
-    fn from_iter<I: IntoIterator<Item = TokenTree>>(streams: I) -> Self {
-        let streams = streams.into_iter().map(TokenStream::from).flat_map(|t| t.0);
-        TokenStream(streams.collect::<proc_macro::TokenStream>())
+    fn from_iter<I: IntoIterator<Item = TokenTree>>(trees: I) -> Self {
+        if nightly_works() {
+            let trees = trees.into_iter()
+                .map(TokenStream::from)
+                .flat_map(|t| {
+                    match t {
+                        TokenStream::Nightly(s) => s,
+                        TokenStream::Stable(_) => mismatch(),
+                    }
+                });
+            TokenStream::Nightly(trees.collect())
+        } else {
+            TokenStream::Stable(trees.into_iter().collect())
+        }
     }
 }
 
 impl fmt::Debug for TokenStream {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        match self {
+            TokenStream::Nightly(tts) => tts.fmt(f),
+            TokenStream::Stable(tts) => tts.fmt(f),
+        }
+    }
+}
+
+impl From<proc_macro::LexError> for LexError {
+    fn from(e: proc_macro::LexError) -> LexError {
+        LexError::Nightly(e)
+    }
+}
+
+impl From<stable::LexError> for LexError {
+    fn from(e: stable::LexError) -> LexError {
+        LexError::Stable(e)
     }
 }
 
 impl fmt::Debug for LexError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        match self {
+            LexError::Nightly(e) => e.fmt(f),
+            LexError::Stable(e) => e.fmt(f),
+        }
     }
 }
 
-pub struct TokenTreeIter(proc_macro::token_stream::IntoIter);
+pub enum TokenTreeIter {
+    Nightly(proc_macro::token_stream::IntoIter),
+    Stable(stable::TokenTreeIter),
+}
 
 impl IntoIterator for TokenStream {
     type Item = TokenTree;
     type IntoIter = TokenTreeIter;
 
     fn into_iter(self) -> TokenTreeIter {
-        TokenTreeIter(self.0.into_iter())
+        match self {
+            TokenStream::Nightly(tts) => TokenTreeIter::Nightly(tts.into_iter()),
+            TokenStream::Stable(tts) => TokenTreeIter::Stable(tts.into_iter()),
+        }
     }
 }
 
@@ -114,7 +208,10 @@
     type Item = TokenTree;
 
     fn next(&mut self) -> Option<TokenTree> {
-        let token = self.0.next()?;
+        let token = match self {
+            TokenTreeIter::Nightly(iter) => iter.next()?,
+            TokenTreeIter::Stable(iter) => return iter.next(),
+        };
         Some(match token {
             proc_macro::TokenTree::Group(tt) => {
                 let delim = match tt.delimiter() {
@@ -123,9 +220,9 @@
                     proc_macro::Delimiter::Brace => Delimiter::Brace,
                     proc_macro::Delimiter::None => Delimiter::None,
                 };
-                let stream = ::TokenStream::_new(TokenStream(tt.stream()));
+                let stream = ::TokenStream::_new(TokenStream::Nightly(tt.stream()));
                 let mut g = Group::new(delim, stream);
-                g.set_span(::Span::_new(Span(tt.span())));
+                g.set_span(::Span::_new(Span::Nightly(tt.span())));
                 g.into()
             }
             proc_macro::TokenTree::Op(tt) => {
@@ -134,16 +231,19 @@
                     proc_macro::Spacing::Alone => Spacing::Alone,
                 };
                 let mut o = Op::new(tt.op(), spacing);
-                o.set_span(::Span::_new(Span(tt.span())));
+                o.set_span(::Span::_new(Span::Nightly(tt.span())));
                 o.into()
             }
-            proc_macro::TokenTree::Term(s) => ::Term::_new(Term { term: s }).into(),
-            proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal { lit: l }).into(),
+            proc_macro::TokenTree::Term(s) => ::Term::_new(Term::Nightly(s)).into(),
+            proc_macro::TokenTree::Literal(l) => ::Literal::_new(Literal::Nightly(l)).into(),
         })
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.0.size_hint()
+        match self {
+            TokenTreeIter::Nightly(tts) => tts.size_hint(),
+            TokenTreeIter::Stable(tts) => tts.size_hint(),
+        }
     }
 }
 
@@ -153,33 +253,35 @@
     }
 }
 
-#[derive(Clone, PartialEq, Eq)]
-pub struct FileName(String);
-
-impl fmt::Display for FileName {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
-    }
-}
+pub use stable::FileName;
 
 // NOTE: We have to generate our own filename object here because we can't wrap
 // the one provided by proc_macro.
 #[derive(Clone, PartialEq, Eq)]
-pub struct SourceFile(proc_macro::SourceFile, FileName);
+pub enum SourceFile {
+    Nightly(proc_macro::SourceFile, FileName),
+    Stable(stable::SourceFile),
+}
 
 impl SourceFile {
-    fn new(sf: proc_macro::SourceFile) -> Self {
-        let filename = FileName(sf.path().to_string());
-        SourceFile(sf, filename)
+    fn nightly(sf: proc_macro::SourceFile) -> Self {
+        let filename = stable::file_name(sf.path().to_string());
+        SourceFile::Nightly(sf, filename)
     }
 
     /// Get the path to this source file as a string.
     pub fn path(&self) -> &FileName {
-        &self.1
+        match self {
+            SourceFile::Nightly(_, f) => f,
+            SourceFile::Stable(a) => a.path(),
+        }
     }
 
     pub fn is_real(&self) -> bool {
-        self.0.is_real()
+        match self {
+            SourceFile::Nightly(a, _) => a.is_real(),
+            SourceFile::Stable(a) => a.is_real(),
+        }
     }
 }
 
@@ -191,7 +293,10 @@
 
 impl fmt::Debug for SourceFile {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        match self {
+            SourceFile::Nightly(a, _) => a.fmt(f),
+            SourceFile::Stable(a) => a.fmt(f),
+        }
     }
 }
 
@@ -201,104 +306,201 @@
 }
 
 #[derive(Copy, Clone)]
-pub struct Span(proc_macro::Span);
-
-impl From<proc_macro::Span> for ::Span {
-    fn from(proc_span: proc_macro::Span) -> ::Span {
-        ::Span::_new(Span(proc_span))
-    }
+pub enum Span {
+    Nightly(proc_macro::Span),
+    Stable(stable::Span),
 }
 
 impl Span {
     pub fn call_site() -> Span {
-        Span(proc_macro::Span::call_site())
+        if nightly_works() {
+            Span::Nightly(proc_macro::Span::call_site())
+        } else {
+            Span::Stable(stable::Span::call_site())
+        }
     }
 
     pub fn def_site() -> Span {
-        Span(proc_macro::Span::def_site())
+        if nightly_works() {
+            Span::Nightly(proc_macro::Span::def_site())
+        } else {
+            Span::Stable(stable::Span::def_site())
+        }
     }
 
     pub fn resolved_at(&self, other: Span) -> Span {
-        Span(self.0.resolved_at(other.0))
+        match (self, other) {
+            (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.resolved_at(b)),
+            (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.resolved_at(b)),
+            _ => mismatch(),
+        }
     }
 
     pub fn located_at(&self, other: Span) -> Span {
-        Span(self.0.located_at(other.0))
+        match (self, other) {
+            (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.located_at(b)),
+            (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.located_at(b)),
+            _ => mismatch(),
+        }
     }
 
     pub fn unstable(self) -> proc_macro::Span {
-        self.0
+        match self {
+            Span::Nightly(s) => s,
+            Span::Stable(_) => mismatch(),
+        }
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn source_file(&self) -> SourceFile {
-        SourceFile::new(self.0.source_file())
+        match self {
+            Span::Nightly(s) => SourceFile::nightly(s.source_file()),
+            Span::Stable(s) => SourceFile::Stable(s.source_file()),
+        }
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn start(&self) -> LineColumn {
-        let proc_macro::LineColumn { line, column } = self.0.start();
-        LineColumn { line, column }
+        match self {
+            Span::Nightly(s) => {
+                let proc_macro::LineColumn { line, column } = s.start();
+                LineColumn { line, column }
+            }
+            Span::Stable(s) => {
+                let stable::LineColumn { line, column } = s.start();
+                LineColumn { line, column }
+            }
+        }
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn end(&self) -> LineColumn {
-        let proc_macro::LineColumn { line, column } = self.0.end();
-        LineColumn { line, column }
+        match self {
+            Span::Nightly(s) => {
+                let proc_macro::LineColumn { line, column } = s.end();
+                LineColumn { line, column }
+            }
+            Span::Stable(s) => {
+                let stable::LineColumn { line, column } = s.end();
+                LineColumn { line, column }
+            }
+        }
     }
 
+    #[cfg(procmacro2_semver_exempt)]
     pub fn join(&self, other: Span) -> Option<Span> {
-        self.0.join(other.0).map(Span)
+        let ret = match (self, other) {
+            (Span::Nightly(a), Span::Nightly(b)) => Span::Nightly(a.join(b)?),
+            (Span::Stable(a), Span::Stable(b)) => Span::Stable(a.join(b)?),
+            _ => return None,
+        };
+        Some(ret)
     }
 
     pub fn eq(&self, other: &Span) -> bool {
-        self.0.eq(&other.0)
+        match (self, other) {
+            (Span::Nightly(a), Span::Nightly(b)) => a.eq(b),
+            (Span::Stable(a), Span::Stable(b)) => a.eq(b),
+            _ => false,
+        }
+    }
+
+    fn unwrap_nightly(self) -> proc_macro::Span {
+        match self {
+            Span::Nightly(s) => s,
+            Span::Stable(_) => mismatch(),
+        }
+    }
+}
+
+impl From<proc_macro::Span> for ::Span {
+    fn from(proc_span: proc_macro::Span) -> ::Span {
+        ::Span::_new(Span::Nightly(proc_span))
+    }
+}
+
+impl From<stable::Span> for Span {
+    fn from(inner: stable::Span) -> Span {
+        Span::Stable(inner)
     }
 }
 
 impl fmt::Debug for Span {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.0.fmt(f)
+        match self {
+            Span::Nightly(s) => s.fmt(f),
+            Span::Stable(s) => s.fmt(f),
+        }
     }
 }
 
 #[derive(Copy, Clone)]
-pub struct Term {
-    term: proc_macro::Term,
+pub enum Term {
+    Nightly(proc_macro::Term),
+    Stable(stable::Term),
 }
 
 impl Term {
     pub fn new(string: &str, span: Span) -> Term {
-        Term {
-            term: proc_macro::Term::new(string, span.0),
+        match span {
+            Span::Nightly(s) => Term::Nightly(proc_macro::Term::new(string, s)),
+            Span::Stable(s) => Term::Stable(stable::Term::new(string, s)),
         }
     }
 
     pub fn as_str(&self) -> &str {
-        self.term.as_str()
+        match self {
+            Term::Nightly(t) => t.as_str(),
+            Term::Stable(t) => t.as_str(),
+        }
     }
 
     pub fn span(&self) -> Span {
-        Span(self.term.span())
+        match self {
+            Term::Nightly(t) => Span::Nightly(t.span()),
+            Term::Stable(t) => Span::Stable(t.span()),
+        }
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.term.set_span(span.0);
+        match (self, span) {
+            (Term::Nightly(t), Span::Nightly(s)) => t.set_span(s),
+            (Term::Stable(t), Span::Stable(s)) => t.set_span(s),
+            _ => mismatch(),
+        }
+    }
+
+    fn unwrap_nightly(self) -> proc_macro::Term {
+        match self {
+            Term::Nightly(s) => s,
+            Term::Stable(_) => mismatch(),
+        }
     }
 }
 
 impl fmt::Debug for Term {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.term.fmt(f)
+        match self {
+            Term::Nightly(t) => t.fmt(f),
+            Term::Stable(t) => t.fmt(f),
+        }
     }
 }
 
 #[derive(Clone)]
-pub struct Literal {
-    lit: proc_macro::Literal,
+pub enum Literal {
+    Nightly(proc_macro::Literal),
+    Stable(stable::Literal),
 }
 
 macro_rules! suffixed_numbers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
-            Literal::_new(proc_macro::Literal::$name(n))
+            if nightly_works() {
+                Literal::Nightly(proc_macro::Literal::$name(n))
+            } else {
+                Literal::Stable(stable::Literal::$name(n))
+            }
         }
     )*)
 }
@@ -306,16 +508,16 @@
 macro_rules! unsuffixed_integers {
     ($($name:ident => $kind:ident,)*) => ($(
         pub fn $name(n: $kind) -> Literal {
-            Literal::_new(proc_macro::Literal::$name(n))
+            if nightly_works() {
+                Literal::Nightly(proc_macro::Literal::$name(n))
+            } else {
+                Literal::Stable(stable::Literal::$name(n))
+            }
         }
     )*)
 }
 
 impl Literal {
-    fn _new(lit: proc_macro::Literal) -> Literal {
-        Literal { lit }
-    }
-
     suffixed_numbers! {
         u8_suffixed => u8,
         u16_suffixed => u16,
@@ -346,42 +548,88 @@
     }
 
     pub fn f32_unsuffixed(f: f32) -> Literal {
-        Literal::_new(proc_macro::Literal::f32_unsuffixed(f))
+        if nightly_works() {
+            Literal::Nightly(proc_macro::Literal::f32_unsuffixed(f))
+        } else {
+            Literal::Stable(stable::Literal::f32_unsuffixed(f))
+        }
     }
 
     pub fn f64_unsuffixed(f: f64) -> Literal {
-        Literal::_new(proc_macro::Literal::f64_unsuffixed(f))
+        if nightly_works() {
+            Literal::Nightly(proc_macro::Literal::f64_unsuffixed(f))
+        } else {
+            Literal::Stable(stable::Literal::f64_unsuffixed(f))
+        }
     }
 
     pub fn string(t: &str) -> Literal {
-        Literal::_new(proc_macro::Literal::string(t))
+        if nightly_works() {
+            Literal::Nightly(proc_macro::Literal::string(t))
+        } else {
+            Literal::Stable(stable::Literal::string(t))
+        }
     }
 
     pub fn character(t: char) -> Literal {
-        Literal::_new(proc_macro::Literal::character(t))
+        if nightly_works() {
+            Literal::Nightly(proc_macro::Literal::character(t))
+        } else {
+            Literal::Stable(stable::Literal::character(t))
+        }
     }
 
     pub fn byte_string(bytes: &[u8]) -> Literal {
-        Literal::_new(proc_macro::Literal::byte_string(bytes))
+        if nightly_works() {
+            Literal::Nightly(proc_macro::Literal::byte_string(bytes))
+        } else {
+            Literal::Stable(stable::Literal::byte_string(bytes))
+        }
     }
 
     pub fn span(&self) -> Span {
-        Span(self.lit.span())
+        match self {
+            Literal::Nightly(lit) => Span::Nightly(lit.span()),
+            Literal::Stable(lit) => Span::Stable(lit.span()),
+        }
     }
 
     pub fn set_span(&mut self, span: Span) {
-        self.lit.set_span(span.0);
+        match (self, span) {
+            (Literal::Nightly(lit), Span::Nightly(s)) => lit.set_span(s),
+            (Literal::Stable(lit), Span::Stable(s)) => lit.set_span(s),
+            _ => mismatch(),
+        }
+    }
+
+    fn unwrap_nightly(self) -> proc_macro::Literal {
+        match self {
+            Literal::Nightly(s) => s,
+            Literal::Stable(_) => mismatch(),
+        }
+    }
+}
+
+impl From<stable::Literal> for Literal {
+    fn from(s: stable::Literal) -> Literal {
+        Literal::Stable(s)
     }
 }
 
 impl fmt::Display for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.lit.fmt(f)
+        match self {
+            Literal::Nightly(t) => t.fmt(f),
+            Literal::Stable(t) => t.fmt(f),
+        }
     }
 }
 
 impl fmt::Debug for Literal {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        self.lit.fmt(f)
+        match self {
+            Literal::Nightly(t) => t.fmt(f),
+            Literal::Stable(t) => t.fmt(f),
+        }
     }
 }