Skip to content

Commit bd455ef

Browse files
committedJul 21, 2018
Auto merge of #52552 - eddyb:proc-macro-prep, r=alexcrichton
Prepare proc_macro for decoupling it from the rest of the compiler. This is #49219 up to the point where the bridge is introduced. Aside from moving some code around, the largest change is the rewrite of `proc_macro::quote` to be simpler and do less introspection. I'd like to also extend `quote!` with `${stmt;...;expr}` instead of just `$variable` (and maybe even `$(... $iter ...)*`), which seems pretty straight-forward now, but I don't know if/when I should. r? @alexcrichton or @dtolnay cc @jseyfried @petrochenkov
2 parents 17eb392 + 99eac01 commit bd455ef

File tree

8 files changed

+465
-570
lines changed

8 files changed

+465
-570
lines changed
 

‎src/libproc_macro/diagnostic.rs

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010

1111
use Span;
1212

13-
use rustc_errors as rustc;
13+
use rustc_errors as errors;
14+
use syntax_pos::MultiSpan;
1415

1516
/// An enum representing a diagnostic level.
1617
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
@@ -97,38 +98,21 @@ impl Diagnostic {
9798
/// Emit the diagnostic.
9899
#[unstable(feature = "proc_macro_diagnostic", issue = "38356")]
99100
pub fn emit(self) {
100-
::__internal::with_sess(move |sess, _| {
101-
let handler = &sess.span_diagnostic;
102-
let level = __internal::level_to_internal_level(self.level);
103-
let mut diag = rustc::DiagnosticBuilder::new(handler, level, &*self.message);
101+
let level = self.level.to_internal();
102+
let mut diag = errors::Diagnostic::new(level, &*self.message);
104103

105-
if let Some(span) = self.span {
106-
diag.set_span(span.0);
107-
}
104+
if let Some(span) = self.span {
105+
diag.set_span(span.0);
106+
}
108107

109-
for child in self.children {
110-
let span = child.span.map(|s| s.0);
111-
let level = __internal::level_to_internal_level(child.level);
112-
diag.sub(level, &*child.message, span);
113-
}
108+
for child in self.children {
109+
let span = child.span.map_or(MultiSpan::new(), |s| s.0.into());
110+
let level = child.level.to_internal();
111+
diag.sub(level, &*child.message, span, None);
112+
}
114113

115-
diag.emit();
114+
::__internal::with_sess(move |sess, _| {
115+
errors::DiagnosticBuilder::new_diagnostic(&sess.span_diagnostic, diag).emit();
116116
});
117117
}
118118
}
119-
120-
#[unstable(feature = "proc_macro_internals", issue = "27812")]
121-
#[doc(hidden)]
122-
pub mod __internal {
123-
use super::{Level, rustc};
124-
125-
pub fn level_to_internal_level(level: Level) -> rustc::Level {
126-
match level {
127-
Level::Error => rustc::Level::Error,
128-
Level::Warning => rustc::Level::Warning,
129-
Level::Note => rustc::Level::Note,
130-
Level::Help => rustc::Level::Help,
131-
Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive")
132-
}
133-
}
134-
}

‎src/libproc_macro/lib.rs

Lines changed: 69 additions & 279 deletions
Large diffs are not rendered by default.

‎src/libproc_macro/quote.rs

Lines changed: 92 additions & 252 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,26 @@
1414
//! This quasiquoter uses macros 2.0 hygiene to reliably access
1515
//! items from `proc_macro`, to build a `proc_macro::TokenStream`.
1616
17-
use {Delimiter, Literal, Spacing, Span, Ident, Punct, Group, TokenStream, TokenTree};
18-
19-
use syntax::ext::base::{ExtCtxt, ProcMacro};
20-
use syntax::parse::token;
21-
use syntax::symbol::Symbol;
22-
use syntax::tokenstream;
23-
24-
/// This is the actual quote!() proc macro
25-
///
26-
/// It is manually loaded in CStore::load_macro_untracked
27-
pub struct Quoter;
28-
29-
pub fn unquote<T: Into<TokenStream> + Clone>(tokens: &T) -> TokenStream {
30-
tokens.clone().into()
31-
}
32-
33-
pub trait Quote {
34-
fn quote(self) -> TokenStream;
35-
}
36-
37-
macro_rules! tt2ts {
38-
($e:expr) => (TokenStream::from(TokenTree::from($e)))
39-
}
40-
41-
macro_rules! quote_tok {
42-
(,) => { tt2ts!(Punct::new(',', Spacing::Alone)) };
43-
(.) => { tt2ts!(Punct::new('.', Spacing::Alone)) };
44-
(:) => { tt2ts!(Punct::new(':', Spacing::Alone)) };
45-
(|) => { tt2ts!(Punct::new('|', Spacing::Alone)) };
17+
use {Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
18+
19+
macro_rules! quote_tt {
20+
(($($t:tt)*)) => { Group::new(Delimiter::Parenthesis, quote!($($t)*)) };
21+
([$($t:tt)*]) => { Group::new(Delimiter::Bracket, quote!($($t)*)) };
22+
({$($t:tt)*}) => { Group::new(Delimiter::Brace, quote!($($t)*)) };
23+
(,) => { Punct::new(',', Spacing::Alone) };
24+
(.) => { Punct::new('.', Spacing::Alone) };
25+
(:) => { Punct::new(':', Spacing::Alone) };
26+
(;) => { Punct::new(';', Spacing::Alone) };
27+
(!) => { Punct::new('!', Spacing::Alone) };
28+
(<) => { Punct::new('<', Spacing::Alone) };
29+
(>) => { Punct::new('>', Spacing::Alone) };
30+
(&) => { Punct::new('&', Spacing::Alone) };
31+
(=) => { Punct::new('=', Spacing::Alone) };
32+
($i:ident) => { Ident::new(stringify!($i), Span::def_site()) };
33+
}
34+
35+
macro_rules! quote_ts {
36+
((@ $($t:tt)*)) => { $($t)* };
4637
(::) => {
4738
[
4839
TokenTree::from(Punct::new(':', Spacing::Joint)),
@@ -55,65 +46,45 @@ macro_rules! quote_tok {
5546
})
5647
.collect::<TokenStream>()
5748
};
58-
(!) => { tt2ts!(Punct::new('!', Spacing::Alone)) };
59-
(<) => { tt2ts!(Punct::new('<', Spacing::Alone)) };
60-
(>) => { tt2ts!(Punct::new('>', Spacing::Alone)) };
61-
(_) => { tt2ts!(Punct::new('_', Spacing::Alone)) };
62-
(0) => { tt2ts!(Literal::i8_unsuffixed(0)) };
63-
(&) => { tt2ts!(Punct::new('&', Spacing::Alone)) };
64-
($i:ident) => { tt2ts!(Ident::new(stringify!($i), Span::def_site())) };
65-
}
66-
67-
macro_rules! quote_tree {
68-
((unquote $($t:tt)*)) => { $($t)* };
69-
((quote $($t:tt)*)) => { ($($t)*).quote() };
70-
(($($t:tt)*)) => { tt2ts!(Group::new(Delimiter::Parenthesis, quote!($($t)*))) };
71-
([$($t:tt)*]) => { tt2ts!(Group::new(Delimiter::Bracket, quote!($($t)*))) };
72-
({$($t:tt)*}) => { tt2ts!(Group::new(Delimiter::Brace, quote!($($t)*))) };
73-
($t:tt) => { quote_tok!($t) };
49+
($t:tt) => { TokenTree::from(quote_tt!($t)) };
7450
}
7551

52+
/// Simpler version of the real `quote!` macro, implemented solely
53+
/// through `macro_rules`, for bootstrapping the real implementation
54+
/// (see the `quote` function), which does not have access to the
55+
/// real `quote!` macro due to the `proc_macro` crate not being
56+
/// able to depend on itself.
57+
///
58+
/// Note: supported tokens are a subset of the real `quote!`, but
59+
/// unquoting is different: instead of `$x`, this uses `(@ expr)`.
7660
macro_rules! quote {
7761
() => { TokenStream::new() };
7862
($($t:tt)*) => {
79-
[$(quote_tree!($t),)*].iter()
80-
.cloned()
81-
.flat_map(|x| x.into_iter())
82-
.collect::<TokenStream>()
63+
[
64+
$(TokenStream::from(quote_ts!($t)),)*
65+
].iter().cloned().collect::<TokenStream>()
8366
};
8467
}
8568

86-
impl ProcMacro for Quoter {
87-
fn expand<'cx>(&self, cx: &'cx mut ExtCtxt,
88-
_: ::syntax_pos::Span,
89-
stream: tokenstream::TokenStream)
90-
-> tokenstream::TokenStream {
91-
::__internal::set_sess(cx, || TokenStream(stream).quote().0)
92-
}
93-
}
94-
95-
impl<T: Quote> Quote for Option<T> {
96-
fn quote(self) -> TokenStream {
97-
match self {
98-
Some(t) => quote!(Some((quote t))),
99-
None => quote!(None),
100-
}
69+
/// Quote a `TokenStream` into a `TokenStream`.
70+
/// This is the actual `quote!()` proc macro.
71+
///
72+
/// It is manually loaded in `CStore::load_macro_untracked`.
73+
#[unstable(feature = "proc_macro_quote", issue = "38356")]
74+
pub fn quote(stream: TokenStream) -> TokenStream {
75+
if stream.is_empty() {
76+
return quote!(::TokenStream::new());
10177
}
102-
}
103-
104-
impl Quote for TokenStream {
105-
fn quote(self) -> TokenStream {
106-
if self.is_empty() {
107-
return quote!(::TokenStream::new());
108-
}
109-
let mut after_dollar = false;
110-
let tokens = self.into_iter().filter_map(|tree| {
78+
let mut after_dollar = false;
79+
let tokens = stream
80+
.into_iter()
81+
.filter_map(|tree| {
11182
if after_dollar {
11283
after_dollar = false;
11384
match tree {
11485
TokenTree::Ident(_) => {
115-
let tree = TokenStream::from(tree);
116-
return Some(quote!(::__internal::unquote(&(unquote tree)),));
86+
return Some(quote!(Into::<::TokenStream>::into(
87+
Clone::clone(&(@ tree))),));
11788
}
11889
TokenTree::Punct(ref tt) if tt.as_char() == '$' => {}
11990
_ => panic!("`$` must be followed by an ident or `$` in `quote!`"),
@@ -125,186 +96,55 @@ impl Quote for TokenStream {
12596
}
12697
}
12798

128-
Some(quote!(::TokenStream::from((quote tree)),))
129-
}).flat_map(|t| t.into_iter()).collect::<TokenStream>();
130-
131-
if after_dollar {
132-
panic!("unexpected trailing `$` in `quote!`");
133-
}
134-
135-
quote!(
136-
[(unquote tokens)].iter()
137-
.cloned()
138-
.flat_map(|x| x.into_iter())
139-
.collect::<::TokenStream>()
140-
)
141-
}
142-
}
143-
144-
impl Quote for TokenTree {
145-
fn quote(self) -> TokenStream {
146-
match self {
147-
TokenTree::Punct(tt) => quote!(::TokenTree::Punct( (quote tt) )),
148-
TokenTree::Group(tt) => quote!(::TokenTree::Group( (quote tt) )),
149-
TokenTree::Ident(tt) => quote!(::TokenTree::Ident( (quote tt) )),
150-
TokenTree::Literal(tt) => quote!(::TokenTree::Literal( (quote tt) )),
151-
}
152-
}
153-
}
154-
155-
impl Quote for char {
156-
fn quote(self) -> TokenStream {
157-
TokenTree::from(Literal::character(self)).into()
158-
}
159-
}
160-
161-
impl<'a> Quote for &'a str {
162-
fn quote(self) -> TokenStream {
163-
TokenTree::from(Literal::string(self)).into()
164-
}
165-
}
166-
167-
impl Quote for u16 {
168-
fn quote(self) -> TokenStream {
169-
TokenTree::from(Literal::u16_unsuffixed(self)).into()
170-
}
171-
}
172-
173-
impl Quote for Group {
174-
fn quote(self) -> TokenStream {
175-
quote!(::Group::new((quote self.delimiter()), (quote self.stream())))
176-
}
177-
}
178-
179-
impl Quote for Punct {
180-
fn quote(self) -> TokenStream {
181-
quote!(::Punct::new((quote self.as_char()), (quote self.spacing())))
182-
}
183-
}
184-
185-
impl Quote for Ident {
186-
fn quote(self) -> TokenStream {
187-
quote!(::Ident::new((quote self.sym.as_str()), (quote self.span())))
188-
}
189-
}
190-
191-
impl Quote for Span {
192-
fn quote(self) -> TokenStream {
193-
quote!(::Span::def_site())
194-
}
195-
}
196-
197-
macro_rules! literals {
198-
($($i:ident),*; $($raw:ident),*) => {
199-
pub struct SpannedSymbol {
200-
sym: Symbol,
201-
span: Span,
202-
}
203-
204-
impl SpannedSymbol {
205-
pub fn new(string: &str, span: Span) -> SpannedSymbol {
206-
SpannedSymbol { sym: Symbol::intern(string), span }
207-
}
208-
}
209-
210-
impl Quote for SpannedSymbol {
211-
fn quote(self) -> TokenStream {
212-
quote!(::__internal::SpannedSymbol::new((quote self.sym.as_str()),
213-
(quote self.span)))
214-
}
215-
}
216-
217-
pub enum LiteralKind {
218-
$($i,)*
219-
$($raw(u16),)*
220-
}
221-
222-
impl LiteralKind {
223-
pub fn with_contents_and_suffix(self, contents: SpannedSymbol,
224-
suffix: Option<SpannedSymbol>) -> Literal {
225-
let sym = contents.sym;
226-
let suffix = suffix.map(|t| t.sym);
227-
match self {
228-
$(LiteralKind::$i => {
229-
Literal {
230-
lit: token::Lit::$i(sym),
231-
suffix,
232-
span: contents.span,
233-
}
234-
})*
235-
$(LiteralKind::$raw(n) => {
236-
Literal {
237-
lit: token::Lit::$raw(sym, n),
238-
suffix,
239-
span: contents.span,
240-
}
241-
})*
242-
}
243-
}
244-
}
245-
246-
impl Literal {
247-
fn kind_contents_and_suffix(self) -> (LiteralKind, SpannedSymbol, Option<SpannedSymbol>)
248-
{
249-
let (kind, contents) = match self.lit {
250-
$(token::Lit::$i(contents) => (LiteralKind::$i, contents),)*
251-
$(token::Lit::$raw(contents, n) => (LiteralKind::$raw(n), contents),)*
252-
};
253-
let suffix = self.suffix.map(|sym| SpannedSymbol::new(&sym.as_str(), self.span()));
254-
(kind, SpannedSymbol::new(&contents.as_str(), self.span()), suffix)
255-
}
256-
}
257-
258-
impl Quote for LiteralKind {
259-
fn quote(self) -> TokenStream {
260-
match self {
261-
$(LiteralKind::$i => quote! {
262-
::__internal::LiteralKind::$i
263-
},)*
264-
$(LiteralKind::$raw(n) => quote! {
265-
::__internal::LiteralKind::$raw((quote n))
266-
},)*
267-
}
268-
}
269-
}
99+
Some(quote!(::TokenStream::from((@ match tree {
100+
TokenTree::Punct(tt) => quote!(::TokenTree::Punct(::Punct::new(
101+
(@ TokenTree::from(Literal::character(tt.as_char()))),
102+
(@ match tt.spacing() {
103+
Spacing::Alone => quote!(::Spacing::Alone),
104+
Spacing::Joint => quote!(::Spacing::Joint),
105+
}),
106+
))),
107+
TokenTree::Group(tt) => quote!(::TokenTree::Group(::Group::new(
108+
(@ match tt.delimiter() {
109+
Delimiter::Parenthesis => quote!(::Delimiter::Parenthesis),
110+
Delimiter::Brace => quote!(::Delimiter::Brace),
111+
Delimiter::Bracket => quote!(::Delimiter::Bracket),
112+
Delimiter::None => quote!(::Delimiter::None),
113+
}),
114+
(@ quote(tt.stream())),
115+
))),
116+
TokenTree::Ident(tt) => quote!(::TokenTree::Ident(::Ident::new(
117+
(@ TokenTree::from(Literal::string(&tt.to_string()))),
118+
(@ quote_span(tt.span())),
119+
))),
120+
TokenTree::Literal(tt) => quote!(::TokenTree::Literal({
121+
let mut iter = (@ TokenTree::from(Literal::string(&tt.to_string())))
122+
.parse::<::TokenStream>()
123+
.unwrap()
124+
.into_iter();
125+
if let (Some(::TokenTree::Literal(mut lit)), None) =
126+
(iter.next(), iter.next())
127+
{
128+
lit.set_span((@ quote_span(tt.span())));
129+
lit
130+
} else {
131+
unreachable!()
132+
}
133+
}))
134+
})),))
135+
})
136+
.collect::<TokenStream>();
270137

271-
impl Quote for Literal {
272-
fn quote(self) -> TokenStream {
273-
let (kind, contents, suffix) = self.kind_contents_and_suffix();
274-
quote! {
275-
(quote kind).with_contents_and_suffix((quote contents), (quote suffix))
276-
}
277-
}
278-
}
138+
if after_dollar {
139+
panic!("unexpected trailing `$` in `quote!`");
279140
}
280-
}
281141

282-
literals!(Byte, Char, Float, Str_, Integer, ByteStr; StrRaw, ByteStrRaw);
283-
284-
impl Quote for Delimiter {
285-
fn quote(self) -> TokenStream {
286-
macro_rules! gen_match {
287-
($($i:ident),*) => {
288-
match self {
289-
$(Delimiter::$i => { quote!(::Delimiter::$i) })*
290-
}
291-
}
292-
}
293-
294-
gen_match!(Parenthesis, Brace, Bracket, None)
295-
}
142+
quote!([(@ tokens)].iter().cloned().collect::<::TokenStream>())
296143
}
297144

298-
impl Quote for Spacing {
299-
fn quote(self) -> TokenStream {
300-
macro_rules! gen_match {
301-
($($i:ident),*) => {
302-
match self {
303-
$(Spacing::$i => { quote!(::Spacing::$i) })*
304-
}
305-
}
306-
}
307-
308-
gen_match!(Alone, Joint)
309-
}
145+
/// Quote a `Span` into a `TokenStream`.
146+
/// This is needed to implement a custom quoter.
147+
#[unstable(feature = "proc_macro_quote", issue = "38356")]
148+
pub fn quote_span(_: Span) -> TokenStream {
149+
quote!(::Span::def_site())
310150
}

‎src/libproc_macro/rustc.rs

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use {Delimiter, Level, Spacing, Span, __internal};
12+
use {Group, Ident, Literal, Punct, TokenTree};
13+
14+
use rustc_errors as errors;
15+
use syntax::ast;
16+
use syntax::parse::lexer::comments;
17+
use syntax::parse::token;
18+
use syntax::tokenstream;
19+
use syntax_pos::symbol::{keywords, Symbol};
20+
21+
impl Ident {
22+
pub(crate) fn new_maybe_raw(string: &str, span: Span, is_raw: bool) -> Ident {
23+
let sym = Symbol::intern(string);
24+
if is_raw
25+
&& (sym == keywords::Underscore.name()
26+
|| ast::Ident::with_empty_ctxt(sym).is_path_segment_keyword())
27+
{
28+
panic!("`{:?}` is not a valid raw identifier", string)
29+
}
30+
Ident { sym, span, is_raw }
31+
}
32+
}
33+
34+
impl Delimiter {
35+
pub(crate) fn from_internal(delim: token::DelimToken) -> Delimiter {
36+
match delim {
37+
token::Paren => Delimiter::Parenthesis,
38+
token::Brace => Delimiter::Brace,
39+
token::Bracket => Delimiter::Bracket,
40+
token::NoDelim => Delimiter::None,
41+
}
42+
}
43+
44+
pub(crate) fn to_internal(self) -> token::DelimToken {
45+
match self {
46+
Delimiter::Parenthesis => token::Paren,
47+
Delimiter::Brace => token::Brace,
48+
Delimiter::Bracket => token::Bracket,
49+
Delimiter::None => token::NoDelim,
50+
}
51+
}
52+
}
53+
54+
impl TokenTree {
55+
pub(crate) fn from_internal(
56+
stream: tokenstream::TokenStream,
57+
stack: &mut Vec<TokenTree>,
58+
) -> TokenTree {
59+
use syntax::parse::token::*;
60+
61+
let (tree, is_joint) = stream.as_tree();
62+
let (span, token) = match tree {
63+
tokenstream::TokenTree::Token(span, token) => (span, token),
64+
tokenstream::TokenTree::Delimited(span, delimed) => {
65+
let delimiter = Delimiter::from_internal(delimed.delim);
66+
let mut g = Group::new(delimiter, ::TokenStream(delimed.tts.into()));
67+
g.set_span(Span(span));
68+
return g.into();
69+
}
70+
};
71+
72+
let op_kind = if is_joint {
73+
Spacing::Joint
74+
} else {
75+
Spacing::Alone
76+
};
77+
macro_rules! tt {
78+
($e:expr) => {{
79+
let mut x = TokenTree::from($e);
80+
x.set_span(Span(span));
81+
x
82+
}};
83+
}
84+
macro_rules! op {
85+
($a:expr) => {
86+
tt!(Punct::new($a, op_kind))
87+
};
88+
($a:expr, $b:expr) => {{
89+
stack.push(tt!(Punct::new($b, op_kind)));
90+
tt!(Punct::new($a, Spacing::Joint))
91+
}};
92+
($a:expr, $b:expr, $c:expr) => {{
93+
stack.push(tt!(Punct::new($c, op_kind)));
94+
stack.push(tt!(Punct::new($b, Spacing::Joint)));
95+
tt!(Punct::new($a, Spacing::Joint))
96+
}};
97+
}
98+
99+
match token {
100+
Eq => op!('='),
101+
Lt => op!('<'),
102+
Le => op!('<', '='),
103+
EqEq => op!('=', '='),
104+
Ne => op!('!', '='),
105+
Ge => op!('>', '='),
106+
Gt => op!('>'),
107+
AndAnd => op!('&', '&'),
108+
OrOr => op!('|', '|'),
109+
Not => op!('!'),
110+
Tilde => op!('~'),
111+
BinOp(Plus) => op!('+'),
112+
BinOp(Minus) => op!('-'),
113+
BinOp(Star) => op!('*'),
114+
BinOp(Slash) => op!('/'),
115+
BinOp(Percent) => op!('%'),
116+
BinOp(Caret) => op!('^'),
117+
BinOp(And) => op!('&'),
118+
BinOp(Or) => op!('|'),
119+
BinOp(Shl) => op!('<', '<'),
120+
BinOp(Shr) => op!('>', '>'),
121+
BinOpEq(Plus) => op!('+', '='),
122+
BinOpEq(Minus) => op!('-', '='),
123+
BinOpEq(Star) => op!('*', '='),
124+
BinOpEq(Slash) => op!('/', '='),
125+
BinOpEq(Percent) => op!('%', '='),
126+
BinOpEq(Caret) => op!('^', '='),
127+
BinOpEq(And) => op!('&', '='),
128+
BinOpEq(Or) => op!('|', '='),
129+
BinOpEq(Shl) => op!('<', '<', '='),
130+
BinOpEq(Shr) => op!('>', '>', '='),
131+
At => op!('@'),
132+
Dot => op!('.'),
133+
DotDot => op!('.', '.'),
134+
DotDotDot => op!('.', '.', '.'),
135+
DotDotEq => op!('.', '.', '='),
136+
Comma => op!(','),
137+
Semi => op!(';'),
138+
Colon => op!(':'),
139+
ModSep => op!(':', ':'),
140+
RArrow => op!('-', '>'),
141+
LArrow => op!('<', '-'),
142+
FatArrow => op!('=', '>'),
143+
Pound => op!('#'),
144+
Dollar => op!('$'),
145+
Question => op!('?'),
146+
SingleQuote => op!('\''),
147+
148+
Ident(ident, false) => tt!(self::Ident::new(&ident.as_str(), Span(span))),
149+
Ident(ident, true) => tt!(self::Ident::new_raw(&ident.as_str(), Span(span))),
150+
Lifetime(ident) => {
151+
let ident = ident.without_first_quote();
152+
stack.push(tt!(self::Ident::new(&ident.as_str(), Span(span))));
153+
tt!(Punct::new('\'', Spacing::Joint))
154+
}
155+
Literal(lit, suffix) => tt!(self::Literal {
156+
lit,
157+
suffix,
158+
span: Span(span)
159+
}),
160+
DocComment(c) => {
161+
let style = comments::doc_comment_style(&c.as_str());
162+
let stripped = comments::strip_doc_comment_decoration(&c.as_str());
163+
let stream = vec![
164+
tt!(self::Ident::new("doc", Span(span))),
165+
tt!(Punct::new('=', Spacing::Alone)),
166+
tt!(self::Literal::string(&stripped)),
167+
].into_iter()
168+
.collect();
169+
stack.push(tt!(Group::new(Delimiter::Bracket, stream)));
170+
if style == ast::AttrStyle::Inner {
171+
stack.push(tt!(Punct::new('!', Spacing::Alone)));
172+
}
173+
tt!(Punct::new('#', Spacing::Alone))
174+
}
175+
176+
Interpolated(_) => __internal::with_sess(|sess, _| {
177+
let tts = token.interpolated_to_tokenstream(sess, span);
178+
tt!(Group::new(Delimiter::None, ::TokenStream(tts)))
179+
}),
180+
181+
DotEq => op!('.', '='),
182+
OpenDelim(..) | CloseDelim(..) => unreachable!(),
183+
Whitespace | Comment | Shebang(..) | Eof => unreachable!(),
184+
}
185+
}
186+
187+
pub(crate) fn to_internal(self) -> tokenstream::TokenStream {
188+
use syntax::parse::token::*;
189+
use syntax::tokenstream::{Delimited, TokenTree};
190+
191+
let (ch, kind, span) = match self {
192+
self::TokenTree::Punct(tt) => (tt.as_char(), tt.spacing(), tt.span()),
193+
self::TokenTree::Group(tt) => {
194+
return TokenTree::Delimited(
195+
tt.span.0,
196+
Delimited {
197+
delim: tt.delimiter.to_internal(),
198+
tts: tt.stream.0.into(),
199+
},
200+
).into();
201+
}
202+
self::TokenTree::Ident(tt) => {
203+
let token = Ident(ast::Ident::new(tt.sym, tt.span.0), tt.is_raw);
204+
return TokenTree::Token(tt.span.0, token).into();
205+
}
206+
self::TokenTree::Literal(self::Literal {
207+
lit: Lit::Integer(ref a),
208+
suffix,
209+
span,
210+
})
211+
if a.as_str().starts_with("-") =>
212+
{
213+
let minus = BinOp(BinOpToken::Minus);
214+
let integer = Symbol::intern(&a.as_str()[1..]);
215+
let integer = Literal(Lit::Integer(integer), suffix);
216+
let a = TokenTree::Token(span.0, minus);
217+
let b = TokenTree::Token(span.0, integer);
218+
return vec![a, b].into_iter().collect();
219+
}
220+
self::TokenTree::Literal(self::Literal {
221+
lit: Lit::Float(ref a),
222+
suffix,
223+
span,
224+
})
225+
if a.as_str().starts_with("-") =>
226+
{
227+
let minus = BinOp(BinOpToken::Minus);
228+
let float = Symbol::intern(&a.as_str()[1..]);
229+
let float = Literal(Lit::Float(float), suffix);
230+
let a = TokenTree::Token(span.0, minus);
231+
let b = TokenTree::Token(span.0, float);
232+
return vec![a, b].into_iter().collect();
233+
}
234+
self::TokenTree::Literal(tt) => {
235+
let token = Literal(tt.lit, tt.suffix);
236+
return TokenTree::Token(tt.span.0, token).into();
237+
}
238+
};
239+
240+
let token = match ch {
241+
'=' => Eq,
242+
'<' => Lt,
243+
'>' => Gt,
244+
'!' => Not,
245+
'~' => Tilde,
246+
'+' => BinOp(Plus),
247+
'-' => BinOp(Minus),
248+
'*' => BinOp(Star),
249+
'/' => BinOp(Slash),
250+
'%' => BinOp(Percent),
251+
'^' => BinOp(Caret),
252+
'&' => BinOp(And),
253+
'|' => BinOp(Or),
254+
'@' => At,
255+
'.' => Dot,
256+
',' => Comma,
257+
';' => Semi,
258+
':' => Colon,
259+
'#' => Pound,
260+
'$' => Dollar,
261+
'?' => Question,
262+
'\'' => SingleQuote,
263+
_ => unreachable!(),
264+
};
265+
266+
let tree = TokenTree::Token(span.0, token);
267+
match kind {
268+
Spacing::Alone => tree.into(),
269+
Spacing::Joint => tree.joint(),
270+
}
271+
}
272+
}
273+
274+
impl Level {
275+
pub(crate) fn to_internal(self) -> errors::Level {
276+
match self {
277+
Level::Error => errors::Level::Error,
278+
Level::Warning => errors::Level::Warning,
279+
Level::Note => errors::Level::Note,
280+
Level::Help => errors::Level::Help,
281+
Level::__Nonexhaustive => unreachable!("Level::__Nonexhaustive"),
282+
}
283+
}
284+
}

‎src/librustc_errors/diagnostic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ impl Diagnostic {
379379

380380
/// Convenience function for internal use, clients should use one of the
381381
/// public methods above.
382-
pub(crate) fn sub(&mut self,
382+
pub fn sub(&mut self,
383383
level: Level,
384384
message: &str,
385385
span: MultiSpan,

‎src/librustc_metadata/cstore_impl.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ use syntax::ast;
3939
use syntax::attr;
4040
use syntax::codemap;
4141
use syntax::edition::Edition;
42-
use syntax::ext::base::SyntaxExtension;
4342
use syntax::parse::filemap_to_stream;
4443
use syntax::symbol::Symbol;
4544
use syntax_pos::{Span, NO_EXPANSION, FileName};
@@ -517,8 +516,11 @@ impl CrateStore for cstore::CStore {
517516
return LoadedMacro::ProcMacro(proc_macros[id.index.to_proc_macro_index()].1.clone());
518517
} else if data.name == "proc_macro" &&
519518
self.get_crate_data(id.krate).item_name(id.index) == "quote" {
519+
use syntax::ext::base::SyntaxExtension;
520+
use syntax_ext::proc_macro_impl::BangProcMacro;
521+
520522
let ext = SyntaxExtension::ProcMacro {
521-
expander: Box::new(::proc_macro::__internal::Quoter),
523+
expander: Box::new(BangProcMacro { inner: ::proc_macro::quote }),
522524
allow_internal_unstable: true,
523525
edition: data.root.edition,
524526
};

‎src/librustc_metadata/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#![feature(libc)]
2020
#![feature(macro_at_most_once_rep)]
2121
#![feature(proc_macro_internals)]
22+
#![feature(proc_macro_quote)]
2223
#![feature(quote)]
2324
#![feature(rustc_diagnostic_macros)]
2425
#![feature(slice_sort_by_cached_key)]

‎src/libsyntax/parse/lexer/mod.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,12 +1775,6 @@ fn ident_continue(c: Option<char>) -> bool {
17751775
(c > '\x7f' && c.is_xid_continue())
17761776
}
17771777

1778-
// The string is a valid identifier or a lifetime identifier.
1779-
pub fn is_valid_ident(s: &str) -> bool {
1780-
let mut chars = s.chars();
1781-
ident_start(chars.next()) && chars.all(|ch| ident_continue(Some(ch)))
1782-
}
1783-
17841778
#[cfg(test)]
17851779
mod tests {
17861780
use super::*;

0 commit comments

Comments
 (0)
Please sign in to comment.