]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_ast/src/tokenstream.rs
Rollup merge of #96480 - user-simon:patch-1, r=Dylan-DPC
[rust.git] / compiler / rustc_ast / src / tokenstream.rs
1 //! # Token Streams
2 //!
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.
6 //!
7 //! ## Ownership
8 //!
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.
15
16 use crate::token::{self, Delimiter, Token, TokenKind};
17 use crate::AttrVec;
18
19 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
20 use rustc_data_structures::sync::{self, Lrc};
21 use rustc_macros::HashStable_Generic;
22 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
23 use rustc_span::{Span, DUMMY_SP};
24 use smallvec::{smallvec, SmallVec};
25
26 use std::{fmt, iter, mem};
27
28 /// When the main Rust parser encounters a syntax-extension invocation, it
29 /// parses the arguments to the invocation as a token tree. This is a very
30 /// loose structure, such that all sorts of different AST fragments can
31 /// be passed to syntax extensions using a uniform type.
32 ///
33 /// If the syntax extension is an MBE macro, it will attempt to match its
34 /// LHS token tree against the provided token tree, and if it finds a
35 /// match, will transcribe the RHS token tree, splicing in any captured
36 /// `macro_parser::matched_nonterminals` into the `SubstNt`s it finds.
37 ///
38 /// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
39 /// Nothing special happens to misnamed or misplaced `SubstNt`s.
40 #[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
41 pub enum TokenTree {
42     /// A single token.
43     Token(Token),
44     /// A delimited sequence of token trees.
45     Delimited(DelimSpan, Delimiter, TokenStream),
46 }
47
48 #[derive(Copy, Clone)]
49 pub enum CanSynthesizeMissingTokens {
50     Yes,
51     No,
52 }
53
54 // Ensure all fields of `TokenTree` is `Send` and `Sync`.
55 #[cfg(parallel_compiler)]
56 fn _dummy()
57 where
58     Token: Send + Sync,
59     DelimSpan: Send + Sync,
60     Delimiter: Send + Sync,
61     TokenStream: Send + Sync,
62 {
63 }
64
65 impl TokenTree {
66     /// Checks if this `TokenTree` is equal to the other, regardless of span information.
67     pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
68         match (self, other) {
69             (TokenTree::Token(token), TokenTree::Token(token2)) => token.kind == token2.kind,
70             (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
71                 delim == delim2 && tts.eq_unspanned(&tts2)
72             }
73             _ => false,
74         }
75     }
76
77     /// Retrieves the `TokenTree`'s span.
78     pub fn span(&self) -> Span {
79         match self {
80             TokenTree::Token(token) => token.span,
81             TokenTree::Delimited(sp, ..) => sp.entire(),
82         }
83     }
84
85     /// Modify the `TokenTree`'s span in-place.
86     pub fn set_span(&mut self, span: Span) {
87         match self {
88             TokenTree::Token(token) => token.span = span,
89             TokenTree::Delimited(dspan, ..) => *dspan = DelimSpan::from_single(span),
90         }
91     }
92
93     pub fn token(kind: TokenKind, span: Span) -> TokenTree {
94         TokenTree::Token(Token::new(kind, span))
95     }
96
97     pub fn uninterpolate(self) -> TokenTree {
98         match self {
99             TokenTree::Token(token) => TokenTree::Token(token.uninterpolate().into_owned()),
100             tt => tt,
101         }
102     }
103 }
104
105 impl<CTX> HashStable<CTX> for TokenStream
106 where
107     CTX: crate::HashStableContext,
108 {
109     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
110         for sub_tt in self.trees() {
111             sub_tt.hash_stable(hcx, hasher);
112         }
113     }
114 }
115
116 pub trait CreateTokenStream: sync::Send + sync::Sync {
117     fn create_token_stream(&self) -> AttrAnnotatedTokenStream;
118 }
119
120 impl CreateTokenStream for AttrAnnotatedTokenStream {
121     fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
122         self.clone()
123     }
124 }
125
126 /// A lazy version of [`TokenStream`], which defers creation
127 /// of an actual `TokenStream` until it is needed.
128 /// `Box` is here only to reduce the structure size.
129 #[derive(Clone)]
130 pub struct LazyTokenStream(Lrc<Box<dyn CreateTokenStream>>);
131
132 impl LazyTokenStream {
133     pub fn new(inner: impl CreateTokenStream + 'static) -> LazyTokenStream {
134         LazyTokenStream(Lrc::new(Box::new(inner)))
135     }
136
137     pub fn create_token_stream(&self) -> AttrAnnotatedTokenStream {
138         self.0.create_token_stream()
139     }
140 }
141
142 impl fmt::Debug for LazyTokenStream {
143     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144         write!(f, "LazyTokenStream({:?})", self.create_token_stream())
145     }
146 }
147
148 impl<S: Encoder> Encodable<S> for LazyTokenStream {
149     fn encode(&self, s: &mut S) -> Result<(), S::Error> {
150         // Used by AST json printing.
151         Encodable::encode(&self.create_token_stream(), s)
152     }
153 }
154
155 impl<D: Decoder> Decodable<D> for LazyTokenStream {
156     fn decode(_d: &mut D) -> Self {
157         panic!("Attempted to decode LazyTokenStream");
158     }
159 }
160
161 impl<CTX> HashStable<CTX> for LazyTokenStream {
162     fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
163         panic!("Attempted to compute stable hash for LazyTokenStream");
164     }
165 }
166
167 /// A `AttrAnnotatedTokenStream` is similar to a `TokenStream`, but with extra
168 /// information about the tokens for attribute targets. This is used
169 /// during expansion to perform early cfg-expansion, and to process attributes
170 /// during proc-macro invocations.
171 #[derive(Clone, Debug, Default, Encodable, Decodable)]
172 pub struct AttrAnnotatedTokenStream(pub Lrc<Vec<(AttrAnnotatedTokenTree, Spacing)>>);
173
174 /// Like `TokenTree`, but for `AttrAnnotatedTokenStream`
175 #[derive(Clone, Debug, Encodable, Decodable)]
176 pub enum AttrAnnotatedTokenTree {
177     Token(Token),
178     Delimited(DelimSpan, Delimiter, AttrAnnotatedTokenStream),
179     /// Stores the attributes for an attribute target,
180     /// along with the tokens for that attribute target.
181     /// See `AttributesData` for more information
182     Attributes(AttributesData),
183 }
184
185 impl AttrAnnotatedTokenStream {
186     pub fn new(tokens: Vec<(AttrAnnotatedTokenTree, Spacing)>) -> AttrAnnotatedTokenStream {
187         AttrAnnotatedTokenStream(Lrc::new(tokens))
188     }
189
190     /// Converts this `AttrAnnotatedTokenStream` to a plain `TokenStream
191     /// During conversion, `AttrAnnotatedTokenTree::Attributes` get 'flattened'
192     /// back to a `TokenStream` of the form `outer_attr attr_target`.
193     /// If there are inner attributes, they are inserted into the proper
194     /// place in the attribute target tokens.
195     pub fn to_tokenstream(&self) -> TokenStream {
196         let trees: Vec<_> = self
197             .0
198             .iter()
199             .flat_map(|tree| match &tree.0 {
200                 AttrAnnotatedTokenTree::Token(inner) => {
201                     smallvec![(TokenTree::Token(inner.clone()), tree.1)].into_iter()
202                 }
203                 AttrAnnotatedTokenTree::Delimited(span, delim, stream) => smallvec![(
204                     TokenTree::Delimited(*span, *delim, stream.to_tokenstream()),
205                     tree.1,
206                 )]
207                 .into_iter(),
208                 AttrAnnotatedTokenTree::Attributes(data) => {
209                     let mut outer_attrs = Vec::new();
210                     let mut inner_attrs = Vec::new();
211                     for attr in &data.attrs {
212                         match attr.style {
213                             crate::AttrStyle::Outer => {
214                                 outer_attrs.push(attr);
215                             }
216                             crate::AttrStyle::Inner => {
217                                 inner_attrs.push(attr);
218                             }
219                         }
220                     }
221
222                     let mut target_tokens: Vec<_> = data
223                         .tokens
224                         .create_token_stream()
225                         .to_tokenstream()
226                         .0
227                         .iter()
228                         .cloned()
229                         .collect();
230                     if !inner_attrs.is_empty() {
231                         let mut found = false;
232                         // Check the last two trees (to account for a trailing semi)
233                         for (tree, _) in target_tokens.iter_mut().rev().take(2) {
234                             if let TokenTree::Delimited(span, delim, delim_tokens) = tree {
235                                 // Inner attributes are only supported on extern blocks, functions, impls,
236                                 // and modules. All of these have their inner attributes placed at
237                                 // the beginning of the rightmost outermost braced group:
238                                 // e.g. fn foo() { #![my_attr} }
239                                 //
240                                 // Therefore, we can insert them back into the right location
241                                 // without needing to do any extra position tracking.
242                                 //
243                                 // Note: Outline modules are an exception - they can
244                                 // have attributes like `#![my_attr]` at the start of a file.
245                                 // Support for custom attributes in this position is not
246                                 // properly implemented - we always synthesize fake tokens,
247                                 // so we never reach this code.
248
249                                 let mut builder = TokenStreamBuilder::new();
250                                 for inner_attr in inner_attrs {
251                                     builder.push(inner_attr.tokens().to_tokenstream());
252                                 }
253                                 builder.push(delim_tokens.clone());
254                                 *tree = TokenTree::Delimited(*span, *delim, builder.build());
255                                 found = true;
256                                 break;
257                             }
258                         }
259
260                         assert!(
261                             found,
262                             "Failed to find trailing delimited group in: {:?}",
263                             target_tokens
264                         );
265                     }
266                     let mut flat: SmallVec<[_; 1]> = SmallVec::new();
267                     for attr in outer_attrs {
268                         // FIXME: Make this more efficient
269                         flat.extend(attr.tokens().to_tokenstream().0.clone().iter().cloned());
270                     }
271                     flat.extend(target_tokens);
272                     flat.into_iter()
273                 }
274             })
275             .collect();
276         TokenStream::new(trees)
277     }
278 }
279
280 /// Stores the tokens for an attribute target, along
281 /// with its attributes.
282 ///
283 /// This is constructed during parsing when we need to capture
284 /// tokens.
285 ///
286 /// For example, `#[cfg(FALSE)] struct Foo {}` would
287 /// have an `attrs` field containing the `#[cfg(FALSE)]` attr,
288 /// and a `tokens` field storing the (unparsed) tokens `struct Foo {}`
289 #[derive(Clone, Debug, Encodable, Decodable)]
290 pub struct AttributesData {
291     /// Attributes, both outer and inner.
292     /// These are stored in the original order that they were parsed in.
293     pub attrs: AttrVec,
294     /// The underlying tokens for the attribute target that `attrs`
295     /// are applied to
296     pub tokens: LazyTokenStream,
297 }
298
299 /// A `TokenStream` is an abstract sequence of tokens, organized into [`TokenTree`]s.
300 ///
301 /// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
302 /// instead of a representation of the abstract syntax tree.
303 /// Today's `TokenTree`s can still contain AST via `token::Interpolated` for
304 /// backwards compatibility.
305 #[derive(Clone, Debug, Default, Encodable, Decodable)]
306 pub struct TokenStream(pub(crate) Lrc<Vec<TreeAndSpacing>>);
307
308 pub type TreeAndSpacing = (TokenTree, Spacing);
309
310 // `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
311 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
312 rustc_data_structures::static_assert_size!(TokenStream, 8);
313
314 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
315 pub enum Spacing {
316     Alone,
317     Joint,
318 }
319
320 impl TokenStream {
321     /// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
322     /// separating the two arguments with a comma for diagnostic suggestions.
323     pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
324         // Used to suggest if a user writes `foo!(a b);`
325         let mut suggestion = None;
326         let mut iter = self.0.iter().enumerate().peekable();
327         while let Some((pos, ts)) = iter.next() {
328             if let Some((_, next)) = iter.peek() {
329                 let sp = match (&ts, &next) {
330                     (_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
331                     (
332                         (TokenTree::Token(token_left), Spacing::Alone),
333                         (TokenTree::Token(token_right), _),
334                     ) if ((token_left.is_ident() && !token_left.is_reserved_ident())
335                         || token_left.is_lit())
336                         && ((token_right.is_ident() && !token_right.is_reserved_ident())
337                             || token_right.is_lit()) =>
338                     {
339                         token_left.span
340                     }
341                     ((TokenTree::Delimited(sp, ..), Spacing::Alone), _) => sp.entire(),
342                     _ => continue,
343                 };
344                 let sp = sp.shrink_to_hi();
345                 let comma = (TokenTree::token(token::Comma, sp), Spacing::Alone);
346                 suggestion = Some((pos, comma, sp));
347             }
348         }
349         if let Some((pos, comma, sp)) = suggestion {
350             let mut new_stream = Vec::with_capacity(self.0.len() + 1);
351             let parts = self.0.split_at(pos + 1);
352             new_stream.extend_from_slice(parts.0);
353             new_stream.push(comma);
354             new_stream.extend_from_slice(parts.1);
355             return Some((TokenStream::new(new_stream), sp));
356         }
357         None
358     }
359 }
360
361 impl From<(AttrAnnotatedTokenTree, Spacing)> for AttrAnnotatedTokenStream {
362     fn from((tree, spacing): (AttrAnnotatedTokenTree, Spacing)) -> AttrAnnotatedTokenStream {
363         AttrAnnotatedTokenStream::new(vec![(tree, spacing)])
364     }
365 }
366
367 impl From<TokenTree> for TokenStream {
368     fn from(tree: TokenTree) -> TokenStream {
369         TokenStream::new(vec![(tree, Spacing::Alone)])
370     }
371 }
372
373 impl From<TokenTree> for TreeAndSpacing {
374     fn from(tree: TokenTree) -> TreeAndSpacing {
375         (tree, Spacing::Alone)
376     }
377 }
378
379 impl iter::FromIterator<TokenTree> for TokenStream {
380     fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
381         TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndSpacing>>())
382     }
383 }
384
385 impl Eq for TokenStream {}
386
387 impl PartialEq<TokenStream> for TokenStream {
388     fn eq(&self, other: &TokenStream) -> bool {
389         self.trees().eq(other.trees())
390     }
391 }
392
393 impl TokenStream {
394     pub fn new(streams: Vec<TreeAndSpacing>) -> TokenStream {
395         TokenStream(Lrc::new(streams))
396     }
397
398     pub fn is_empty(&self) -> bool {
399         self.0.is_empty()
400     }
401
402     pub fn len(&self) -> usize {
403         self.0.len()
404     }
405
406     pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
407         match streams.len() {
408             0 => TokenStream::default(),
409             1 => streams.pop().unwrap(),
410             _ => {
411                 // We are going to extend the first stream in `streams` with
412                 // the elements from the subsequent streams. This requires
413                 // using `make_mut()` on the first stream, and in practice this
414                 // doesn't cause cloning 99.9% of the time.
415                 //
416                 // One very common use case is when `streams` has two elements,
417                 // where the first stream has any number of elements within
418                 // (often 1, but sometimes many more) and the second stream has
419                 // a single element within.
420
421                 // Determine how much the first stream will be extended.
422                 // Needed to avoid quadratic blow up from on-the-fly
423                 // reallocations (#57735).
424                 let num_appends = streams.iter().skip(1).map(|ts| ts.len()).sum();
425
426                 // Get the first stream. If it's `None`, create an empty
427                 // stream.
428                 let mut iter = streams.drain(..);
429                 let mut first_stream_lrc = iter.next().unwrap().0;
430
431                 // Append the elements to the first stream, after reserving
432                 // space for them.
433                 let first_vec_mut = Lrc::make_mut(&mut first_stream_lrc);
434                 first_vec_mut.reserve(num_appends);
435                 for stream in iter {
436                     first_vec_mut.extend(stream.0.iter().cloned());
437                 }
438
439                 // Create the final `TokenStream`.
440                 TokenStream(first_stream_lrc)
441             }
442         }
443     }
444
445     pub fn trees(&self) -> Cursor {
446         self.clone().into_trees()
447     }
448
449     pub fn into_trees(self) -> Cursor {
450         Cursor::new(self)
451     }
452
453     /// Compares two `TokenStream`s, checking equality without regarding span information.
454     pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
455         let mut t1 = self.trees();
456         let mut t2 = other.trees();
457         for (t1, t2) in iter::zip(&mut t1, &mut t2) {
458             if !t1.eq_unspanned(&t2) {
459                 return false;
460             }
461         }
462         t1.next().is_none() && t2.next().is_none()
463     }
464
465     pub fn map_enumerated<F: FnMut(usize, &TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
466         TokenStream(Lrc::new(
467             self.0
468                 .iter()
469                 .enumerate()
470                 .map(|(i, (tree, is_joint))| (f(i, tree), *is_joint))
471                 .collect(),
472         ))
473     }
474 }
475
476 // 99.5%+ of the time we have 1 or 2 elements in this vector.
477 #[derive(Clone)]
478 pub struct TokenStreamBuilder(SmallVec<[TokenStream; 2]>);
479
480 impl TokenStreamBuilder {
481     pub fn new() -> TokenStreamBuilder {
482         TokenStreamBuilder(SmallVec::new())
483     }
484
485     pub fn push<T: Into<TokenStream>>(&mut self, stream: T) {
486         let mut stream = stream.into();
487
488         // If `self` is not empty and the last tree within the last stream is a
489         // token tree marked with `Joint`...
490         if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut()
491             && let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last()
492             // ...and `stream` is not empty and the first tree within it is
493             // a token tree...
494             && let TokenStream(ref mut stream_lrc) = stream
495             && let Some((TokenTree::Token(token), spacing)) = stream_lrc.first()
496             // ...and the two tokens can be glued together...
497             && let Some(glued_tok) = last_token.glue(&token)
498         {
499             // ...then do so, by overwriting the last token
500             // tree in `self` and removing the first token tree
501             // from `stream`. This requires using `make_mut()`
502             // on the last stream in `self` and on `stream`,
503             // and in practice this doesn't cause cloning 99.9%
504             // of the time.
505
506             // Overwrite the last token tree with the merged
507             // token.
508             let last_vec_mut = Lrc::make_mut(last_stream_lrc);
509             *last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
510
511             // Remove the first token tree from `stream`. (This
512             // is almost always the only tree in `stream`.)
513             let stream_vec_mut = Lrc::make_mut(stream_lrc);
514             stream_vec_mut.remove(0);
515
516             // Don't push `stream` if it's empty -- that could
517             // block subsequent token gluing, by getting
518             // between two token trees that should be glued
519             // together.
520             if !stream.is_empty() {
521                 self.0.push(stream);
522             }
523             return;
524         }
525         self.0.push(stream);
526     }
527
528     pub fn build(self) -> TokenStream {
529         TokenStream::from_streams(self.0)
530     }
531 }
532
533 /// By-reference iterator over a [`TokenStream`].
534 #[derive(Clone)]
535 pub struct CursorRef<'t> {
536     stream: &'t TokenStream,
537     index: usize,
538 }
539
540 impl<'t> CursorRef<'t> {
541     fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> {
542         self.stream.0.get(self.index).map(|tree| {
543             self.index += 1;
544             tree
545         })
546     }
547 }
548
549 impl<'t> Iterator for CursorRef<'t> {
550     type Item = &'t TokenTree;
551
552     fn next(&mut self) -> Option<&'t TokenTree> {
553         self.next_with_spacing().map(|(tree, _)| tree)
554     }
555 }
556
557 /// Owning by-value iterator over a [`TokenStream`].
558 // FIXME: Many uses of this can be replaced with by-reference iterator to avoid clones.
559 #[derive(Clone)]
560 pub struct Cursor {
561     pub stream: TokenStream,
562     index: usize,
563 }
564
565 impl Iterator for Cursor {
566     type Item = TokenTree;
567
568     fn next(&mut self) -> Option<TokenTree> {
569         self.next_with_spacing().map(|(tree, _)| tree)
570     }
571 }
572
573 impl Cursor {
574     fn new(stream: TokenStream) -> Self {
575         Cursor { stream, index: 0 }
576     }
577
578     #[inline]
579     pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> {
580         self.stream.0.get(self.index).map(|tree| {
581             self.index += 1;
582             tree.clone()
583         })
584     }
585
586     #[inline]
587     pub fn next_with_spacing_ref(&mut self) -> Option<&TreeAndSpacing> {
588         self.stream.0.get(self.index).map(|tree| {
589             self.index += 1;
590             tree
591         })
592     }
593
594     pub fn index(&self) -> usize {
595         self.index
596     }
597
598     pub fn append(&mut self, new_stream: TokenStream) {
599         if new_stream.is_empty() {
600             return;
601         }
602         let index = self.index;
603         let stream = mem::take(&mut self.stream);
604         *self = TokenStream::from_streams(smallvec![stream, new_stream]).into_trees();
605         self.index = index;
606     }
607
608     pub fn look_ahead(&self, n: usize) -> Option<&TokenTree> {
609         self.stream.0[self.index..].get(n).map(|(tree, _)| tree)
610     }
611 }
612
613 #[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
614 pub struct DelimSpan {
615     pub open: Span,
616     pub close: Span,
617 }
618
619 impl DelimSpan {
620     pub fn from_single(sp: Span) -> Self {
621         DelimSpan { open: sp, close: sp }
622     }
623
624     pub fn from_pair(open: Span, close: Span) -> Self {
625         DelimSpan { open, close }
626     }
627
628     pub fn dummy() -> Self {
629         Self::from_single(DUMMY_SP)
630     }
631
632     pub fn entire(self) -> Span {
633         self.open.with_hi(self.close.hi())
634     }
635 }