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;
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::NtBlock(block) => TokenStream::from_ast(block),
465 Nonterminal::NtExpr(expr) | Nonterminal::NtLiteral(expr) => TokenStream::from_ast(expr),
466 }
467 }
468
469 fn flatten_token(token: &Token, spacing: Spacing) -> TokenTree {
470 match token.kind {
471 token::NtIdent(ident, is_raw) => {
472 TokenTree::Token(Token::new(token::Ident(ident.name, is_raw), ident.span), spacing)
473 }
474 token::NtLifetime(ident, is_raw) => TokenTree::Delimited(
475 DelimSpan::from_single(token.span),
476 DelimSpacing::new(Spacing::JointHidden, spacing),
477 Delimiter::Invisible(InvisibleOrigin::FlattenToken),
478 TokenStream::token_alone(token::Lifetime(ident.name, is_raw), ident.span),
479 ),
480 token::Interpolated(ref nt) => TokenTree::Delimited(
481 DelimSpan::from_single(token.span),
482 DelimSpacing::new(Spacing::JointHidden, spacing),
483 Delimiter::Invisible(InvisibleOrigin::FlattenToken),
484 TokenStream::from_nonterminal_ast(&nt).flattened(),
485 ),
486 _ => TokenTree::Token(token.clone(), spacing),
487 }
488 }
489
490 fn flatten_token_tree(tree: &TokenTree) -> TokenTree {
491 match tree {
492 TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing),
493 TokenTree::Delimited(span, spacing, delim, tts) => {
494 TokenTree::Delimited(*span, *spacing, *delim, tts.flattened())
495 }
496 }
497 }
498
499 #[must_use]
500 pub fn flattened(&self) -> TokenStream {
501 fn can_skip(stream: &TokenStream) -> bool {
502 stream.iter().all(|tree| match tree {
503 TokenTree::Token(token, _) => !matches!(
504 token.kind,
505 token::NtIdent(..) | token::NtLifetime(..) | token::Interpolated(..)
506 ),
507 TokenTree::Delimited(.., inner) => can_skip(inner),
508 })
509 }
510
511 if can_skip(self) {
512 return self.clone();
513 }
514
515 self.iter().map(|tree| TokenStream::flatten_token_tree(tree)).collect()
516 }
517
518 fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
521 if let Some(TokenTree::Token(last_tok, Spacing::Joint | Spacing::JointHidden)) = vec.last()
522 && let TokenTree::Token(tok, spacing) = tt
523 && let Some(glued_tok) = last_tok.glue(tok)
524 {
525 *vec.last_mut().unwrap() = TokenTree::Token(glued_tok, *spacing);
528 true
529 } else {
530 false
531 }
532 }
533
534 pub fn push_tree(&mut self, tt: TokenTree) {
537 let vec_mut = Arc::make_mut(&mut self.0);
538
539 if Self::try_glue_to_last(vec_mut, &tt) {
540 } else {
542 vec_mut.push(tt);
543 }
544 }
545
546 pub fn push_stream(&mut self, stream: TokenStream) {
550 let vec_mut = Arc::make_mut(&mut self.0);
551
552 let stream_iter = stream.0.iter().cloned();
553
554 if let Some(first) = stream.0.first()
555 && Self::try_glue_to_last(vec_mut, first)
556 {
557 vec_mut.extend(stream_iter.skip(1));
559 } else {
560 vec_mut.extend(stream_iter);
562 }
563 }
564
565 pub fn chunks(&self, chunk_size: usize) -> core::slice::Chunks<'_, TokenTree> {
566 self.0.chunks(chunk_size)
567 }
568
569 pub fn desugar_doc_comments(&mut self) {
573 if let Some(desugared_stream) = desugar_inner(self.clone()) {
574 *self = desugared_stream;
575 }
576
577 fn desugar_inner(mut stream: TokenStream) -> Option<TokenStream> {
579 let mut i = 0;
580 let mut modified = false;
581 while let Some(tt) = stream.0.get(i) {
582 match tt {
583 &TokenTree::Token(
584 Token { kind: token::DocComment(_, attr_style, data), span },
585 _spacing,
586 ) => {
587 let desugared = desugared_tts(attr_style, data, span);
588 let desugared_len = desugared.len();
589 Arc::make_mut(&mut stream.0).splice(i..i + 1, desugared);
590 modified = true;
591 i += desugared_len;
592 }
593
594 &TokenTree::Token(..) => i += 1,
595
596 &TokenTree::Delimited(sp, spacing, delim, ref delim_stream) => {
597 if let Some(desugared_delim_stream) = desugar_inner(delim_stream.clone()) {
598 let new_tt =
599 TokenTree::Delimited(sp, spacing, delim, desugared_delim_stream);
600 Arc::make_mut(&mut stream.0)[i] = new_tt;
601 modified = true;
602 }
603 i += 1;
604 }
605 }
606 }
607 if modified { Some(stream) } else { None }
608 }
609
610 fn desugared_tts(attr_style: AttrStyle, data: Symbol, span: Span) -> Vec<TokenTree> {
611 let mut num_of_hashes = 0;
617 let mut count = 0;
618 for ch in data.as_str().chars() {
619 count = match ch {
620 '"' => 1,
621 '#' if count > 0 => count + 1,
622 _ => 0,
623 };
624 num_of_hashes = cmp::max(num_of_hashes, count);
625 }
626
627 let delim_span = DelimSpan::from_single(span);
629 let body = TokenTree::Delimited(
630 delim_span,
631 DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
632 Delimiter::Bracket,
633 [
634 TokenTree::token_alone(token::Ident(sym::doc, token::IdentIsRaw::No), span),
635 TokenTree::token_alone(token::Eq, span),
636 TokenTree::token_alone(
637 TokenKind::lit(token::StrRaw(num_of_hashes), data, None),
638 span,
639 ),
640 ]
641 .into_iter()
642 .collect::<TokenStream>(),
643 );
644
645 if attr_style == AttrStyle::Inner {
646 vec![
647 TokenTree::token_joint(token::Pound, span),
648 TokenTree::token_joint_hidden(token::Bang, span),
649 body,
650 ]
651 } else {
652 vec![TokenTree::token_joint_hidden(token::Pound, span), body]
653 }
654 }
655 }
656}
657
658#[derive(Clone)]
659pub struct TokenStreamIter<'t> {
660 stream: &'t TokenStream,
661 index: usize,
662}
663
664impl<'t> TokenStreamIter<'t> {
665 fn new(stream: &'t TokenStream) -> Self {
666 TokenStreamIter { stream, index: 0 }
667 }
668
669 pub fn peek(&self) -> Option<&'t TokenTree> {
673 self.stream.0.get(self.index)
674 }
675}
676
677impl<'t> Iterator for TokenStreamIter<'t> {
678 type Item = &'t TokenTree;
679
680 fn next(&mut self) -> Option<&'t TokenTree> {
681 self.stream.0.get(self.index).map(|tree| {
682 self.index += 1;
683 tree
684 })
685 }
686}
687
688#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
689pub struct DelimSpan {
690 pub open: Span,
691 pub close: Span,
692}
693
694impl DelimSpan {
695 pub fn from_single(sp: Span) -> Self {
696 DelimSpan { open: sp, close: sp }
697 }
698
699 pub fn from_pair(open: Span, close: Span) -> Self {
700 DelimSpan { open, close }
701 }
702
703 pub fn dummy() -> Self {
704 Self::from_single(DUMMY_SP)
705 }
706
707 pub fn entire(self) -> Span {
708 self.open.with_hi(self.close.hi())
709 }
710}
711
712#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
713pub struct DelimSpacing {
714 pub open: Spacing,
715 pub close: Spacing,
716}
717
718impl DelimSpacing {
719 pub fn new(open: Spacing, close: Spacing) -> DelimSpacing {
720 DelimSpacing { open, close }
721 }
722}
723
724#[cfg(target_pointer_width = "64")]
726mod size_asserts {
727 use rustc_data_structures::static_assert_size;
728
729 use super::*;
730 static_assert_size!(AttrTokenStream, 8);
732 static_assert_size!(AttrTokenTree, 32);
733 static_assert_size!(LazyAttrTokenStream, 8);
734 static_assert_size!(Option<LazyAttrTokenStream>, 8); static_assert_size!(TokenStream, 8);
736 static_assert_size!(TokenTree, 32);
737 }