| 
1 |  | -use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken};  | 
2 |  | -use rustc_ast::token::{self, Delimiter, Token, TokenKind};  | 
3 |  | -use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttrsTarget, DelimSpacing};  | 
4 |  | -use rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, ToAttrTokenStream};  | 
 | 1 | +use super::{Capturing, ForceCollect, Parser, TrailingToken};  | 
 | 2 | +use rustc_ast::token;  | 
 | 3 | +use rustc_ast::tokenstream::{AttrsTarget, LazyAttrTokenStream, ReplaceRange};  | 
5 | 4 | use rustc_ast::{self as ast};  | 
6 | 5 | use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens};  | 
7 | 6 | use rustc_errors::PResult;  | 
8 | 7 | use rustc_session::parse::ParseSess;  | 
9 |  | -use rustc_span::{sym, Span, DUMMY_SP};  | 
 | 8 | +use rustc_span::{sym, DUMMY_SP};  | 
10 | 9 | 
 
  | 
11 |  | -use std::{iter, mem};  | 
 | 10 | +use std::mem;  | 
12 | 11 | 
 
  | 
13 | 12 | /// A wrapper type to ensure that the parser handles outer attributes correctly.  | 
14 | 13 | /// When we parse outer attributes, we need to ensure that we capture tokens  | 
@@ -76,98 +75,6 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {  | 
76 | 75 |     })  | 
77 | 76 | }  | 
78 | 77 | 
 
  | 
