Skip to content

Commit 30a4e9e

Browse files
committed
Fix the nightly feature outside of rustc
This commit is a stab at getting the `proc_macro2` crate to function outside the context of the compiler, **even when the `nightly` feature is enabled**. Previously when the `nightly` feature was enabled then `proc_macro2` would panic at runtime because `proc_macro` itself would panic at runtime due to the lack of the compiler being initialized. In this commit the `unstable` module in `proc_macro2` no longer unconditionally uses the `proc_macro` upstream crate but is rather an `enum` over the upstream crate and the `stable` module. At runtime the appropriate implementation is dynamically selected depending on which works. This brings up some uncomfortable issues such as what happens when you try to psas a "stable span" to a "nightly `Literal`", but I think we can paper over these issues in time by further canonicalizing everything to nightly/stable if it comes up. One caveat this brings up is that `Span::unstable` unconditionally panics when outside the compiler, but I think that's expected regardless.
1 parent 6b46deb commit 30a4e9e

File tree

5 files changed

+378
-115
lines changed

5 files changed

+378
-115
lines changed

.travis.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ matrix:
1111
- pip install 'travis-cargo<0.2' --user && export PATH=$HOME/.local/bin:$PATH
1212
script:
1313
- cargo test
14-
- cargo build --features nightly
15-
- cargo build --no-default-features
14+
- cargo test --features nightly
15+
- cargo test --no-default-features
1616
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test
17-
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo build --features nightly
17+
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo test --features nightly
1818
- RUSTFLAGS='--cfg procmacro2_semver_exempt' cargo doc --no-deps
1919
after_success:
2020
- travis-cargo --only nightly doc-upload

src/lib.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@
4848

4949
#[cfg(feature = "proc-macro")]
5050
extern crate proc_macro;
51-
52-
#[cfg(not(feature = "nightly"))]
5351
extern crate unicode_xid;
5452

5553
use std::fmt;
@@ -59,12 +57,11 @@ use std::rc::Rc;
5957
use std::str::FromStr;
6058

6159
#[macro_use]
62-
#[cfg(not(feature = "nightly"))]
6360
mod strnom;
61+
mod stable;
6462

65-
#[path = "stable.rs"]
6663
#[cfg(not(feature = "nightly"))]
67-
mod imp;
64+
use stable as imp;
6865
#[path = "unstable.rs"]
6966
#[cfg(feature = "nightly")]
7067
mod imp;
@@ -88,6 +85,13 @@ impl TokenStream {
8885
}
8986
}
9087

88+
fn _new_stable(inner: stable::TokenStream) -> TokenStream {
89+
TokenStream {
90+
inner: inner.into(),
91+
_marker: marker::PhantomData,
92+
}
93+
}
94+
9195
pub fn empty() -> TokenStream {
9296
TokenStream::_new(imp::TokenStream::empty())
9397
}
@@ -201,6 +205,13 @@ impl Span {
201205
}
202206
}
203207

208+
fn _new_stable(inner: stable::Span) -> Span {
209+
Span {
210+
inner: inner.into(),
211+
_marker: marker::PhantomData,
212+
}
213+
}
214+
204215
pub fn call_site() -> Span {
205216
Span::_new(imp::Span::call_site())
206217
}
@@ -525,6 +536,13 @@ impl Literal {
525536
}
526537
}
527538

