3 //! `TokenStream`s represent syntactic objects before they are converted into ASTs.
4 //! A `TokenStream` is, roughly speaking, a sequence of [`TokenTree`]s,
5 //! which are themselves a single [`Token`] or a `Delimited` subsequence of tokens.
9 //! `TokenStream`s are persistent data structures constructed as ropes with reference
10 //! counted-children. In general, this means that calling an operation on a `TokenStream`
11 //! (such as `slice`) produces an entirely new `TokenStream` from the borrowed reference to
12 //! the original. This essentially coerces `TokenStream`s into "views" of their subparts,
13 //! and a borrowed `TokenStream` is sufficient to build an owned `TokenStream` without taking
14 //! ownership of the original.
16 use crate::token
::{self, DelimToken, Token, TokenKind}
;
18 use rustc_data_structures
::stable_hasher
::{HashStable, StableHasher}
;
19 use rustc_data_structures
::sync
::{self, Lrc}
;
20 use rustc_macros
::HashStable_Generic
;
21 use rustc_serialize
::{Decodable, Decoder, Encodable, Encoder}
;
22 use rustc_span
::{Span, DUMMY_SP}
;
23 use smallvec
::{smallvec, SmallVec}
;
25 use std
::{fmt, iter, mem}
;
27 /// When the main Rust parser encounters a syntax-extension invocation, it
28 /// parses the arguments to the invocation as a token tree. This is a very
29 /// loose structure, such that all sorts of different AST fragments can
30 /// be passed to syntax extensions using a uniform type.
32 /// If the syntax extension is an MBE macro, it will attempt to match its
33 /// LHS token tree against the provided token tree, and if it finds a
34 /// match, will transcribe the RHS token tree, splicing in any captured
35 /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
37 /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
38 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
39 #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
43 /// A delimited sequence of token trees.
44 Delimited(DelimSpan
, DelimToken
, TokenStream
),
47 #[derive(Copy, Clone)]
48 pub enum CanSynthesizeMissingTokens
{
53 // Ensure all fields of `TokenTree` is `Send` and `Sync`.
54 #[cfg(parallel_compiler)]
58 DelimSpan
: Send
+ Sync
,
59 DelimToken
: Send
+ Sync
,
60 TokenStream
: Send
+ Sync
,
65 /// Checks if this `TokenTree` is equal to the other, regardless of span information.
66 pub fn eq_unspanned(&self, other
: &TokenTree
) -> bool
{
68 (TokenTree
::Token(token
), TokenTree
::Token(token2
)) => token
.kind
== token2
.kind
,
69 (TokenTree
::Delimited(_
, delim
, tts
), TokenTree
::Delimited(_
, delim2
, tts2
)) => {
70 delim
== delim2
&& tts
.eq_unspanned(&tts2
)
76 /// Retrieves the `TokenTree`'s span.
77 pub fn span(&self) -> Span
{
79 TokenTree
::Token(token
) => token
.span
,
80 TokenTree
::Delimited(sp
, ..) => sp
.entire(),
84 /// Modify the `TokenTree`'s span in-place.
85 pub fn set_span(&mut self, span
: Span
) {
87 TokenTree
::Token(token
) => token
.span
= span
,
88 TokenTree
::Delimited(dspan
, ..) => *dspan
= DelimSpan
::from_single(span
),
92 pub fn joint(self) -> TokenStream
{
93 TokenStream
::new(vec
![(self, Spacing
::Joint
)])
96 pub fn token(kind
: TokenKind
, span
: Span
) -> TokenTree
{
97 TokenTree
::Token(Token
::new(kind
, span
))
100 /// Returns the opening delimiter as a token tree.
101 pub fn open_tt(span
: DelimSpan
, delim
: DelimToken
) -> TokenTree
{
102 TokenTree
::token(token
::OpenDelim(delim
), span
.open
)
105 /// Returns the closing delimiter as a token tree.
106 pub fn close_tt(span
: DelimSpan
, delim
: DelimToken
) -> TokenTree
{
107 TokenTree
::token(token
::CloseDelim(delim
), span
.close
)
110 pub fn uninterpolate(self) -> TokenTree
{
112 TokenTree
::Token(token
) => TokenTree
::Token(token
.uninterpolate().into_owned()),
118 impl<CTX
> HashStable
<CTX
> for TokenStream
120 CTX
: crate::HashStableContext
,
122 fn hash_stable(&self, hcx
: &mut CTX
, hasher
: &mut StableHasher
) {
123 for sub_tt
in self.trees() {
124 sub_tt
.hash_stable(hcx
, hasher
);
129 pub trait CreateTokenStream
: sync
::Send
+ sync
::Sync
{
130 fn create_token_stream(&self) -> TokenStream
;
133 impl CreateTokenStream
for TokenStream
{
134 fn create_token_stream(&self) -> TokenStream
{
139 /// A lazy version of [`TokenStream`], which defers creation
140 /// of an actual `TokenStream` until it is needed.
141 /// `Box` is here only to reduce the structure size.
143 pub struct LazyTokenStream(Lrc
<Box
<dyn CreateTokenStream
>>);
145 impl LazyTokenStream
{
146 pub fn new(inner
: impl CreateTokenStream
+ '
static) -> LazyTokenStream
{
147 LazyTokenStream(Lrc
::new(Box
::new(inner
)))
150 pub fn create_token_stream(&self) -> TokenStream
{
151 self.0.create_token_stream()
155 impl fmt
::Debug
for LazyTokenStream
{
156 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
157 fmt
::Debug
::fmt("LazyTokenStream", f
)
161 impl<S
: Encoder
> Encodable
<S
> for LazyTokenStream
{
162 fn encode(&self, s
: &mut S
) -> Result
<(), S
::Error
> {
163 // Used by AST json printing.
164 Encodable
::encode(&self.create_token_stream(), s
)
168 impl<D
: Decoder
> Decodable
<D
> for LazyTokenStream
{
169 fn decode(_d
: &mut D
) -> Result
<Self, D
::Error
> {
170 panic
!("Attempted to decode LazyTokenStream");
174 impl<CTX
> HashStable
<CTX
> for LazyTokenStream
{
175 fn hash_stable(&self, _hcx
: &mut CTX
, _hasher
: &mut StableHasher
) {
176 panic
!("Attempted to compute stable hash for LazyTokenStream");
180 /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
182 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
183 /// instead of a representation of the abstract syntax tree.
184 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
185 /// backwards compatability.
186 #[derive(Clone, Debug, Default, Encodable, Decodable)]
187 pub struct TokenStream(pub(crate) Lrc
<Vec
<TreeAndSpacing
>>);
189 pub type TreeAndSpacing
= (TokenTree
, Spacing
);
191 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
192 #[cfg(target_arch = "x86_64")]
193 rustc_data_structures
::static_assert_size
!(TokenStream
, 8);
195 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
202 /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
203 /// separating the two arguments with a comma for diagnostic suggestions.
204 pub fn add_comma(&self) -> Option
<(TokenStream
, Span
)> {
205 // Used to suggest if a user writes `foo!(a b);`
206 let mut suggestion
= None
;
207 let mut iter
= self.0.iter
().enumerate().peekable();
208 while let Some((pos
, ts
)) = iter
.next() {
209 if let Some((_
, next
)) = iter
.peek() {
210 let sp
= match (&ts
, &next
) {
211 (_
, (TokenTree
::Token(Token { kind: token::Comma, .. }
), _
)) => continue,
213 (TokenTree
::Token(token_left
), Spacing
::Alone
),
214 (TokenTree
::Token(token_right
), _
),
215 ) if ((token_left
.is_ident() && !token_left
.is_reserved_ident())
216 || token_left
.is_lit())
217 && ((token_right
.is_ident() && !token_right
.is_reserved_ident())
218 || token_right
.is_lit()) =>
222 ((TokenTree
::Delimited(sp
, ..), Spacing
::Alone
), _
) => sp
.entire(),
225 let sp
= sp
.shrink_to_hi();
226 let comma
= (TokenTree
::token(token
::Comma
, sp
), Spacing
::Alone
);
227 suggestion
= Some((pos
, comma
, sp
));
230 if let Some((pos
, comma
, sp
)) = suggestion
{
231 let mut new_stream
= Vec
::with_capacity(self.0.len() + 1);
232 let parts
= self.0.split_at(pos
+ 1);
233 new_stream
.extend_from_slice(parts
.0);
234 new_stream
.push(comma
);
235 new_stream
.extend_from_slice(parts
.1);
236 return Some((TokenStream
::new(new_stream
), sp
));
242 impl From
<TokenTree
> for TokenStream
{
243 fn from(tree
: TokenTree
) -> TokenStream
{
244 TokenStream
::new(vec
![(tree
, Spacing
::Alone
)])
248 impl From
<TokenTree
> for TreeAndSpacing
{
249 fn from(tree
: TokenTree
) -> TreeAndSpacing
{
250 (tree
, Spacing
::Alone
)
254 impl iter
::FromIterator
<TokenTree
> for TokenStream
{
255 fn from_iter
<I
: IntoIterator
<Item
= TokenTree
>>(iter
: I
) -> Self {
256 TokenStream
::new(iter
.into_iter().map(Into
::into
).collect
::<Vec
<TreeAndSpacing
>>())
260 impl Eq
for TokenStream {}
262 impl PartialEq
<TokenStream
> for TokenStream
{
263 fn eq(&self, other
: &TokenStream
) -> bool
{
264 self.trees().eq(other
.trees())
269 pub fn new(streams
: Vec
<TreeAndSpacing
>) -> TokenStream
{
270 TokenStream(Lrc
::new(streams
))
273 pub fn is_empty(&self) -> bool
{
277 pub fn len(&self) -> usize {
281 pub fn span(&self) -> Option
<Span
> {
284 [(tt
, _
)] => Some(tt
.span()),
285 [(tt_start
, _
), .., (tt_end
, _
)] => Some(tt_start
.span().to(tt_end
.span())),
289 pub fn from_streams(mut streams
: SmallVec
<[TokenStream
; 2]>) -> TokenStream
{
290 match streams
.len() {
291 0 => TokenStream
::default(),
292 1 => streams
.pop().unwrap(),
294 // We are going to extend the first stream in `streams` with
295 // the elements from the subsequent streams. This requires
296 // using `make_mut()` on the first stream, and in practice this
297 // doesn't cause cloning 99.9% of the time.
299 // One very common use case is when `streams` has two elements,
300 // where the first stream has any number of elements within
301 // (often 1, but sometimes many more) and the second stream has
302 // a single element within.
304 // Determine how much the first stream will be extended.
305 // Needed to avoid quadratic blow up from on-the-fly
306 // reallocations (#57735).
307 let num_appends
= streams
.iter().skip(1).map(|ts
| ts
.len()).sum();
309 // Get the first stream. If it's `None`, create an empty
311 let mut iter
= streams
.drain(..);
312 let mut first_stream_lrc
= iter
.next().unwrap().0;
314 // Append the elements to the first stream, after reserving
316 let first_vec_mut
= Lrc
::make_mut(&mut first_stream_lrc
);
317 first_vec_mut
.reserve(num_appends
);
319 first_vec_mut
.extend(stream
.0.iter
().cloned());
322 // Create the final `TokenStream`.
323 TokenStream(first_stream_lrc
)
328 pub fn trees_ref(&self) -> CursorRef
<'_
> {
332 pub fn trees(&self) -> Cursor
{
333 self.clone().into_trees()
336 pub fn into_trees(self) -> Cursor
{
340 /// Compares two `TokenStream`s, checking equality without regarding span information.
341 pub fn eq_unspanned(&self, other
: &TokenStream
) -> bool
{
342 let mut t1
= self.trees();
343 let mut t2
= other
.trees();
344 for (t1
, t2
) in t1
.by_ref().zip(t2
.by_ref()) {
345 if !t1
.eq_unspanned(&t2
) {
349 t1
.next().is_none() && t2
.next().is_none()
352 pub fn map_enumerated
<F
: FnMut(usize, &TokenTree
) -> TokenTree
>(self, mut f
: F
) -> TokenStream
{
353 TokenStream(Lrc
::new(
357 .map(|(i
, (tree
, is_joint
))| (f(i
, tree
), *is_joint
))
363 // 99.5%+ of the time we have 1 or 2 elements in this vector.
365 pub struct TokenStreamBuilder(SmallVec
<[TokenStream
; 2]>);
367 impl TokenStreamBuilder
{
368 pub fn new() -> TokenStreamBuilder
{
369 TokenStreamBuilder(SmallVec
::new())
372 pub fn push
<T
: Into
<TokenStream
>>(&mut self, stream
: T
) {
373 let mut stream
= stream
.into();
375 // If `self` is not empty and the last tree within the last stream is a
376 // token tree marked with `Joint`...
377 if let Some(TokenStream(ref mut last_stream_lrc
)) = self.0.last_mut() {
378 if let Some((TokenTree
::Token(last_token
), Spacing
::Joint
)) = last_stream_lrc
.last() {
379 // ...and `stream` is not empty and the first tree within it is
381 let TokenStream(ref mut stream_lrc
) = stream
;
382 if let Some((TokenTree
::Token(token
), spacing
)) = stream_lrc
.first() {
383 // ...and the two tokens can be glued together...
384 if let Some(glued_tok
) = last_token
.glue(&token
) {
385 // ...then do so, by overwriting the last token
386 // tree in `self` and removing the first token tree
387 // from `stream`. This requires using `make_mut()`
388 // on the last stream in `self` and on `stream`,
389 // and in practice this doesn't cause cloning 99.9%
392 // Overwrite the last token tree with the merged
394 let last_vec_mut
= Lrc
::make_mut(last_stream_lrc
);
395 *last_vec_mut
.last_mut().unwrap() = (TokenTree
::Token(glued_tok
), *spacing
);
397 // Remove the first token tree from `stream`. (This
398 // is almost always the only tree in `stream`.)
399 let stream_vec_mut
= Lrc
::make_mut(stream_lrc
);
400 stream_vec_mut
.remove(0);
402 // Don't push `stream` if it's empty -- that could
403 // block subsequent token gluing, by getting
404 // between two token trees that should be glued
406 if !stream
.is_empty() {
417 pub fn build(self) -> TokenStream
{
418 TokenStream
::from_streams(self.0)
422 /// By-reference iterator over a [`TokenStream`].
424 pub struct CursorRef
<'t
> {
425 stream
: &'t TokenStream
,
429 impl<'t
> CursorRef
<'t
> {
430 fn new(stream
: &TokenStream
) -> CursorRef
<'_
> {
431 CursorRef { stream, index: 0 }
434 fn next_with_spacing(&mut self) -> Option
<&'t TreeAndSpacing
> {
435 self.stream
.0.get(self.index
).map(|tree
| {
442 impl<'t
> Iterator
for CursorRef
<'t
> {
443 type Item
= &'t TokenTree
;
445 fn next(&mut self) -> Option
<&'t TokenTree
> {
446 self.next_with_spacing().map(|(tree
, _
)| tree
)
450 /// Owning by-value iterator over a [`TokenStream`].
451 // FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
454 pub stream
: TokenStream
,
458 impl Iterator
for Cursor
{
459 type Item
= TokenTree
;
461 fn next(&mut self) -> Option
<TokenTree
> {
462 self.next_with_spacing().map(|(tree
, _
)| tree
)
467 fn new(stream
: TokenStream
) -> Self {
468 Cursor { stream, index: 0 }
471 pub fn next_with_spacing(&mut self) -> Option
<TreeAndSpacing
> {
472 if self.index
< self.stream
.len() {
474 Some(self.stream
.0[self.index
- 1].clone())
480 pub fn append(&mut self, new_stream
: TokenStream
) {
481 if new_stream
.is_empty() {
484 let index
= self.index
;
485 let stream
= mem
::take(&mut self.stream
);
486 *self = TokenStream
::from_streams(smallvec
![stream
, new_stream
]).into_trees();
490 pub fn look_ahead(&self, n
: usize) -> Option
<&TokenTree
> {
491 self.stream
.0[self.index
..].get(n
).map(|(tree
, _
)| tree
)
495 #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
496 pub struct DelimSpan
{
502 pub fn from_single(sp
: Span
) -> Self {
503 DelimSpan { open: sp, close: sp }
506 pub fn from_pair(open
: Span
, close
: Span
) -> Self {
507 DelimSpan { open, close }
510 pub fn dummy() -> Self {
511 Self::from_single(DUMMY_SP
)
514 pub fn entire(self) -> Span
{
515 self.open
.with_hi(self.close
.hi())