1 // Copyright 2016 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.
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.
11 //! A support library for macro authors when defining new macros.
13 //! This library, provided by the standard distribution, provides the types
14 //! consumed in the interfaces of procedurally defined macro definitions.
15 //! Currently the primary use of this crate is to provide the ability to define
16 //! new custom derive modes through `#[proc_macro_derive]`.
18 //! Note that this crate is intentionally very bare-bones currently. The main
19 //! type, `TokenStream`, only supports `fmt::Display` and `FromStr`
20 //! implementations, indicating that it can only go to and come from a string.
21 //! This functionality is intended to be expanded over time as more surface
22 //! area for macro authors is stabilized.
24 //! See [the book](../book/first-edition/procedural-macros.html) for more.
26 #![stable(feature = "proc_macro_lib", since = "1.15.0")]
28 #![deny(missing_docs)]
29 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
30 html_favicon_url
= "https://doc.rust-lang.org/favicon.ico",
31 html_root_url
= "https://doc.rust-lang.org/nightly/",
32 html_playground_url
= "https://play.rust-lang.org/",
33 issue_tracker_base_url
= "https://github.com/rust-lang/rust/issues/",
34 test(no_crate_inject
, attr(deny(warnings
))),
35 test(attr(allow(dead_code
, deprecated
, unused_variables
, unused_mut
))))]
37 #![feature(i128_type)]
38 #![feature(rustc_private)]
39 #![feature(staged_api)]
40 #![feature(lang_items)]
44 extern crate syntax_pos
;
45 extern crate rustc_errors
;
49 #[unstable(feature = "proc_macro", issue = "38356")]
50 pub use diagnostic
::{Diagnostic, Level}
;
52 use std
::{ascii, fmt, iter}
;
54 use std
::str::FromStr
;
57 use syntax
::errors
::DiagnosticBuilder
;
58 use syntax
::parse
::{self, token}
;
59 use syntax
::symbol
::Symbol
;
60 use syntax
::tokenstream
;
61 use syntax_pos
::DUMMY_SP
;
62 use syntax_pos
::{FileMap, Pos, SyntaxContext, FileName}
;
63 use syntax_pos
::hygiene
::Mark
;
65 /// The main type provided by this crate, representing an abstract stream of
68 /// This is both the input and output of `#[proc_macro_derive]` definitions.
69 /// Currently it's required to be a list of valid Rust items, but this
70 /// restriction may be lifted in the future.
72 /// The API of this type is intentionally bare-bones, but it'll be expanded over
74 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
75 #[derive(Clone, Debug)]
76 pub struct TokenStream(tokenstream
::TokenStream
);
78 /// Error returned from `TokenStream::from_str`.
79 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
85 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
86 impl FromStr
for TokenStream
{
89 fn from_str(src
: &str) -> Result
<TokenStream
, LexError
> {
90 __internal
::with_sess(|(sess
, mark
)| {
91 let src
= src
.to_string();
92 let name
= FileName
::ProcMacroSourceCode
;
93 let expn_info
= mark
.expn_info().unwrap();
94 let call_site
= expn_info
.call_site
;
95 // notify the expansion info that it is unhygienic
96 let mark
= Mark
::fresh(mark
);
97 mark
.set_expn_info(expn_info
);
98 let span
= call_site
.with_ctxt(call_site
.ctxt().apply_mark(mark
));
99 let stream
= parse
::parse_stream_from_source_str(name
, src
, sess
, Some(span
));
100 Ok(__internal
::token_stream_wrap(stream
))
105 #[stable(feature = "proc_macro_lib", since = "1.15.0")]
106 impl fmt
::Display
for TokenStream
{
107 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
112 /// `quote!(..)` accepts arbitrary tokens and expands into a `TokenStream` describing the input.
113 /// For example, `quote!(a + b)` will produce a expression, that, when evaluated, constructs
114 /// the `TokenStream` `[Word("a"), Op('+', Alone), Word("b")]`.
116 /// Unquoting is done with `$`, and works by taking the single next ident as the unquoted term.
117 /// To quote `$` itself, use `$$`.
118 #[unstable(feature = "proc_macro", issue = "38356")]
120 macro_rules
! quote { () => {}
}
122 #[unstable(feature = "proc_macro_internals", issue = "27812")]
126 #[unstable(feature = "proc_macro", issue = "38356")]
127 impl From
<TokenTree
> for TokenStream
{
128 fn from(tree
: TokenTree
) -> TokenStream
{
129 TokenStream(tree
.to_internal())
133 #[unstable(feature = "proc_macro", issue = "38356")]
134 impl From
<TokenNode
> for TokenStream
{
135 fn from(kind
: TokenNode
) -> TokenStream
{
136 TokenTree
::from(kind
).into()
140 #[unstable(feature = "proc_macro", issue = "38356")]
141 impl<T
: Into
<TokenStream
>> iter
::FromIterator
<T
> for TokenStream
{
142 fn from_iter
<I
: IntoIterator
<Item
= T
>>(streams
: I
) -> Self {
143 let mut builder
= tokenstream
::TokenStreamBuilder
::new();
144 for stream
in streams
{
145 builder
.push(stream
.into().0);
147 TokenStream(builder
.build())
151 #[unstable(feature = "proc_macro", issue = "38356")]
152 impl IntoIterator
for TokenStream
{
153 type Item
= TokenTree
;
154 type IntoIter
= TokenTreeIter
;
156 fn into_iter(self) -> TokenTreeIter
{
157 TokenTreeIter { cursor: self.0.trees(), next: None }
162 /// Returns an empty `TokenStream`.
163 #[unstable(feature = "proc_macro", issue = "38356")]
164 pub fn empty() -> TokenStream
{
165 TokenStream(tokenstream
::TokenStream
::empty())
168 /// Checks if this `TokenStream` is empty.
169 #[unstable(feature = "proc_macro", issue = "38356")]
170 pub fn is_empty(&self) -> bool
{
175 /// A region of source code, along with macro expansion information.
176 #[unstable(feature = "proc_macro", issue = "38356")]
177 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
178 pub struct Span(syntax_pos
::Span
);
181 /// A span that resolves at the macro definition site.
182 #[unstable(feature = "proc_macro", issue = "38356")]
183 pub fn def_site() -> Span
{
184 ::__internal
::with_sess(|(_
, mark
)| {
185 let call_site
= mark
.expn_info().unwrap().call_site
;
186 Span(call_site
.with_ctxt(SyntaxContext
::empty().apply_mark(mark
)))
191 /// Quote a `Span` into a `TokenStream`.
192 /// This is needed to implement a custom quoter.
193 #[unstable(feature = "proc_macro", issue = "38356")]
194 pub fn quote_span(span
: Span
) -> TokenStream
{
195 quote
::Quote
::quote(span
)
198 macro_rules
! diagnostic_method
{
199 ($name
:ident
, $level
:expr
) => (
200 /// Create a new `Diagnostic` with the given `message` at the span
202 #[unstable(feature = "proc_macro", issue = "38356")]
203 pub fn $name
<T
: Into
<String
>>(self, message
: T
) -> Diagnostic
{
204 Diagnostic
::spanned(self, $level
, message
)
210 /// The span of the invocation of the current procedural macro.
211 #[unstable(feature = "proc_macro", issue = "38356")]
212 pub fn call_site() -> Span
{
213 ::__internal
::with_sess(|(_
, mark
)| Span(mark
.expn_info().unwrap().call_site
))
216 /// The original source file into which this span points.
217 #[unstable(feature = "proc_macro", issue = "38356")]
218 pub fn source_file(&self) -> SourceFile
{
220 filemap
: __internal
::lookup_char_pos(self.0.lo()).file
,
224 /// Get the starting line/column in the source file for this span.
225 #[unstable(feature = "proc_macro", issue = "38356")]
226 pub fn start(&self) -> LineColumn
{
227 let loc
= __internal
::lookup_char_pos(self.0.lo());
230 column
: loc
.col
.to_usize()
234 /// Get the ending line/column in the source file for this span.
235 #[unstable(feature = "proc_macro", issue = "38356")]
236 pub fn end(&self) -> LineColumn
{
237 let loc
= __internal
::lookup_char_pos(self.0.hi());
240 column
: loc
.col
.to_usize()
244 /// Create a new span encompassing `self` and `other`.
246 /// Returns `None` if `self` and `other` are from different files.
247 #[unstable(feature = "proc_macro", issue = "38356")]
248 pub fn join(&self, other
: Span
) -> Option
<Span
> {
249 let self_loc
= __internal
::lookup_char_pos(self.0.lo());
250 let other_loc
= __internal
::lookup_char_pos(self.0.lo());
252 if self_loc
.file
.name
!= other_loc
.file
.name { return None }
254 Some(Span(self.0.to(other
.0)))
257 diagnostic_method
!(error
, Level
::Error
);
258 diagnostic_method
!(warning
, Level
::Warning
);
259 diagnostic_method
!(note
, Level
::Note
);
260 diagnostic_method
!(help
, Level
::Help
);
263 /// A line-column pair representing the start or end of a `Span`.
264 #[unstable(feature = "proc_macro", issue = "38356")]
265 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
266 pub struct LineColumn
{
267 /// The 1-indexed line in the source file on which the span starts or ends (inclusive).
268 #[unstable(feature = "proc_macro", issue = "38356")]
270 /// The 0-indexed column (in UTF-8 characters) in the source file on which
271 /// the span starts or ends (inclusive).
272 #[unstable(feature = "proc_macro", issue = "38356")]
276 /// The source file of a given `Span`.
277 #[unstable(feature = "proc_macro", issue = "38356")]
279 pub struct SourceFile
{
280 filemap
: Rc
<FileMap
>,
284 /// Get the path to this source file.
287 /// If the code span associated with this `SourceFile` was generated by an external macro, this
288 /// may not be an actual path on the filesystem. Use [`is_real`] to check.
290 /// Also note that even if `is_real` returns `true`, if `-Z remap-path-prefix-*` was passed on
291 /// the command line, the path as given may not actually be valid.
293 /// [`is_real`]: #method.is_real
294 # [unstable(feature = "proc_macro", issue = "38356")]
295 pub fn path(&self) -> &FileName
{
299 /// Returns `true` if this source file is a real source file, and not generated by an external
300 /// macro's expansion.
301 # [unstable(feature = "proc_macro", issue = "38356")]
302 pub fn is_real(&self) -> bool
{
303 // This is a hack until intercrate spans are implemented and we can have real source files
304 // for spans generated in external macros.
305 // https://github.com/rust-lang/rust/pull/43604#issuecomment-333334368
306 self.filemap
.is_real_file()
310 #[unstable(feature = "proc_macro", issue = "38356")]
311 impl AsRef
<FileName
> for SourceFile
{
312 fn as_ref(&self) -> &FileName
{
317 #[unstable(feature = "proc_macro", issue = "38356")]
318 impl fmt
::Debug
for SourceFile
{
319 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
320 f
.debug_struct("SourceFile")
321 .field("path", self.path())
322 .field("is_real", &self.is_real())
327 #[unstable(feature = "proc_macro", issue = "38356")]
328 impl PartialEq
for SourceFile
{
329 fn eq(&self, other
: &Self) -> bool
{
330 Rc
::ptr_eq(&self.filemap
, &other
.filemap
)
334 #[unstable(feature = "proc_macro", issue = "38356")]
335 impl Eq
for SourceFile {}
337 #[unstable(feature = "proc_macro", issue = "38356")]
338 impl PartialEq
<FileName
> for SourceFile
{
339 fn eq(&self, other
: &FileName
) -> bool
{
340 self.as_ref() == other
344 /// A single token or a delimited sequence of token trees (e.g. `[1, (), ..]`).
345 #[unstable(feature = "proc_macro", issue = "38356")]
346 #[derive(Clone, Debug)]
347 pub struct TokenTree
{
348 /// The `TokenTree`'s span
350 /// Description of the `TokenTree`
354 #[unstable(feature = "proc_macro", issue = "38356")]
355 impl From
<TokenNode
> for TokenTree
{
356 fn from(kind
: TokenNode
) -> TokenTree
{
357 TokenTree { span: Span::def_site(), kind: kind }
361 #[unstable(feature = "proc_macro", issue = "38356")]
362 impl fmt
::Display
for TokenTree
{
363 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
364 TokenStream
::from(self.clone()).fmt(f
)
368 /// Description of a `TokenTree`
369 #[derive(Clone, Debug)]
370 #[unstable(feature = "proc_macro", issue = "38356")]
372 /// A delimited tokenstream.
373 Group(Delimiter
, TokenStream
),
374 /// A unicode identifier.
376 /// A punctuation character (`+`, `,`, `$`, etc.).
378 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
382 /// Describes how a sequence of token trees is delimited.
383 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
384 #[unstable(feature = "proc_macro", issue = "38356")]
392 /// An implicit delimiter, e.g. `$var`, where $var is `...`.
396 /// An interned string.
397 #[derive(Copy, Clone, Debug)]
398 #[unstable(feature = "proc_macro", issue = "38356")]
399 pub struct Term(Symbol
);
402 /// Intern a string into a `Term`.
403 #[unstable(feature = "proc_macro", issue = "38356")]
404 pub fn intern(string
: &str) -> Term
{
405 Term(Symbol
::intern(string
))
408 /// Get a reference to the interned string.
409 #[unstable(feature = "proc_macro", issue = "38356")]
410 pub fn as_str(&self) -> &str {
411 unsafe { &*(&*self.0.as_str() as *const str) }
415 /// Whether an `Op` is either followed immediately by another `Op` or followed by whitespace.
416 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
417 #[unstable(feature = "proc_macro", issue = "38356")]
419 /// e.g. `+` is `Alone` in `+ =`.
421 /// e.g. `+` is `Joint` in `+=`.
425 /// A literal character (`'a'`), string (`"hello"`), or number (`2.3`).
426 #[derive(Clone, Debug)]
427 #[unstable(feature = "proc_macro", issue = "38356")]
428 pub struct Literal(token
::Token
);
430 #[unstable(feature = "proc_macro", issue = "38356")]
431 impl fmt
::Display
for Literal
{
432 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
433 TokenTree { kind: TokenNode::Literal(self.clone()), span: Span(DUMMY_SP) }
.fmt(f
)
437 macro_rules
! int_literals
{
438 ($
($int_kind
:ident
),*) => {$
(
440 #[unstable(feature = "proc_macro", issue = "38356")]
441 pub fn $
int_kind(n
: $int_kind
) -> Literal
{
442 Literal
::typed_integer(n
as i128
, stringify
!($int_kind
))
449 #[unstable(feature = "proc_macro", issue = "38356")]
450 pub fn integer(n
: i128
) -> Literal
{
451 Literal(token
::Literal(token
::Lit
::Integer(Symbol
::intern(&n
.to_string())), None
))
454 int_literals
!(u8, i8, u16, i16, u32, i32, u64, i64, usize, isize);
455 fn typed_integer(n
: i128
, kind
: &'
static str) -> Literal
{
456 Literal(token
::Literal(token
::Lit
::Integer(Symbol
::intern(&n
.to_string())),
457 Some(Symbol
::intern(kind
))))
460 /// Floating point literal.
461 #[unstable(feature = "proc_macro", issue = "38356")]
462 pub fn float(n
: f64) -> Literal
{
464 panic
!("Invalid float literal {}", n
);
466 Literal(token
::Literal(token
::Lit
::Float(Symbol
::intern(&n
.to_string())), None
))
469 /// Floating point literal.
470 #[unstable(feature = "proc_macro", issue = "38356")]
471 pub fn f32(n
: f32) -> Literal
{
473 panic
!("Invalid f32 literal {}", n
);
475 Literal(token
::Literal(token
::Lit
::Float(Symbol
::intern(&n
.to_string())),
476 Some(Symbol
::intern("f32"))))
479 /// Floating point literal.
480 #[unstable(feature = "proc_macro", issue = "38356")]
481 pub fn f64(n
: f64) -> Literal
{
483 panic
!("Invalid f64 literal {}", n
);
485 Literal(token
::Literal(token
::Lit
::Float(Symbol
::intern(&n
.to_string())),
486 Some(Symbol
::intern("f64"))))
490 #[unstable(feature = "proc_macro", issue = "38356")]
491 pub fn string(string
: &str) -> Literal
{
492 let mut escaped
= String
::new();
493 for ch
in string
.chars() {
494 escaped
.extend(ch
.escape_debug());
496 Literal(token
::Literal(token
::Lit
::Str_(Symbol
::intern(&escaped
)), None
))
499 /// Character literal.
500 #[unstable(feature = "proc_macro", issue = "38356")]
501 pub fn character(ch
: char) -> Literal
{
502 let mut escaped
= String
::new();
503 escaped
.extend(ch
.escape_unicode());
504 Literal(token
::Literal(token
::Lit
::Char(Symbol
::intern(&escaped
)), None
))
507 /// Byte string literal.
508 #[unstable(feature = "proc_macro", issue = "38356")]
509 pub fn byte_string(bytes
: &[u8]) -> Literal
{
510 let string
= bytes
.iter().cloned().flat_map(ascii
::escape_default
)
511 .map(Into
::<char>::into
).collect
::<String
>();
512 Literal(token
::Literal(token
::Lit
::ByteStr(Symbol
::intern(&string
)), None
))
516 /// An iterator over `TokenTree`s.
518 #[unstable(feature = "proc_macro", issue = "38356")]
519 pub struct TokenTreeIter
{
520 cursor
: tokenstream
::Cursor
,
521 next
: Option
<tokenstream
::TokenStream
>,
524 #[unstable(feature = "proc_macro", issue = "38356")]
525 impl Iterator
for TokenTreeIter
{
526 type Item
= TokenTree
;
528 fn next(&mut self) -> Option
<TokenTree
> {
531 unwrap_or
!(self.next
.take().or_else(|| self.cursor
.next_as_stream()), return None
);
532 let tree
= TokenTree
::from_internal(next
, &mut self.next
);
533 if tree
.span
.0 == DUMMY_SP
{
534 if let TokenNode
::Group(Delimiter
::None
, stream
) = tree
.kind
{
535 self.cursor
.insert(stream
.0);
545 fn from_internal(delim
: token
::DelimToken
) -> Delimiter
{
547 token
::Paren
=> Delimiter
::Parenthesis
,
548 token
::Brace
=> Delimiter
::Brace
,
549 token
::Bracket
=> Delimiter
::Bracket
,
550 token
::NoDelim
=> Delimiter
::None
,
554 fn to_internal(self) -> token
::DelimToken
{
556 Delimiter
::Parenthesis
=> token
::Paren
,
557 Delimiter
::Brace
=> token
::Brace
,
558 Delimiter
::Bracket
=> token
::Bracket
,
559 Delimiter
::None
=> token
::NoDelim
,
565 fn from_internal(stream
: tokenstream
::TokenStream
, next
: &mut Option
<tokenstream
::TokenStream
>)
567 use syntax
::parse
::token
::*;
569 let (tree
, is_joint
) = stream
.as_tree();
570 let (mut span
, token
) = match tree
{
571 tokenstream
::TokenTree
::Token(span
, token
) => (span
, token
),
572 tokenstream
::TokenTree
::Delimited(span
, delimed
) => {
573 let delimiter
= Delimiter
::from_internal(delimed
.delim
);
576 kind
: TokenNode
::Group(delimiter
, TokenStream(delimed
.tts
.into())),
581 let op_kind
= if is_joint { Spacing::Joint }
else { Spacing::Alone }
;
583 ($op
:expr
) => { TokenNode::Op($op, op_kind) }
587 ($first
:expr
, $rest
:expr
) => { joint($first, $rest, is_joint, &mut span, next) }
590 fn joint(first
: char, rest
: Token
, is_joint
: bool
, span
: &mut syntax_pos
::Span
,
591 next
: &mut Option
<tokenstream
::TokenStream
>)
593 let (first_span
, rest_span
) = (*span
, *span
);
595 let tree
= tokenstream
::TokenTree
::Token(rest_span
, rest
);
596 *next
= Some(if is_joint { tree.joint() }
else { tree.into() }
);
597 TokenNode
::Op(first
, Spacing
::Joint
)
600 let kind
= match token
{
603 Le
=> joint
!('
<'
, Eq
),
604 EqEq
=> joint
!('
='
, Eq
),
605 Ne
=> joint
!('
!'
, Eq
),
606 Ge
=> joint
!('
>'
, Eq
),
608 AndAnd
=> joint
!('
&'
, BinOp(And
)),
609 OrOr
=> joint
!('
|'
, BinOp(Or
)),
612 BinOp(Plus
) => op
!('
+'
),
613 BinOp(Minus
) => op
!('
-'
),
614 BinOp(Star
) => op
!('
*'
),
615 BinOp(Slash
) => op
!('
/'
),
616 BinOp(Percent
) => op
!('
%'
),
617 BinOp(Caret
) => op
!('
^'),
618 BinOp(And
) => op
!('
&'
),
619 BinOp(Or
) => op
!('
|'
),
620 BinOp(Shl
) => joint
!('
<'
, Lt
),
621 BinOp(Shr
) => joint
!('
>'
, Gt
),
622 BinOpEq(Plus
) => joint
!('
+'
, Eq
),
623 BinOpEq(Minus
) => joint
!('
-'
, Eq
),
624 BinOpEq(Star
) => joint
!('
*'
, Eq
),
625 BinOpEq(Slash
) => joint
!('
/'
, Eq
),
626 BinOpEq(Percent
) => joint
!('
%'
, Eq
),
627 BinOpEq(Caret
) => joint
!('
^', Eq
),
628 BinOpEq(And
) => joint
!('
&'
, Eq
),
629 BinOpEq(Or
) => joint
!('
|'
, Eq
),
630 BinOpEq(Shl
) => joint
!('
<'
, Le
),
631 BinOpEq(Shr
) => joint
!('
>'
, Ge
),
634 DotDot
=> joint
!('
.'
, Dot
),
635 DotDotDot
=> joint
!('
.'
, DotDot
),
636 DotDotEq
=> joint
!('
.'
, DotEq
),
640 ModSep
=> joint
!('
:'
, Colon
),
641 RArrow
=> joint
!('
-'
, Gt
),
642 LArrow
=> joint
!('
<'
, BinOp(Minus
)),
643 FatArrow
=> joint
!('
='
, Gt
),
646 Question
=> op
!('?'
),
647 Underscore
=> op
!('_'
),
649 Ident(ident
) | Lifetime(ident
) => TokenNode
::Term(Term(ident
.name
)),
650 Literal(..) | DocComment(..) => TokenNode
::Literal(self::Literal(token
)),
653 __internal
::with_sess(|(sess
, _
)| {
654 let tts
= token
.interpolated_to_tokenstream(sess
, span
);
655 TokenNode
::Group(Delimiter
::None
, TokenStream(tts
))
659 DotEq
=> unreachable
!(),
660 OpenDelim(..) | CloseDelim(..) => unreachable
!(),
661 Whitespace
| Comment
| Shebang(..) | Eof
=> unreachable
!(),
664 TokenTree { span: Span(span), kind: kind }
667 fn to_internal(self) -> tokenstream
::TokenStream
{
668 use syntax
::parse
::token
::*;
669 use syntax
::tokenstream
::{TokenTree, Delimited}
;
671 let (op
, kind
) = match self.kind
{
672 TokenNode
::Op(op
, kind
) => (op
, kind
),
673 TokenNode
::Group(delimiter
, tokens
) => {
674 return TokenTree
::Delimited(self.span
.0, Delimited
{
675 delim
: delimiter
.to_internal(),
676 tts
: tokens
.0.into
(),
679 TokenNode
::Term(symbol
) => {
680 let ident
= ast
::Ident { name: symbol.0, ctxt: self.span.0.ctxt() }
;
682 if symbol
.0.as_str().starts_with("'") { Lifetime(ident) }
else { Ident(ident) }
;
683 return TokenTree
::Token(self.span
.0, token
).into();
685 TokenNode
::Literal(token
) => return TokenTree
::Token(self.span
.0, token
.0).into(),
688 let token
= match op
{
698 '
%'
=> BinOp(Percent
),
711 _
=> panic
!("unsupported character {}", op
),
714 let tree
= TokenTree
::Token(self.span
.0, token
);
716 Spacing
::Alone
=> tree
.into(),
717 Spacing
::Joint
=> tree
.joint(),
722 /// Permanently unstable internal implementation details of this crate. This
723 /// should not be used.
725 /// These methods are used by the rest of the compiler to generate instances of
726 /// `TokenStream` to hand to macro definitions, as well as consume the output.
728 /// Note that this module is also intentionally separate from the rest of the
729 /// crate. This allows the `#[unstable]` directive below to naturally apply to
730 /// all of the contents.
731 #[unstable(feature = "proc_macro_internals", issue = "27812")]
734 pub use quote
::{LiteralKind, Quoter, unquote}
;
739 use syntax
::ext
::base
::ExtCtxt
;
740 use syntax
::ext
::hygiene
::Mark
;
742 use syntax
::parse
::{self, ParseSess}
;
743 use syntax
::parse
::token
::{self, Token}
;
744 use syntax
::tokenstream
;
745 use syntax_pos
::{BytePos, Loc, DUMMY_SP}
;
747 use super::{TokenStream, LexError}
;
749 pub fn lookup_char_pos(pos
: BytePos
) -> Loc
{
750 with_sess(|(sess
, _
)| sess
.codemap().lookup_char_pos(pos
))
753 pub fn new_token_stream(item
: P
<ast
::Item
>) -> TokenStream
{
754 let token
= Token
::interpolated(token
::NtItem(item
));
755 TokenStream(tokenstream
::TokenTree
::Token(DUMMY_SP
, token
).into())
758 pub fn token_stream_wrap(inner
: tokenstream
::TokenStream
) -> TokenStream
{
762 pub fn token_stream_parse_items(stream
: TokenStream
) -> Result
<Vec
<P
<ast
::Item
>>, LexError
> {
763 with_sess(move |(sess
, _
)| {
764 let mut parser
= parse
::stream_to_parser(sess
, stream
.0);
765 let mut items
= Vec
::new();
767 while let Some(item
) = try
!(parser
.parse_item().map_err(super::parse_to_lex_err
)) {
775 pub fn token_stream_inner(stream
: TokenStream
) -> tokenstream
::TokenStream
{
780 fn register_custom_derive(&mut self,
782 expand
: fn(TokenStream
) -> TokenStream
,
783 attributes
: &[&'
static str]);
785 fn register_attr_proc_macro(&mut self,
787 expand
: fn(TokenStream
, TokenStream
) -> TokenStream
);
789 fn register_bang_proc_macro(&mut self,
791 expand
: fn(TokenStream
) -> TokenStream
);
794 // Emulate scoped_thread_local!() here essentially
796 static CURRENT_SESS
: Cell
<(*const ParseSess
, Mark
)> =
797 Cell
::new((0 as *const _
, Mark
::root()));
800 pub fn set_sess
<F
, R
>(cx
: &ExtCtxt
, f
: F
) -> R
801 where F
: FnOnce() -> R
803 struct Reset { prev: (*const ParseSess, Mark) }
805 impl Drop
for Reset
{
807 CURRENT_SESS
.with(|p
| p
.set(self.prev
));
811 CURRENT_SESS
.with(|p
| {
812 let _reset
= Reset { prev: p.get() }
;
813 p
.set((cx
.parse_sess
, cx
.current_expansion
.mark
));
818 pub fn with_sess
<F
, R
>(f
: F
) -> R
819 where F
: FnOnce((&ParseSess
, Mark
)) -> R
821 let p
= CURRENT_SESS
.with(|p
| p
.get());
822 assert
!(!p
.0.is_null
(), "proc_macro::__internal::with_sess() called \
823 before set_parse_sess()!");
824 f(unsafe { (&*p.0, p.1) }
)
828 fn parse_to_lex_err(mut err
: DiagnosticBuilder
) -> LexError
{
830 LexError { _inner: () }