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),
+ }
}
}