539+
fn _new_stable(inner: stable::Literal) -> Literal {
540+
Literal {
541+
inner: inner.into(),
542+
_marker: marker::PhantomData,
543+
}
544+
}
545+
528546
int_literals! {
529547
u8_suffixed => u8,
530548
u16_suffixed => u16,

src/stable.rs

+16-19
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ impl FromStr for TokenStream {
6565
if skip_whitespace(input).len() != 0 {
6666
Err(LexError)
6767
} else {
68-
Ok(output.inner)
68+
Ok(output)
6969
}
7070
}
7171
Err(LexError) => Err(LexError),
@@ -89,7 +89,7 @@ impl fmt::Display for TokenStream {
8989
Delimiter::Bracket => ("[", "]"),
9090
Delimiter::None => ("", ""),
9191
};
92-
if tt.stream().inner.inner.len() == 0 {
92+
if tt.stream().into_iter().next().is_none() {
9393
write!(f, "{} {}", start, end)?
9494
} else {
9595
write!(f, "{} {} {}", start, tt.stream(), end)?
@@ -167,24 +167,24 @@ impl IntoIterator for TokenStream {
167167
}
168168
}
169169

170-
#[cfg(procmacro2_semver_exempt)]
171170
#[derive(Clone, PartialEq, Eq, Debug)]
172171
pub struct FileName(String);
173172

174-
#[cfg(procmacro2_semver_exempt)]
173+
pub fn file_name(s: String) -> FileName {
174+
FileName(s)
175+
}
176+
175177
impl fmt::Display for FileName {
176178
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
177179
self.0.fmt(f)
178180
}
179181
}
180182

181-
#[cfg(procmacro2_semver_exempt)]
182183
#[derive(Clone, PartialEq, Eq)]
183184
pub struct SourceFile {
184185
name: FileName,
185186
}
186187

187-
#[cfg(procmacro2_semver_exempt)]
188188
impl SourceFile {
189189
/// Get the path to this source file as a string.
190190
pub fn path(&self) -> &FileName {
@@ -197,14 +197,12 @@ impl SourceFile {
197197
}
198198
}
199199

200-
#[cfg(procmacro2_semver_exempt)]
201200
impl AsRef<FileName> for SourceFile {
202201
fn as_ref(&self) -> &FileName {
203202
self.path()
204203
}
205204
}
206205

207-
#[cfg(procmacro2_semver_exempt)]
208206
impl fmt::Debug for SourceFile {
209207
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
210208
f.debug_struct("SourceFile")
@@ -214,7 +212,6 @@ impl fmt::Debug for SourceFile {
214212
}
215213
}
216214

217-
#[cfg(procmacro2_semver_exempt)]
218215
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
219216
pub struct LineColumn {
220217
pub line: usize,
@@ -660,7 +657,7 @@ impl fmt::Debug for Literal {
660657
}
661658
}
662659

663-
fn token_stream(mut input: Cursor) -> PResult<::TokenStream> {
660+
fn token_stream(mut input: Cursor) -> PResult<TokenStream> {
664661
let mut trees = Vec::new();
665662
loop {
666663
let input_no_ws = skip_whitespace(input);
@@ -680,7 +677,7 @@ fn token_stream(mut input: Cursor) -> PResult<::TokenStream> {
680677
trees.push(tt);
681678
input = a;
682679
}
683-
Ok((input, ::TokenStream::_new(TokenStream { inner: trees })))
680+
Ok((input, TokenStream { inner: trees }))
684681
}
685682

686683
#[cfg(not(procmacro2_semver_exempt))]
@@ -689,7 +686,7 @@ fn spanned<'a, T>(
689686
f: fn(Cursor<'a>) -> PResult<'a, T>,
690687
) -> PResult<'a, (T, ::Span)> {
691688
let (a, b) = f(skip_whitespace(input))?;
692-
Ok((a, ((b, ::Span::_new(Span {})))))
689+
Ok((a, ((b, ::Span::_new_stable(Span {})))))
693690
}
694691

695692
#[cfg(procmacro2_semver_exempt)]
@@ -701,7 +698,7 @@ fn spanned<'a, T>(
701698
let lo = input.off;
702699
let (a, b) = f(input)?;
703700
let hi = a.off;
704-
let span = ::Span::_new(Span { lo: lo, hi: hi });
701+
let span = ::Span::_new_stable(Span { lo: lo, hi: hi });
705702
Ok((a, (b, span)))
706703
}
707704

@@ -714,7 +711,7 @@ fn token_tree(input: Cursor) -> PResult<TokenTree> {
714711
named!(token_kind -> TokenTree, alt!(
715712
map!(group, TokenTree::Group)
716713
|
717-
map!(literal, TokenTree::Literal) // must be before symbol
714+
map!(literal, |l| TokenTree::Literal(::Literal::_new_stable(l))) // must be before symbol
718715
|
719716
symbol
720717
|
@@ -726,19 +723,19 @@ named!(group -> Group, alt!(
726723
punct!("("),
727724
token_stream,
728725
punct!(")")
729-
) => { |ts| Group::new(Delimiter::Parenthesis, ts) }
726+
) => { |ts| Group::new(Delimiter::Parenthesis, ::TokenStream::_new_stable(ts)) }
730727
|
731728
delimited!(
732729
punct!("["),
733730
token_stream,
734731
punct!("]")
735-
) => { |ts| Group::new(Delimiter::Bracket, ts) }
732+
) => { |ts| Group::new(Delimiter::Bracket, ::TokenStream::_new_stable(ts)) }
736733
|
737734
delimited!(
738735
punct!("{"),
739736
token_stream,
740737
punct!("}")
741-
) => { |ts| Group::new(Delimiter::Brace, ts) }
738+
) => { |ts| Group::new(Delimiter::Brace, ::TokenStream::_new_stable(ts)) }
742739
));
743740

744741
fn symbol(mut input: Cursor) -> PResult<TokenTree> {
@@ -792,7 +789,7 @@ static KEYWORDS: &'static [&'static str] = &[
792789
"type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
793790
];
794791

795-
fn literal(input: Cursor) -> PResult<::Literal> {
792+
fn literal(input: Cursor) -> PResult<Literal> {
796793
let input_no_ws = skip_whitespace(input);
797794

798795
match literal_nocapture(input_no_ws) {
@@ -802,7 +799,7 @@ fn literal(input: Cursor) -> PResult<::Literal> {
802799
let end = start + len;
803800
Ok((
804801
a,
805-
::Literal::_new(Literal::_new(input.rest[start..end].to_string())),
802+
Literal::_new(input.rest[start..end].to_string()),
806803
))
807804
}
808805
Err(LexError) => Err(LexError),

src/strnom.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::str::{Bytes, CharIndices, Chars};
44

55
use unicode_xid::UnicodeXID;
66

7-
use imp::LexError;
7+
use stable::LexError;
88

99
#[derive(Copy, Clone, Eq, PartialEq)]
1010
pub struct Cursor<'a> {

0 commit comments

Comments
 (0)