1
1
use std:: borrow:: Cow ;
2
- use std:: { iter , mem} ;
2
+ use std:: mem;
3
3
4
- use rustc_ast:: token:: { Delimiter , Token } ;
4
+ use rustc_ast:: token:: Token ;
5
5
use rustc_ast:: tokenstream:: {
6
- AttrTokenStream , AttrTokenTree , AttrsTarget , DelimSpacing , DelimSpan , LazyAttrTokenStream ,
7
- Spacing , ToAttrTokenStream ,
6
+ AttrsTarget , LazyAttrTokenStream , NodeRange , ParserRange , Spacing , TokenCursor ,
8
7
} ;
9
8
use rustc_ast:: { self as ast, AttrVec , Attribute , HasAttrs , HasTokens } ;
10
9
use rustc_data_structures:: fx:: FxHashSet ;
11
10
use rustc_errors:: PResult ;
12
11
use rustc_session:: parse:: ParseSess ;
13
- use rustc_span:: { DUMMY_SP , Span , sym} ;
12
+ use rustc_span:: { DUMMY_SP , sym} ;
13
+ use thin_vec:: ThinVec ;
14
14
15
- use super :: {
16
- Capturing , FlatToken , ForceCollect , NodeRange , NodeReplacement , Parser , ParserRange ,
17
- TokenCursor , Trailing ,
18
- } ;
15
+ use super :: { Capturing , ForceCollect , Parser , Trailing } ;
19
16
20
17
// When collecting tokens, this fully captures the start point. Usually its
21
18
// just after outer attributes, but occasionally it's before.
@@ -94,95 +91,6 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
94
91
} )
95
92
}
96
93
97
- // From a value of this type we can reconstruct the `TokenStream` seen by the
98
- // `f` callback passed to a call to `Parser::collect_tokens`, by
99
- // replaying the getting of the tokens. This saves us producing a `TokenStream`
100
- // if it is never needed, e.g. a captured `macro_rules!` argument that is never
101
- // passed to a proc macro. In practice, token stream creation happens rarely
102
- // compared to calls to `collect_tokens` (see some statistics in #78736) so we
103
- // are doing as little up-front work as possible.
104
- //
105
- // This also makes `Parser` very cheap to clone, since
106
- // there is no intermediate collection buffer to clone.
107
- struct LazyAttrTokenStreamImpl {
108
- start_token : ( Token , Spacing ) ,
109
- cursor_snapshot : TokenCursor ,
110
- num_calls : u32 ,
111
- break_last_token : u32 ,
112
- node_replacements : Box < [ NodeReplacement ] > ,
113
- }
114
-
115
- impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
116
- fn to_attr_token_stream ( & self ) -> AttrTokenStream {
117
- // The token produced by the final call to `{,inlined_}next` was not
118
- // actually consumed by the callback. The combination of chaining the
119
- // initial token and using `take` produces the desired result - we
120
- // produce an empty `TokenStream` if no calls were made, and omit the
121
- // final token otherwise.
122
- let mut cursor_snapshot = self . cursor_snapshot . clone ( ) ;
123
- let tokens = iter:: once ( FlatToken :: Token ( self . start_token ) )
124
- . chain ( iter:: repeat_with ( || FlatToken :: Token ( cursor_snapshot. next ( ) ) ) )
125
- . take ( self . num_calls as usize ) ;
126
-
127
- if self . node_replacements . is_empty ( ) {
128
- make_attr_token_stream ( tokens, self . break_last_token )
129
- } else {
130
- let mut tokens: Vec < _ > = tokens. collect ( ) ;
131
- let mut node_replacements = self . node_replacements . to_vec ( ) ;
132
- node_replacements. sort_by_key ( |( range, _) | range. 0 . start ) ;
133
-
134
- #[ cfg( debug_assertions) ]
135
- for [ ( node_range, tokens) , ( next_node_range, next_tokens) ] in
136
- node_replacements. array_windows ( )
137
- {
138
- assert ! (
139
- node_range. 0 . end <= next_node_range. 0 . start
140
- || node_range. 0 . end >= next_node_range. 0 . end,
141
- "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})" ,
142
- node_range,
143
- tokens,
144
- next_node_range,
145
- next_tokens,
146
- ) ;
147
- }
148
-
149
- // Process the replace ranges, starting from the highest start
150
- // position and working our way back. If have tokens like:
151
- //
152
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
153
- //
154
- // Then we will generate replace ranges for both
155
- // the `#[cfg(FALSE)] field: bool` and the entire
156
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
157
- //
158
- // By starting processing from the replace range with the greatest
159
- // start position, we ensure that any (outer) replace range which
160
- // encloses another (inner) replace range will fully overwrite the
161
- // inner range's replacement.
162
- for ( node_range, target) in node_replacements. into_iter ( ) . rev ( ) {
163
- assert ! (
164
- !node_range. 0 . is_empty( ) ,
165
- "Cannot replace an empty node range: {:?}" ,
166
- node_range. 0
167
- ) ;
168
-
169
- // Replace the tokens in range with zero or one `FlatToken::AttrsTarget`s, plus
170
- // enough `FlatToken::Empty`s to fill up the rest of the range. This keeps the
171
- // total length of `tokens` constant throughout the replacement process, allowing
172
- // us to do all replacements without adjusting indices.
173
- let target_len = target. is_some ( ) as usize ;
174
- tokens. splice (
175
- ( node_range. 0 . start as usize ) ..( node_range. 0 . end as usize ) ,
176
- target. into_iter ( ) . map ( |target| FlatToken :: AttrsTarget ( target) ) . chain (
177
- iter:: repeat ( FlatToken :: Empty ) . take ( node_range. 0 . len ( ) - target_len) ,
178
- ) ,
179
- ) ;
180
- }
181
- make_attr_token_stream ( tokens. into_iter ( ) , self . break_last_token )
182
- }
183
- }
184
- }
185
-
186
94
impl < ' a > Parser < ' a > {
187
95
pub ( super ) fn collect_pos ( & self ) -> CollectPos {
188
96
CollectPos {
@@ -387,10 +295,10 @@ impl<'a> Parser<'a> {
387
295
388
296
// This is hot enough for `deep-vector` that checking the conditions for an empty iterator
389
297
// is measurably faster than actually executing the iterator.
390
- let node_replacements: Box < [ _ ] > = if parser_replacements_start == parser_replacements_end
298
+ let node_replacements = if parser_replacements_start == parser_replacements_end
391
299
&& inner_attr_parser_replacements. is_empty ( )
392
300
{
393
- Box :: new ( [ ] )
301
+ ThinVec :: new ( )
394
302
} else {
395
303
// Grab any replace ranges that occur *inside* the current AST node. Convert them
396
304
// from `ParserRange` form to `NodeRange` form. We will perform the actual
@@ -429,13 +337,13 @@ impl<'a> Parser<'a> {
429
337
// - `attrs`: includes the outer and the inner attr.
430
338
// - `tokens`: lazy tokens for `g` (with its inner attr deleted).
431
339
432
- let tokens = LazyAttrTokenStream :: new ( LazyAttrTokenStreamImpl {
433
- start_token : collect_pos. start_token ,
434
- cursor_snapshot : collect_pos. cursor_snapshot ,
340
+ let tokens = LazyAttrTokenStream :: new_pending (
341
+ collect_pos. start_token ,
342
+ collect_pos. cursor_snapshot ,
435
343
num_calls,
436
- break_last_token : self . break_last_token ,
344
+ self . break_last_token ,
437
345
node_replacements,
438
- } ) ;
346
+ ) ;
439
347
let mut tokens_used = false ;
440
348
441
349
// If in "definite capture mode" we need to register a replace range
@@ -483,71 +391,6 @@ impl<'a> Parser<'a> {
483
391
}
484
392
}
485
393
486
- /// Converts a flattened iterator of tokens (including open and close delimiter tokens) into an
487
- /// `AttrTokenStream`, creating an `AttrTokenTree::Delimited` for each matching pair of open and
488
- /// close delims.
489
- fn make_attr_token_stream (
490
- iter : impl Iterator < Item = FlatToken > ,
491
- break_last_token : u32 ,
492
- ) -> AttrTokenStream {
493
- #[ derive( Debug ) ]
494
- struct FrameData {
495
- // This is `None` for the first frame, `Some` for all others.
496
- open_delim_sp : Option < ( Delimiter , Span , Spacing ) > ,
497
- inner : Vec < AttrTokenTree > ,
498
- }
499
- // The stack always has at least one element. Storing it separately makes for shorter code.
500
- let mut stack_top = FrameData { open_delim_sp : None , inner : vec ! [ ] } ;
501
- let mut stack_rest = vec ! [ ] ;
502
- for flat_token in iter {
503
- match flat_token {
504
- FlatToken :: Token ( ( token @ Token { kind, span } , spacing) ) => {
505
- if let Some ( delim) = kind. open_delim ( ) {
506
- stack_rest. push ( mem:: replace (
507
- & mut stack_top,
508
- FrameData { open_delim_sp : Some ( ( delim, span, spacing) ) , inner : vec ! [ ] } ,
509
- ) ) ;
510
- } else if let Some ( delim) = kind. close_delim ( ) {
511
- let frame_data = mem:: replace ( & mut stack_top, stack_rest. pop ( ) . unwrap ( ) ) ;
512
- let ( open_delim, open_sp, open_spacing) = frame_data. open_delim_sp . unwrap ( ) ;
513
- assert ! (
514
- open_delim. eq_ignoring_invisible_origin( & delim) ,
515
- "Mismatched open/close delims: open={open_delim:?} close={span:?}"
516
- ) ;
517
- let dspan = DelimSpan :: from_pair ( open_sp, span) ;
518
- let dspacing = DelimSpacing :: new ( open_spacing, spacing) ;
519
- let stream = AttrTokenStream :: new ( frame_data. inner ) ;
520
- let delimited = AttrTokenTree :: Delimited ( dspan, dspacing, delim, stream) ;
521
- stack_top. inner . push ( delimited) ;
522
- } else {
523
- stack_top. inner . push ( AttrTokenTree :: Token ( token, spacing) )
524
- }
525
- }
526
- FlatToken :: AttrsTarget ( target) => {
527
- stack_top. inner . push ( AttrTokenTree :: AttrsTarget ( target) )
528
- }
529
- FlatToken :: Empty => { }
530
- }
531
- }
532
-
533
- if break_last_token > 0 {
534
- let last_token = stack_top. inner . pop ( ) . unwrap ( ) ;
535
- if let AttrTokenTree :: Token ( last_token, spacing) = last_token {
536
- let ( unglued, _) = last_token. kind . break_two_token_op ( break_last_token) . unwrap ( ) ;
537
-
538
- // Tokens are always ASCII chars, so we can use byte arithmetic here.
539
- let mut first_span = last_token. span . shrink_to_lo ( ) ;
540
- first_span =
541
- first_span. with_hi ( first_span. lo ( ) + rustc_span:: BytePos ( break_last_token) ) ;
542
-
543
- stack_top. inner . push ( AttrTokenTree :: Token ( Token :: new ( unglued, first_span) , spacing) ) ;
544
- } else {
545
- panic ! ( "Unexpected last token {last_token:?}" )
546
- }
547
- }
548
- AttrTokenStream :: new ( stack_top. inner )
549
- }
550
-
551
394
/// Tokens are needed if:
552
395
/// - any non-single-segment attributes (other than doc comments) are present,
553
396
/// e.g. `rustfmt::skip`; or
@@ -562,14 +405,3 @@ fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
562
405
}
563
406
} )
564
407
}
565
-
566
- // Some types are used a lot. Make sure they don't unintentionally get bigger.
567
- #[ cfg( target_pointer_width = "64" ) ]
568
- mod size_asserts {
569
- use rustc_data_structures:: static_assert_size;
570
-
571
- use super :: * ;
572
- // tidy-alphabetical-start
573
- static_assert_size ! ( LazyAttrTokenStreamImpl , 96 ) ;
574
- // tidy-alphabetical-end
575
- }
0 commit comments