79 |  | -// Produces a `TokenStream` on-demand. Using `cursor_snapshot`  | 
80 |  | -// and `num_calls`, we can reconstruct the `TokenStream` seen  | 
81 |  | -// by the callback. This allows us to avoid producing a `TokenStream`  | 
82 |  | -// if it is never needed - for example, a captured `macro_rules!`  | 
83 |  | -// argument that is never passed to a proc macro.  | 
84 |  | -// In practice token stream creation happens rarely compared to  | 
85 |  | -// calls to `collect_tokens` (see some statistics in #78736),  | 
86 |  | -// so we are doing as little up-front work as possible.  | 
87 |  | -//  | 
88 |  | -// This also makes `Parser` very cheap to clone, since  | 
89 |  | -// there is no intermediate collection buffer to clone.  | 
90 |  | -struct LazyAttrTokenStreamImpl {  | 
91 |  | -    start_token: (Token, Spacing),  | 
92 |  | -    cursor_snapshot: TokenCursor,  | 
93 |  | -    num_calls: u32,  | 
94 |  | -    break_last_token: bool,  | 
95 |  | -    replace_ranges: Box<[ReplaceRange]>,  | 
96 |  | -}  | 
97 |  | - | 
98 |  | -impl ToAttrTokenStream for LazyAttrTokenStreamImpl {  | 
99 |  | -    fn to_attr_token_stream(&self) -> AttrTokenStream {  | 
100 |  | -        // The token produced by the final call to `{,inlined_}next` was not  | 
101 |  | -        // actually consumed by the callback. The combination of chaining the  | 
102 |  | -        // initial token and using `take` produces the desired result - we  | 
103 |  | -        // produce an empty `TokenStream` if no calls were made, and omit the  | 
104 |  | -        // final token otherwise.  | 
105 |  | -        let mut cursor_snapshot = self.cursor_snapshot.clone();  | 
106 |  | -        let tokens = iter::once((FlatToken::Token(self.start_token.0.clone()), self.start_token.1))  | 
107 |  | -            .chain(iter::repeat_with(|| {  | 
108 |  | -                let token = cursor_snapshot.next();  | 
109 |  | -                (FlatToken::Token(token.0), token.1)  | 
110 |  | -            }))  | 
111 |  | -            .take(self.num_calls as usize);  | 
112 |  | - | 
113 |  | -        if self.replace_ranges.is_empty() {  | 
114 |  | -            make_attr_token_stream(tokens, self.break_last_token)  | 
115 |  | -        } else {  | 
116 |  | -            let mut tokens: Vec<_> = tokens.collect();  | 
117 |  | -            let mut replace_ranges = self.replace_ranges.to_vec();  | 
118 |  | -            replace_ranges.sort_by_key(|(range, _)| range.start);  | 
119 |  | - | 
120 |  | -            #[cfg(debug_assertions)]  | 
121 |  | -            {  | 
122 |  | -                for [(range, tokens), (next_range, next_tokens)] in replace_ranges.array_windows() {  | 
123 |  | -                    assert!(  | 
124 |  | -                        range.end <= next_range.start || range.end >= next_range.end,  | 
125 |  | -                        "Replace ranges should either be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",  | 
126 |  | -                        range,  | 
127 |  | -                        tokens,  | 
128 |  | -                        next_range,  | 
129 |  | -                        next_tokens,  | 
130 |  | -                    );  | 
131 |  | -                }  | 
132 |  | -            }  | 
133 |  | - | 
134 |  | -            // Process the replace ranges, starting from the highest start  | 
135 |  | -            // position and working our way back. If have tokens like:  | 
136 |  | -            //  | 
137 |  | -            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`  | 
138 |  | -            //  | 
139 |  | -            // Then we will generate replace ranges for both  | 
140 |  | -            // the `#[cfg(FALSE)] field: bool` and the entire  | 
141 |  | -            // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`  | 
142 |  | -            //  | 
143 |  | -            // By starting processing from the replace range with the greatest  | 
144 |  | -            // start position, we ensure that any replace range which encloses  | 
145 |  | -            // another replace range will capture the *replaced* tokens for the inner  | 
146 |  | -            // range, not the original tokens.  | 
147 |  | -            for (range, target) in replace_ranges.into_iter().rev() {  | 
148 |  | -                assert!(!range.is_empty(), "Cannot replace an empty range: {range:?}");  | 
149 |  | - | 
150 |  | -                // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus  | 
151 |  | -                // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the  | 
152 |  | -                // total length of `tokens` constant throughout the replacement process, allowing  | 
153 |  | -                // us to use all of the `ReplaceRanges` entries without adjusting indices.  | 
154 |  | -                let target_len = target.is_some() as usize;  | 
155 |  | -                tokens.splice(  | 
156 |  | -                    (range.start as usize)..(range.end as usize),  | 
157 |  | -                    target  | 
158 |  | -                        .into_iter()  | 
159 |  | -                        .map(|target| (FlatToken::AttrsTarget(target), Spacing::Alone))  | 
160 |  | -                        .chain(  | 
161 |  | -                            iter::repeat((FlatToken::Empty, Spacing::Alone))  | 
162 |  | -                                .take(range.len() - target_len),  | 
163 |  | -                        ),  | 
164 |  | -                );  | 
165 |  | -            }  | 
166 |  | -            make_attr_token_stream(tokens.into_iter(), self.break_last_token)  | 
167 |  | -        }  | 
168 |  | -    }  | 
169 |  | -}  | 
170 |  | - | 
171 | 78 | impl<'a> Parser<'a> {  | 
172 | 79 |     /// Records all tokens consumed by the provided callback,  | 
173 | 80 |     /// including the current token. These tokens are collected  | 
@@ -317,20 +224,17 @@ impl<'a> Parser<'a> {  | 
317 | 224 |                 .collect()  | 
318 | 225 |         };  | 
319 | 226 | 
 
  | 
320 |  | -        let tokens = LazyAttrTokenStream::new(LazyAttrTokenStreamImpl {  | 
 | 227 | +        let tokens = LazyAttrTokenStream::new_pending(  | 
321 | 228 |             start_token,  | 
322 |  | -            num_calls,  | 
323 | 229 |             cursor_snapshot,  | 
324 |  | -            break_last_token: self.break_last_token,  | 
 | 230 | +            num_calls,  | 
 | 231 | +            self.break_last_token,  | 
325 | 232 |             replace_ranges,  | 
326 |  | -        });  | 
 | 233 | +        );  | 
327 | 234 | 
 
  | 
328 |  | -        // If we support tokens at all  | 
329 |  | -        if let Some(target_tokens) = ret.tokens_mut() {  | 
330 |  | -            if target_tokens.is_none() {  | 
331 |  | -                // Store our newly captured tokens into the AST node.  | 
332 |  | -                *target_tokens = Some(tokens.clone());  | 
333 |  | -            }  | 
 | 235 | +        // If we support tokens and don't already have them, store the newly captured tokens.  | 
 | 236 | +        if let Some(target_tokens @ None) = ret.tokens_mut() {  | 
 | 237 | +            *target_tokens = Some(tokens.clone());  | 
334 | 238 |         }  | 
335 | 239 | 
 
  | 
336 | 240 |         let final_attrs = ret.attrs();  | 
@@ -366,88 +270,12 @@ impl<'a> Parser<'a> {  | 
366 | 270 |     }  | 
367 | 271 | }  | 
368 | 272 | 
 
  | 
369 |  | -/// Converts a flattened iterator of tokens (including open and close delimiter tokens) into an  | 
370 |  | -/// `AttrTokenStream`, creating an `AttrTokenTree::Delimited` for each matching pair of open and  | 
371 |  | -/// close delims.  | 
372 |  | -fn make_attr_token_stream(  | 
373 |  | -    mut iter: impl Iterator<Item = (FlatToken, Spacing)>,  | 
374 |  | -    break_last_token: bool,  | 
375 |  | -) -> AttrTokenStream {  | 
376 |  | -    #[derive(Debug)]  | 
377 |  | -    struct FrameData {  | 
378 |  | -        // This is `None` for the first frame, `Some` for all others.  | 
379 |  | -        open_delim_sp: Option<(Delimiter, Span, Spacing)>,  | 
380 |  | -        inner: Vec<AttrTokenTree>,  | 
381 |  | -    }  | 
382 |  | -    let mut stack = vec![FrameData { open_delim_sp: None, inner: vec![] }];  | 
383 |  | -    let mut token_and_spacing = iter.next();  | 
384 |  | -    while let Some((token, spacing)) = token_and_spacing {  | 
385 |  | -        match token {  | 
386 |  | -            FlatToken::Token(Token { kind: TokenKind::OpenDelim(delim), span }) => {  | 
387 |  | -                stack  | 
388 |  | -                    .push(FrameData { open_delim_sp: Some((delim, span, spacing)), inner: vec![] });  | 
389 |  | -            }  | 
390 |  | -            FlatToken::Token(Token { kind: TokenKind::CloseDelim(delim), span }) => {  | 
391 |  | -                let frame_data = stack  | 
392 |  | -                    .pop()  | 
393 |  | -                    .unwrap_or_else(|| panic!("Token stack was empty for token: {token:?}"));  | 
394 |  | - | 
395 |  | -                let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap();  | 
396 |  | -                assert_eq!(  | 
397 |  | -                    open_delim, delim,  | 
398 |  | -                    "Mismatched open/close delims: open={open_delim:?} close={span:?}"  | 
399 |  | -                );  | 
400 |  | -                let dspan = DelimSpan::from_pair(open_sp, span);  | 
401 |  | -                let dspacing = DelimSpacing::new(open_spacing, spacing);  | 
402 |  | -                let stream = AttrTokenStream::new(frame_data.inner);  | 
403 |  | -                let delimited = AttrTokenTree::Delimited(dspan, dspacing, delim, stream);  | 
404 |  | -                stack  | 
405 |  | -                    .last_mut()  | 
406 |  | -                    .unwrap_or_else(|| panic!("Bottom token frame is missing for token: {token:?}"))  | 
407 |  | -                    .inner  | 
408 |  | -                    .push(delimited);  | 
409 |  | -            }  | 
410 |  | -            FlatToken::Token(token) => stack  | 
411 |  | -                .last_mut()  | 
412 |  | -                .expect("Bottom token frame is missing!")  | 
413 |  | -                .inner  | 
414 |  | -                .push(AttrTokenTree::Token(token, spacing)),  | 
415 |  | -            FlatToken::AttrsTarget(target) => stack  | 
416 |  | -                .last_mut()  | 
417 |  | -                .expect("Bottom token frame is missing!")  | 
418 |  | -                .inner  | 
419 |  | -                .push(AttrTokenTree::AttrsTarget(target)),  | 
420 |  | -            FlatToken::Empty => {}  | 
421 |  | -        }  | 
422 |  | -        token_and_spacing = iter.next();  | 
423 |  | -    }  | 
424 |  | -    let mut final_buf = stack.pop().expect("Missing final buf!");  | 
425 |  | -    if break_last_token {  | 
426 |  | -        let last_token = final_buf.inner.pop().unwrap();  | 
427 |  | -        if let AttrTokenTree::Token(last_token, spacing) = last_token {  | 
428 |  | -            let unglued_first = last_token.kind.break_two_token_op().unwrap().0;  | 
429 |  | - | 
430 |  | -            // An 'unglued' token is always two ASCII characters  | 
431 |  | -            let mut first_span = last_token.span.shrink_to_lo();  | 
432 |  | -            first_span = first_span.with_hi(first_span.lo() + rustc_span::BytePos(1));  | 
433 |  | - | 
434 |  | -            final_buf  | 
435 |  | -                .inner  | 
436 |  | -                .push(AttrTokenTree::Token(Token::new(unglued_first, first_span), spacing));  | 
437 |  | -        } else {  | 
438 |  | -            panic!("Unexpected last token {last_token:?}")  | 
439 |  | -        }  | 
440 |  | -    }  | 
441 |  | -    AttrTokenStream::new(final_buf.inner)  | 
442 |  | -}  | 
443 |  | - | 
444 | 273 | // Some types are used a lot. Make sure they don't unintentionally get bigger.  | 
445 | 274 | #[cfg(target_pointer_width = "64")]  | 
446 | 275 | mod size_asserts {  | 
447 | 276 |     use super::*;  | 
448 | 277 |     use rustc_data_structures::static_assert_size;  | 
449 | 278 |     // tidy-alphabetical-start  | 
450 | 279 |     static_assert_size!(AttrWrapper, 16);  | 
451 |  | -    static_assert_size!(LazyAttrTokenStreamImpl, 96);  | 
452 | 280 |     // tidy-alphabetical-end  | 
453 | 281 | }  | 
0 commit comments