@@ -12,40 +12,56 @@ use rustc_span::{sym, Span, DUMMY_SP};
12
12
13
13
use super :: {
14
14
Capturing , FlatToken , ForceCollect , NodeRange , NodeReplacement , Parser , ParserRange ,
15
- TokenCursor ,
15
+ TokenCursor , Trailing ,
16
16
} ;
17
17
18
+ // When collecting tokens, this fully captures the start point. Usually its
19
+ // just after outer attributes, but occasionally it's before.
20
+ #[ derive( Clone , Debug ) ]
21
+ pub ( super ) struct CollectPos {
22
+ start_token : ( Token , Spacing ) ,
23
+ cursor_snapshot : TokenCursor ,
24
+ start_pos : u32 ,
25
+ }
26
+
27
+ pub ( super ) enum UsePreAttrPos {
28
+ No ,
29
+ Yes ,
30
+ }
31
+
18
32
/// A wrapper type to ensure that the parser handles outer attributes correctly.
19
33
/// When we parse outer attributes, we need to ensure that we capture tokens
20
34
/// for the attribute target. This allows us to perform cfg-expansion on
21
35
/// a token stream before we invoke a derive proc-macro.
22
36
///
23
37
/// This wrapper prevents direct access to the underlying `ast::AttrVec`.
24
38
/// Parsing code can only get access to the underlying attributes
25
- /// by passing an `AttrWrapper` to `collect_tokens_trailing_token `.
39
+ /// by passing an `AttrWrapper` to `collect_tokens `.
26
40
/// This makes it difficult to accidentally construct an AST node
27
41
/// (which stores an `ast::AttrVec`) without first collecting tokens.
28
42
///
29
43
/// This struct has its own module, to ensure that the parser code
30
44
/// cannot directly access the `attrs` field.
31
45
#[ derive( Debug , Clone ) ]
32
- pub struct AttrWrapper {
46
+ pub ( super ) struct AttrWrapper {
33
47
attrs : AttrVec ,
34
48
// The start of the outer attributes in the parser's token stream.
35
49
// This lets us create a `NodeReplacement` for the entire attribute
36
- // target, including outer attributes.
37
- start_pos : u32 ,
50
+ // target, including outer attributes. `None` if there are no outer
51
+ // attributes.
52
+ start_pos : Option < u32 > ,
38
53
}
39
54
40
55
impl AttrWrapper {
41
56
pub ( super ) fn new ( attrs : AttrVec , start_pos : u32 ) -> AttrWrapper {
42
- AttrWrapper { attrs, start_pos }
57
+ AttrWrapper { attrs, start_pos : Some ( start_pos ) }
43
58
}
44
- pub fn empty ( ) -> AttrWrapper {
45
- AttrWrapper { attrs : AttrVec :: new ( ) , start_pos : u32:: MAX }
59
+
60
+ pub ( super ) fn empty ( ) -> AttrWrapper {
61
+ AttrWrapper { attrs : AttrVec :: new ( ) , start_pos : None }
46
62
}
47
63
48
- pub ( crate ) fn take_for_recovery ( self , psess : & ParseSess ) -> AttrVec {
64
+ pub ( super ) fn take_for_recovery ( self , psess : & ParseSess ) -> AttrVec {
49
65
psess. dcx ( ) . span_delayed_bug (
50
66
self . attrs . get ( 0 ) . map ( |attr| attr. span ) . unwrap_or ( DUMMY_SP ) ,
51
67
"AttrVec is taken for recovery but no error is produced" ,
@@ -56,12 +72,12 @@ impl AttrWrapper {
56
72
57
73
/// Prepend `self.attrs` to `attrs`.
58
74
// FIXME: require passing an NT to prevent misuse of this method
59
- pub ( crate ) fn prepend_to_nt_inner ( mut self , attrs : & mut AttrVec ) {
75
+ pub ( super ) fn prepend_to_nt_inner ( mut self , attrs : & mut AttrVec ) {
60
76
mem:: swap ( attrs, & mut self . attrs ) ;
61
77
attrs. extend ( self . attrs ) ;
62
78
}
63
79
64
- pub fn is_empty ( & self ) -> bool {
80
+ pub ( super ) fn is_empty ( & self ) -> bool {
65
81
self . attrs . is_empty ( )
66
82
}
67
83
}
@@ -77,7 +93,7 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
77
93
}
78
94
79
95
// From a value of this type we can reconstruct the `TokenStream` seen by the
80
- // `f` callback passed to a call to `Parser::collect_tokens_trailing_token `, by
96
+ // `f` callback passed to a call to `Parser::collect_tokens `, by
81
97
// replaying the getting of the tokens. This saves us producing a `TokenStream`
82
98
// if it is never needed, e.g. a captured `macro_rules!` argument that is never
83
99
// passed to a proc macro. In practice, token stream creation happens rarely
@@ -166,16 +182,30 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
166
182
}
167
183
168
184
impl < ' a > Parser < ' a > {
185
+ pub ( super ) fn collect_pos ( & self ) -> CollectPos {
186
+ CollectPos {
187
+ start_token : ( self . token . clone ( ) , self . token_spacing ) ,
188
+ cursor_snapshot : self . token_cursor . clone ( ) ,
189
+ start_pos : self . num_bump_calls ,
190
+ }
191
+ }
192
+
169
193
/// Parses code with `f`. If appropriate, it records the tokens (in
170
194
/// `LazyAttrTokenStream` form) that were parsed in the result, accessible
171
- /// via the `HasTokens` trait. The second (bool) part of the callback's
195
+ /// via the `HasTokens` trait. The `Trailing` part of the callback's
172
196
/// result indicates if an extra token should be captured, e.g. a comma or
173
- /// semicolon.
197
+ /// semicolon. The `UsePreAttrPos` part of the callback's result indicates
198
+ /// if we should use `pre_attr_pos` as the collection start position (only
199
+ /// required in a few cases).
174
200
///
175
201
/// The `attrs` passed in are in `AttrWrapper` form, which is opaque. The
176
202
/// `AttrVec` within is passed to `f`. See the comment on `AttrWrapper` for
177
203
/// details.
178
204
///
205
+ /// `pre_attr_pos` is the position before the outer attributes (or the node
206
+ /// itself, if no outer attributes are present). It is only needed if `f`
207
+ /// can return `UsePreAttrPos::Yes`.
208
+ ///
179
209
/// Note: If your callback consumes an opening delimiter (including the
180
210
/// case where `self.token` is an opening delimiter on entry to this
181
211
/// function), you must also consume the corresponding closing delimiter.
@@ -197,11 +227,12 @@ impl<'a> Parser<'a> {
197
227
/// } // 32..33
198
228
/// } // 33..34
199
229
/// ```
200
- pub fn collect_tokens_trailing_token < R : HasAttrs + HasTokens > (
230
+ pub ( super ) fn collect_tokens < R : HasAttrs + HasTokens > (
201
231
& mut self ,
232
+ pre_attr_pos : Option < CollectPos > ,
202
233
attrs : AttrWrapper ,
203
234
force_collect : ForceCollect ,
204
- f : impl FnOnce ( & mut Self , ast :: AttrVec ) -> PResult < ' a , ( R , bool ) > ,
235
+ f : impl FnOnce ( & mut Self , AttrVec ) -> PResult < ' a , ( R , Trailing , UsePreAttrPos ) > ,
205
236
) -> PResult < ' a , R > {
206
237
// We must collect if anything could observe the collected tokens, i.e.
207
238
// if any of the following conditions hold.
@@ -220,23 +251,20 @@ impl<'a> Parser<'a> {
220
251
return Ok ( f ( self , attrs. attrs ) ?. 0 ) ;
221
252
}
222
253
223
- let start_token = ( self . token . clone ( ) , self . token_spacing ) ;
224
- let cursor_snapshot = self . token_cursor . clone ( ) ;
225
- let start_pos = self . num_bump_calls ;
254
+ let mut collect_pos = self . collect_pos ( ) ;
226
255
let has_outer_attrs = !attrs. attrs . is_empty ( ) ;
227
256
let parser_replacements_start = self . capture_state . parser_replacements . len ( ) ;
228
257
229
258
// We set and restore `Capturing::Yes` on either side of the call to
230
- // `f`, so we can distinguish the outermost call to
231
- // `collect_tokens_trailing_token` (e.g. parsing `m` in the example
232
- // above) from any inner (indirectly recursive) calls (e.g. parsing `g`
233
- // in the example above). This distinction is used below and in
234
- // `Parser::parse_inner_attributes`.
235
- let ( mut ret, capture_trailing) = {
259
+ // `f`, so we can distinguish the outermost call to `collect_tokens`
260
+ // (e.g. parsing `m` in the example above) from any inner (indirectly
261
+ // recursive) calls (e.g. parsing `g` in the example above). This
262
+ // distinction is used below and in `Parser::parse_inner_attributes`.
263
+ let ( mut ret, capture_trailing, use_pre_attr_pos) = {
236
264
let prev_capturing = mem:: replace ( & mut self . capture_state . capturing , Capturing :: Yes ) ;
237
- let ret_and_trailing = f ( self , attrs. attrs ) ;
265
+ let res = f ( self , attrs. attrs ) ;
238
266
self . capture_state . capturing = prev_capturing;
239
- ret_and_trailing ?
267
+ res ?
240
268
} ;
241
269
242
270
// When we're not in `capture_cfg` mode, then skip collecting and
@@ -279,10 +307,18 @@ impl<'a> Parser<'a> {
279
307
return Ok ( ret) ;
280
308
}
281
309
310
+ // Replace the post-attribute collection start position with the
311
+ // pre-attribute position supplied, if `f` indicated it is necessary.
312
+ // (The caller is responsible for providing a non-`None` `pre_attr_pos`
313
+ // if this is a possibility.)
314
+ if matches ! ( use_pre_attr_pos, UsePreAttrPos :: Yes ) {
315
+ collect_pos = pre_attr_pos. unwrap ( ) ;
316
+ }
317
+
282
318
let parser_replacements_end = self . capture_state . parser_replacements . len ( ) ;
283
319
284
320
assert ! (
285
- !( self . break_last_token && capture_trailing) ,
321
+ !( self . break_last_token && matches! ( capture_trailing, Trailing :: Yes ) ) ,
286
322
"Cannot set break_last_token and have trailing token"
287
323
) ;
288
324
@@ -294,7 +330,7 @@ impl<'a> Parser<'a> {
294
330
// `AttrTokenStream`, we will create the proper token.
295
331
+ self . break_last_token as u32 ;
296
332
297
- let num_calls = end_pos - start_pos;
333
+ let num_calls = end_pos - collect_pos . start_pos ;
298
334
299
335
// Take the captured `ParserRange`s for any inner attributes that we parsed in
300
336
// `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
@@ -328,7 +364,9 @@ impl<'a> Parser<'a> {
328
364
. iter ( )
329
365
. cloned ( )
330
366
. chain ( inner_attr_parser_replacements. iter ( ) . cloned ( ) )
331
- . map ( |( parser_range, data) | ( NodeRange :: new ( parser_range, start_pos) , data) )
367
+ . map ( |( parser_range, data) | {
368
+ ( NodeRange :: new ( parser_range, collect_pos. start_pos ) , data)
369
+ } )
332
370
. collect ( )
333
371
} ;
334
372
@@ -355,9 +393,9 @@ impl<'a> Parser<'a> {
355
393
// - `tokens`: lazy tokens for `g` (with its inner attr deleted).
356
394
357
395
let tokens = LazyAttrTokenStream :: new ( LazyAttrTokenStreamImpl {
358
- start_token,
396
+ start_token : collect_pos. start_token ,
397
+ cursor_snapshot : collect_pos. cursor_snapshot ,
359
398
num_calls,
360
- cursor_snapshot,
361
399
break_last_token : self . break_last_token ,
362
400
node_replacements,
363
401
} ) ;
@@ -368,9 +406,9 @@ impl<'a> Parser<'a> {
368
406
}
369
407
370
408
// If `capture_cfg` is set and we're inside a recursive call to
371
- // `collect_tokens_trailing_token `, then we need to register a replace range
372
- // if we have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager cfg-expansion
373
- // on the captured token stream.
409
+ // `collect_tokens `, then we need to register a replace range if we
410
+ // have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager
411
+ // cfg-expansion on the captured token stream.
374
412
if self . capture_cfg
375
413
&& matches ! ( self . capture_state. capturing, Capturing :: Yes )
376
414
&& has_cfg_or_cfg_attr ( ret. attrs ( ) )
@@ -389,7 +427,8 @@ impl<'a> Parser<'a> {
389
427
// Set things up so that the entire AST node that we just parsed, including attributes,
390
428
// will be replaced with `target` in the lazy token stream. This will allow us to
391
429
// cfg-expand this AST node.
392
- let start_pos = if has_outer_attrs { attrs. start_pos } else { start_pos } ;
430
+ let start_pos =
431
+ if has_outer_attrs { attrs. start_pos . unwrap ( ) } else { collect_pos. start_pos } ;
393
432
let target = AttrsTarget { attrs : ret. attrs ( ) . iter ( ) . cloned ( ) . collect ( ) , tokens } ;
394
433
self . capture_state
395
434
. parser_replacements
@@ -490,7 +529,6 @@ mod size_asserts {
490
529
491
530
use super :: * ;
492
531
// tidy-alphabetical-start
493
- static_assert_size ! ( AttrWrapper , 16 ) ;
494
532
static_assert_size ! ( LazyAttrTokenStreamImpl , 96 ) ;
495
533
// tidy-alphabetical-end
496
534
}
0 commit comments