@@ -12,40 +12,56 @@ use rustc_span::{sym, Span, DUMMY_SP};
1212
1313use super :: {
1414 Capturing , FlatToken , ForceCollect , NodeRange , NodeReplacement , Parser , ParserRange ,
15- TokenCursor ,
15+ TokenCursor , Trailing ,
1616} ;
1717
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+
1832/// A wrapper type to ensure that the parser handles outer attributes correctly.
1933/// When we parse outer attributes, we need to ensure that we capture tokens
2034/// for the attribute target. This allows us to perform cfg-expansion on
2135/// a token stream before we invoke a derive proc-macro.
2236///
2337/// This wrapper prevents direct access to the underlying `ast::AttrVec`.
2438/// 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 `.
2640/// This makes it difficult to accidentally construct an AST node
2741/// (which stores an `ast::AttrVec`) without first collecting tokens.
2842///
2943/// This struct has its own module, to ensure that the parser code
3044/// cannot directly access the `attrs` field.
3145#[ derive( Debug , Clone ) ]
32- pub struct AttrWrapper {
46+ pub ( super ) struct AttrWrapper {
3347 attrs : AttrVec ,
3448 // The start of the outer attributes in the parser's token stream.
3549 // 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 > ,
3853}
3954
4055impl AttrWrapper {
4156 pub ( super ) fn new ( attrs : AttrVec , start_pos : u32 ) -> AttrWrapper {
42- AttrWrapper { attrs, start_pos }
57+ AttrWrapper { attrs, start_pos : Some ( start_pos ) }
4358 }
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 }
4662 }
4763
48- pub ( crate ) fn take_for_recovery ( self , psess : & ParseSess ) -> AttrVec {
64+ pub ( super ) fn take_for_recovery ( self , psess : & ParseSess ) -> AttrVec {
4965 psess. dcx ( ) . span_delayed_bug (
5066 self . attrs . get ( 0 ) . map ( |attr| attr. span ) . unwrap_or ( DUMMY_SP ) ,
5167 "AttrVec is taken for recovery but no error is produced" ,
@@ -56,12 +72,12 @@ impl AttrWrapper {
5672
5773 /// Prepend `self.attrs` to `attrs`.
5874 // 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 ) {
6076 mem:: swap ( attrs, & mut self . attrs ) ;
6177 attrs. extend ( self . attrs ) ;
6278 }
6379
64- pub fn is_empty ( & self ) -> bool {
80+ pub ( super ) fn is_empty ( & self ) -> bool {
6581 self . attrs . is_empty ( )
6682 }
6783}
@@ -77,7 +93,7 @@ fn has_cfg_or_cfg_attr(attrs: &[Attribute]) -> bool {
7793}
7894
7995// 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
8197// replaying the getting of the tokens. This saves us producing a `TokenStream`
8298// if it is never needed, e.g. a captured `macro_rules!` argument that is never
8399// passed to a proc macro. In practice, token stream creation happens rarely
@@ -166,16 +182,30 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
166182}
167183
168184impl < ' 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+
169193 /// Parses code with `f`. If appropriate, it records the tokens (in
170194 /// `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
172196 /// 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).
174200 ///
175201 /// The `attrs` passed in are in `AttrWrapper` form, which is opaque. The
176202 /// `AttrVec` within is passed to `f`. See the comment on `AttrWrapper` for
177203 /// details.
178204 ///
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+ ///
179209 /// Note: If your callback consumes an opening delimiter (including the
180210 /// case where `self.token` is an opening delimiter on entry to this
181211 /// function), you must also consume the corresponding closing delimiter.
@@ -197,11 +227,12 @@ impl<'a> Parser<'a> {
197227 /// } // 32..33
198228 /// } // 33..34
199229 /// ```
200- pub fn collect_tokens_trailing_token < R : HasAttrs + HasTokens > (
230+ pub ( super ) fn collect_tokens < R : HasAttrs + HasTokens > (
201231 & mut self ,
232+ pre_attr_pos : Option < CollectPos > ,
202233 attrs : AttrWrapper ,
203234 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 ) > ,
205236 ) -> PResult < ' a , R > {
206237 // We must collect if anything could observe the collected tokens, i.e.
207238 // if any of the following conditions hold.
@@ -220,23 +251,20 @@ impl<'a> Parser<'a> {
220251 return Ok ( f ( self , attrs. attrs ) ?. 0 ) ;
221252 }
222253
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 ( ) ;
226255 let has_outer_attrs = !attrs. attrs . is_empty ( ) ;
227256 let parser_replacements_start = self . capture_state . parser_replacements . len ( ) ;
228257
229258 // 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) = {
236264 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 ) ;
238266 self . capture_state . capturing = prev_capturing;
239- ret_and_trailing ?
267+ res ?
240268 } ;
241269
242270 // When we're not in `capture_cfg` mode, then skip collecting and
@@ -279,10 +307,18 @@ impl<'a> Parser<'a> {
279307 return Ok ( ret) ;
280308 }
281309
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+
282318 let parser_replacements_end = self . capture_state . parser_replacements . len ( ) ;
283319
284320 assert ! (
285- !( self . break_last_token && capture_trailing) ,
321+ !( self . break_last_token && matches! ( capture_trailing, Trailing :: Yes ) ) ,
286322 "Cannot set break_last_token and have trailing token"
287323 ) ;
288324
@@ -294,7 +330,7 @@ impl<'a> Parser<'a> {
294330 // `AttrTokenStream`, we will create the proper token.
295331 + self . break_last_token as u32 ;
296332
297- let num_calls = end_pos - start_pos;
333+ let num_calls = end_pos - collect_pos . start_pos ;
298334
299335 // Take the captured `ParserRange`s for any inner attributes that we parsed in
300336 // `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
@@ -328,7 +364,9 @@ impl<'a> Parser<'a> {
328364 . iter ( )
329365 . cloned ( )
330366 . 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+ } )
332370 . collect ( )
333371 } ;
334372
@@ -355,9 +393,9 @@ impl<'a> Parser<'a> {
355393 // - `tokens`: lazy tokens for `g` (with its inner attr deleted).
356394
357395 let tokens = LazyAttrTokenStream :: new ( LazyAttrTokenStreamImpl {
358- start_token,
396+ start_token : collect_pos. start_token ,
397+ cursor_snapshot : collect_pos. cursor_snapshot ,
359398 num_calls,
360- cursor_snapshot,
361399 break_last_token : self . break_last_token ,
362400 node_replacements,
363401 } ) ;
@@ -368,9 +406,9 @@ impl<'a> Parser<'a> {
368406 }
369407
370408 // 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.
374412 if self . capture_cfg
375413 && matches ! ( self . capture_state. capturing, Capturing :: Yes )
376414 && has_cfg_or_cfg_attr ( ret. attrs ( ) )
@@ -389,7 +427,8 @@ impl<'a> Parser<'a> {
389427 // Set things up so that the entire AST node that we just parsed, including attributes,
390428 // will be replaced with `target` in the lazy token stream. This will allow us to
391429 // 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 } ;
393432 let target = AttrsTarget { attrs : ret. attrs ( ) . iter ( ) . cloned ( ) . collect ( ) , tokens } ;
394433 self . capture_state
395434 . parser_replacements
@@ -490,7 +529,6 @@ mod size_asserts {
490529
491530 use super :: * ;
492531 // tidy-alphabetical-start
493- static_assert_size ! ( AttrWrapper , 16 ) ;
494532 static_assert_size ! ( LazyAttrTokenStreamImpl , 96 ) ;
495533 // tidy-alphabetical-end
496534}
0 commit comments