|
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