1use std::borrow::Cow;
17use std::sync::Arc;
18use std::{cmp, fmt, iter};
19
20use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
21use rustc_data_structures::sync;
22use rustc_macros::{Decodable, Encodable, HashStable_Generic};
23use rustc_serialize::{Decodable, Encodable};
24use rustc_span::{DUMMY_SP, Span, SpanDecoder, SpanEncoder, Symbol, sym};
25
26use crate::ast::{AttrStyle, StmtKind};
27use crate::ast_traits::{HasAttrs, HasTokens};
28use crate::token::{self, Delimiter, InvisibleOrigin, Nonterminal, Token, TokenKind};
29use crate::{AttrVec, Attribute};
30
31#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
33pub enum TokenTree {
34 Token(Token, Spacing),
37 Delimited(DelimSpan, DelimSpacing, Delimiter, TokenStream),
39}
40
41fn _dummy()
43where
44 Token: sync::DynSend + sync::DynSync,
45 Spacing: sync::DynSend + sync::DynSync,
46 DelimSpan: sync::DynSend + sync::DynSync,
47 Delimiter: sync::DynSend + sync::DynSync,
48 TokenStream: sync::DynSend + sync::DynSync,
49{
50}
51
52impl TokenTree {
53 pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
55 match (self, other) {
56 (TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
57 (TokenTree::Delimited(.., delim, tts), TokenTree::Delimited(.., delim2, tts2)) => {
58 delim == delim2 && tts.eq_unspanned(tts2)
59 }
60 _ => false,
61 }
62 }
63
64 pub fn span(&self) -> Span {
66 match self {
67 TokenTree::Token(token, _) => token.span,
68 TokenTree::Delimited(sp, ..) => sp.entire(),
69 }
70 }
71
72 pub fn token_alone(kind: TokenKind, span: Span) -> TokenTree {
74 TokenTree::Token(Token::new(kind, span), Spacing::Alone)
75 }
76
77 pub fn token_joint(kind: TokenKind, span: Span) -> TokenTree {
79 TokenTree::Token(Token::new(kind, span), Spacing::Joint)
80 }
81
82 pub fn token_joint_hidden(kind: TokenKind, span: Span) -> TokenTree {
84 TokenTree::Token(Token::new(kind, span), Spacing::JointHidden)
85 }
86
87 pub fn uninterpolate(&self) -> Cow<'_, TokenTree> {
88 match self {
89 TokenTree::Token(token, spacing) => match token.uninterpolate() {
90 Cow::Owned(token) => Cow::Owned(TokenTree::Token(token, *spacing)),
91 Cow::Borrowed(_) => Cow::Borrowed(self),
92 },
93 _ => Cow::Borrowed(self),
94 }
95 }
96}
97
98impl<CTX> HashStable<CTX> for TokenStream
99where
100 CTX: crate::HashStableContext,
101{
102 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
103 for sub_tt in self.iter() {
104 sub_tt.hash_stable(hcx, hasher);
105 }
106 }
107}
108
109pub trait ToAttrTokenStream: sync::DynSend + sync::DynSync {
110 fn to_attr_token_stream(&self) -> AttrTokenStream;
111}
112
113impl ToAttrTokenStream for AttrTokenStream {
114 fn to_attr_token_stream(&self) -> AttrTokenStream {
115 self.clone()
116 }
117}
118
119#[derive(Clone)]
123pub struct LazyAttrTokenStream(Arc<Box<dyn ToAttrTokenStream>>);
124
125impl LazyAttrTokenStream {
126 pub fn new(inner: impl ToAttrTokenStream + 'static) -> LazyAttrTokenStream {
127 LazyAttrTokenStream(Arc::new(Box::new(inner)))
128 }
129
130 pub fn to_attr_token_stream(&self) -> AttrTokenStream {
131 self.0.to_attr_token_stream()
132 }
133}
134
135impl fmt::Debug for LazyAttrTokenStream {
136 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137 write!(f, "LazyAttrTokenStream({:?})", self.to_attr_token_stream())
138 }
139}
140
141impl<S: SpanEncoder> Encodable<S> for LazyAttrTokenStream {
142 fn encode(&self, _s: &mut S) {
143 panic!("Attempted to encode LazyAttrTokenStream");
144 }
145}
146
147impl<D: SpanDecoder> Decodable<D> for LazyAttrTokenStream {
148 fn decode(_d: &mut D) -> Self {
149 panic!("Attempted to decode LazyAttrTokenStream");
150 }
151}
152
153impl<CTX> HashStable<CTX> for LazyAttrTokenStream {
154 fn hash_stable(&self, _hcx: &mut CTX, _hasher: &mut StableHasher) {
155 panic!("Attempted to compute stable hash for LazyAttrTokenStream");
156 }
157}
158
159#[derive(Clone, Debug, Default, Encodable, Decodable)]
164pub struct AttrTokenStream(pub Arc<Vec<AttrTokenTree>>);
165
166#[derive(Clone, Debug, Encodable, Decodable)]
168pub enum AttrTokenTree {
169 Token(Token, Spacing),
170 Delimited(DelimSpan, DelimSpacing, Delimiter, AttrTokenStream),
171 AttrsTarget(AttrsTarget),
175}
176
177impl AttrTokenStream {
178 pub fn new(tokens: Vec<AttrTokenTree>) -> AttrTokenStream {
179 AttrTokenStream(Arc::new(tokens))
180 }
181
182 pub fn to_token_trees(&self) -> Vec<TokenTree> {
187 let mut res = Vec::with_capacity(self.0.len());
188 for tree in self.0.iter() {
189 match tree {
190 AttrTokenTree::Token(inner, spacing) => {
191 res.push(TokenTree::Token(inner.clone(), *spacing));
192 }
193 AttrTokenTree::Delimited(span, spacing, delim, stream) => {
194 res.push(TokenTree::Delimited(
195 *span,
196 *spacing,
197 *delim,
198 TokenStream::new(stream.to_token_trees()),
199 ))
200 }
201 AttrTokenTree::AttrsTarget(target) => {
202 attrs_and_tokens_to_token_trees(&target.attrs, &target.tokens, &mut res);
203 }
204 }
205 }
206 res
207 }
208}
209
210fn attrs_and_tokens_to_token_trees(
219 attrs: &[Attribute],
220 target_tokens: &LazyAttrTokenStream,
221 res: &mut Vec<TokenTree>,
222) {
223 let idx = attrs.partition_point(|attr| matches!(attr.style, crate::AttrStyle::Outer));
224 let (outer_attrs, inner_attrs) = attrs.split_at(idx);
225
226 for attr in outer_attrs {
228 res.extend(attr.token_trees());
229 }
230
231 res.extend(target_tokens.to_attr_token_stream().to_token_trees());
233
234 if !inner_attrs.is_empty() {
236 let mut found = false;
237 for tree in res.iter_mut().rev().take(2) {
239 if let TokenTree::Delimited(span, spacing, delim, delim_tokens) = tree {
240 let mut tts = vec![];
254 for inner_attr in inner_attrs {
255 tts.extend(inner_attr.token_trees());
256 }
257 tts.extend(delim_tokens.0.iter().cloned());
258 let stream = TokenStream::new(tts);
259 *tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
260 found = true;
261 break;
262 }
263 }
264 assert!(found, "Failed to find trailing delimited group in: {res:?}");
265 }
266}
267
268#[derive(Clone, Debug, Encodable, Decodable)]
281pub struct AttrsTarget {
282 pub attrs: AttrVec,
285 pub tokens: LazyAttrTokenStream,
288}
289
290#[derive(Clone, Debug, Default, Encodable, Decodable)]
297pub struct TokenStream(pub(crate) Arc<Vec<TokenTree>>);
298
299#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
304pub enum Spacing {
305 Alone,
321
322 Joint,
335
336 JointHidden,
357}
358
359impl TokenStream {
360 pub fn add_comma(&self) -> Option<(TokenStream, Span)> {
363 let mut suggestion = None;
365 let mut iter = self.0.iter().enumerate().peekable();
366 while let Some((pos, ts)) = iter.next() {
367 if let Some((_, next)) = iter.peek() {
368 let sp = match (&ts, &next) {
369 (_, TokenTree::Token(Token { kind: token::Comma, .. }, _)) => continue,
370 (
371 TokenTree::Token(token_left, Spacing::Alone),
372 TokenTree::Token(token_right, _),
373 ) if ((token_left.is_ident() && !token_left.is_reserved_ident())
374 || token_left.is_lit())
375 && ((token_right.is_ident() && !token_right.is_reserved_ident())
376 || token_right.is_lit()) =>
377 {
378 token_left.span
379 }
380 (TokenTree::Delimited(sp, ..), _) => sp.entire(),
381 _ => continue,
382 };
383 let sp = sp.shrink_to_hi();
384 let comma = TokenTree::token_alone(token::Comma, sp);
385 suggestion = Some((pos, comma, sp));
386 }
387 }
388 if let Some((pos, comma, sp)) = suggestion {
389 let mut new_stream = Vec::with_capacity(self.0.len() + 1);
390 let parts = self.0.split_at(pos + 1);
391 new_stream.extend_from_slice(parts.0);
392 new_stream.push(comma);
393 new_stream.extend_from_slice(parts.1);
394 return Some((TokenStream::new(new_stream), sp));
395 }
396 None
397 }
398}
399
400impl FromIterator<TokenTree> for TokenStream {
401 fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
402 TokenStream::new(iter.into_iter().collect::<Vec<TokenTree>>())
403 }
404}
405
406impl Eq for TokenStream {}
407
408impl PartialEq<TokenStream> for TokenStream {
409 fn eq(&self, other: &TokenStream) -> bool {
410 self.iter().eq(other.iter())
411 }
412}
413
414impl TokenStream {
415 pub fn new(tts: Vec<TokenTree>) -> TokenStream {
416 TokenStream(Arc::new(tts))
417 }
418
419 pub fn is_empty(&self) -> bool {
420 self.0.is_empty()
421 }
422
423 pub fn len(&self) -> usize {
424 self.0.len()
425 }
426
427 pub fn get(&self, index: usize) -> Option<&TokenTree> {
428 self.0.get(index)
429 }
430
431 pub fn iter(&self) -> TokenStreamIter<'_> {
432 TokenStreamIter::new(self)
433 }
434
435 pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
437 let mut iter1 = self.iter();
438 let mut iter2 = other.iter();
439 for (tt1, tt2) in iter::zip(&mut iter1, &mut iter2) {
440 if !tt1.eq_unspanned(tt2) {
441 return false;
442 }
443 }
444 iter1.next().is_none() && iter2.next().is_none()
445 }
446
447 pub fn token_alone(kind: TokenKind, span: Span) -> TokenStream {
452 TokenStream::new(vec![TokenTree::token_alone(kind, span)])
453 }
454
455 pub fn from_ast(node: &(impl HasAttrs + HasTokens + fmt::Debug)) -> TokenStream {
456 let tokens = node.tokens().unwrap_or_else(|| panic!("missing tokens for node: {:?}", node));
457 let mut tts = vec![];
458 attrs_and_tokens_to_token_trees(node.attrs(), tokens, &mut tts);
459 TokenStream::new(tts)
460 }
461
462 pub fn from_nonterminal_ast(nt: &Nonterminal) -> TokenStream {
463 match nt {
464 Nonterminal::NtItem(item) => TokenStream::from_ast(item),
465 Nonterminal::NtBlock(block) => TokenStream::from_ast(block),
466 Nonterminal::NtStmt(stmt) if let StmtKind::Empty = stmt.kind => {
467 TokenStream::token_alone(token::Semi, stmt.span)
469 }
470 Nonterminal::NtStmt(stmt) => TokenStream::from_ast(stmt),
471 Nonterminal::NtPat(pat) => TokenStream::from_ast(pat),
472 Nonterminal::NtTy(ty) => TokenStream::from_ast(ty),
473 Nonterminal::NtMeta(attr) => TokenStream::from_ast(attr),
474 Nonterminal::NtPath(path) => TokenStream::from_ast(path),
475 Nonterminal::NtVis(vis) => TokenStream::from_ast(vis),
476 Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
477 }
478 }
479
480 fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
481 match token.kind {
482 token::NtIdent(ident, is_raw) => {
483 TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
484 }
485 token::NtLifetime(ident, is_raw) => TokenTree::Delimited(
486 DelimSpan::from_single(token.span),
487 DelimSpacing::new(Spacing::JointHidden, spacing),
488 Delimiter::Invisible(InvisibleOrigin::FlattenToken),
489 TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span),
490 ),
491 token::Interpolated(ref nt) => TokenTree::Delimited(
492 DelimSpan::from_single(token.span),
493 DelimSpacing::new(Spacing::JointHidden, spacing),
494 Delimiter::Invisible(InvisibleOrigin::FlattenToken),
495 TokenStream::from_nonterminal_ast(&nt).flattened(),
496 ),
497 _ => TokenTree::Token(token.clone(), spacing),
498 }
499 }
500
501 fn flatten_token_tree(tree: &TokenTree) -> TokenTree {
502 match tree {
503 TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing),
504 TokenTree::Delimited(span, spacing, delim, tts) => {
505 TokenTree::Delimited(*span, *spacing, *delim, tts.flattened())
506 }
507 }
508 }
509
510 #[must_use]
511 pub fn flattened(&self) -> TokenStream {
512 fn can_skip(stream: &TokenStream) -> bool {
513 stream.iter().all(|tree| match tree {
514 TokenTree::Token(token, _) => !matches!(
515 token.kind,
516 token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..)
517 ),
518 TokenTree::Delimited(.., inner) => can_skip(inner),
519 })
520 }
521
522 if can_skip(self) {
523 return self.clone();
524 }
525
526 self.iter().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
527 }
528
529 fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
532 if let Some(TokenTree::Token(last_tok, Spacing::Joint | Spacing::JointHidden)) = vec.last()
533 && let TokenTree::Token(tok, spacing) = tt
534 && let Some(glued_tok) = last_tok.glue(tok)
535 {
536 *vec.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
539 true
540 } else {
541 false
542 }
543 }
544
545 pub fn push_tree(&mut self, tt: TokenTree) {
548 let vec_mut = Arc::make_mut(&mut self.0);
549
550 if Self::try_glue_to_last(vec_mut, &tt) {
551 } else {
553 vec_mut.push(tt);
554 }
555 }
556
557 pub fn push_stream(&mut self, stream: TokenStream) {
561 let vec_mut = Arc::make_mut(&mut self.0);
562
563 let stream_iter = stream.0.iter().cloned();
564
565 if let Some(first) = stream.0.first()
566 && Self::try_glue_to_last(vec_mut, first)
567 {
568 vec_mut.extend(stream_iter.skip(1));
570 } else {
571 vec_mut.extend(stream_iter);
573 }
574 }
575
576 pub fn chunks(&self, chunk_size: usize) -> core::slice::Chunks<'_, TokenTree> {
577 self.0.chunks(chunk_size)
578 }
579
580 pub fn desugar_doc_comments(&mut self) {
584 if let Some(desugared_stream) = desugar_inner(self.clone()) {
585 *self = desugared_stream;
586 }
587
588 fn desugar_inner(mut stream: TokenStream) -> Option<TokenStream> {
590 let mut i = 0;
591 let mut modified = false;
592 while let Some(tt) = stream.0.get(i) {
593 match tt {
594 &TokenTree::Token(
595 Token { kind: token::DocComment(_, attr_style, data), span },
596 _spacing,
597 ) => {
598 let desugared = desugared_tts(attr_style, data, span);
599 let desugared_len = desugared.len();
600 Arc::make_mut(&mut stream.0).splice(i..i + 1, desugared);
601 modified = true;
602 i += desugared_len;
603 }
604
605 &TokenTree::Token(..) => i += 1,
606
607 &TokenTree::Delimited(sp, spacing, delim, ref delim_stream) => {
608 if let Some(desugared_delim_stream) = desugar_inner(delim_stream.clone()) {
609 let new_tt =
610 TokenTree::Delimited(sp, spacing, delim, desugared_delim_stream);
611 Arc::make_mut(&mut stream.0)[i] = new_tt;
612 modified = true;
613 }
614 i += 1;
615 }
616 }
617 }
618 if modified { Some(stream) } else { None }
619 }
620
621 fn desugared_tts(attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTree> {
622 let mut num_of_hashes = 0;
628 let mut count = 0;
629 for ch in data.as_str().chars() {
630 count = match ch {
631 '"' => 1,
632 '#' if count > 0 => count + 1,
633 _ => 0,
634 };
635 num_of_hashes = cmp::max(num_of_hashes, count);
636 }
637
638 let delim_span = DelimSpan::from_single(span);
640 let body = TokenTree::Delimited(
641 delim_span,
642 DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
643 Delimiter::Bracket,
644 [
645 TokenTree::token_alone(token::Ident(sym::doc, token::IdentIsRaw::No), span),
646 TokenTree::token_alone(token::Eq, span),
647 TokenTree::token_alone(
648 TokenKind::lit(token::StrRaw(num_of_hashes), data, None),
649 span,
650 ),
651 ]
652 .into_iter()
653 .collect::<TokenStream>(),
654 );
655
656 if attr_style == AttrStyle::Inner {
657 vec![
658 TokenTree::token_joint(token::Pound, span),
659 TokenTree::token_joint_hidden(token::Not, span),
660 body,
661 ]
662 } else {
663 vec![TokenTree::token_joint_hidden(token::Pound, span), body]
664 }
665 }
666 }
667}
668
669#[derive(Clone)]
670pub struct TokenStreamIter<'t> {
671 stream: &'t TokenStream,
672 index: usize,
673}
674
675impl<'t> TokenStreamIter<'t> {
676 fn new(stream: &'t TokenStream) -> Self {
677 TokenStreamIter { stream, index: 0 }
678 }
679
680 pub fn peek(&self) -> Option<&'t TokenTree> {
684 self.stream.0.get(self.index)
685 }
686}
687
688impl<'t> Iterator for TokenStreamIter<'t> {
689 type Item = &'t TokenTree;
690
691 fn next(&mut self) -> Option<&'t TokenTree> {
692 self.stream.0.get(self.index).map(|tree| {
693 self.index += 1;
694 tree
695 })
696 }
697}
698
699#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
700pub struct DelimSpan {
701 pub open: Span,
702 pub close: Span,
703}
704
705impl DelimSpan {
706 pub fn from_single(sp: Span) -> Self {
707 DelimSpan { open: sp, close: sp }
708 }
709
710 pub fn from_pair(open: Span, close: Span) -> Self {
711 DelimSpan { open, close }
712 }
713
714 pub fn dummy() -> Self {
715 Self::from_single(DUMMY_SP)
716 }
717
718 pub fn entire(self) -> Span {
719 self.open.with_hi(self.close.hi())
720 }
721}
722
723#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
724pub struct DelimSpacing {
725 pub open: Spacing,
726 pub close: Spacing,
727}
728
729impl DelimSpacing {
730 pub fn new(open: Spacing, close: Spacing) -> DelimSpacing {
731 DelimSpacing { open, close }
732 }
733}
734
735#[cfg(target_pointer_width = "64")]
737mod size_asserts {
738 use rustc_data_structures::static_assert_size;
739
740 use super::*;
741 static_assert_size!(AttrTokenStream, 8);
743 static_assert_size!(AttrTokenTree, 32);
744 static_assert_size!(LazyAttrTokenStream, 8);
745 static_assert_size!(Option<LazyAttrTokenStream>, 8); static_assert_size!(TokenStream, 8);
747 static_assert_size!(TokenTree, 32);
748 }