@@ -60,10 +60,6 @@ impl AttrWrapper {
60
60
pub fn is_empty ( & self ) -> bool {
61
61
self . attrs . is_empty ( )
62
62
}
63
-
64
- pub fn is_complete ( & self ) -> bool {
65
- crate :: parser:: attr:: is_complete ( & self . attrs )
66
- }
67
63
}
68
64
69
65
/// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute
@@ -199,20 +195,20 @@ impl<'a> Parser<'a> {
199
195
force_collect : ForceCollect ,
200
196
f : impl FnOnce ( & mut Self , ast:: AttrVec ) -> PResult < ' a , ( R , bool ) > ,
201
197
) -> PResult < ' a , R > {
202
- // Skip collection when nothing could observe the collected tokens, i.e.
203
- // all of the following conditions hold.
204
- // - We are not force collecting tokens (because force collection
205
- // requires tokens by definition).
206
- if matches ! ( force_collect, ForceCollect :: No )
207
- // - None of our outer attributes require tokens.
208
- && attrs. is_complete ( )
209
- // - Our target doesn't support custom inner attributes (custom
198
+ // We must collect if anything could observe the collected tokens, i.e.
199
+ // if any of the following conditions hold.
200
+ // - We are force collecting tokens (because force collection requires
201
+ // tokens by definition).
202
+ let needs_collection = matches ! ( force_collect, ForceCollect :: Yes )
203
+ // - Any of our outer attributes require tokens.
204
+ || needs_tokens ( & attrs. attrs )
205
+ // - Our target supports custom inner attributes (custom
210
206
// inner attribute invocation might require token capturing).
211
- && ! R :: SUPPORTS_CUSTOM_INNER_ATTRS
212
- // - We are not in `capture_cfg` mode (which requires tokens if
207
+ || R :: SUPPORTS_CUSTOM_INNER_ATTRS
208
+ // - We are in `capture_cfg` mode (which requires tokens if
213
209
// the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
214
- && ! self . capture_cfg
215
- {
210
+ || self . capture_cfg ;
211
+ if !needs_collection {
216
212
return Ok ( f ( self , attrs. attrs ) ?. 0 ) ;
217
213
}
218
214
@@ -250,28 +246,28 @@ impl<'a> Parser<'a> {
250
246
return Ok ( ret) ;
251
247
}
252
248
253
- // This is similar to the "skip collection" check at the start of this
254
- // function, but now that we've parsed an AST node we have more
249
+ // This is similar to the `needs_collection` check at the start of this
250
+ // function, but now that we've parsed an AST node we have complete
255
251
// information available. (If we return early here that means the
256
252
// setup, such as cloning the token cursor, was unnecessary. That's
257
253
// hard to avoid.)
258
254
//
259
- // Skip collection when nothing could observe the collected tokens, i.e.
260
- // all of the following conditions hold.
261
- // - We are not force collecting tokens.
262
- if matches ! ( force_collect, ForceCollect :: No )
263
- // - None of our outer *or* inner attributes require tokens.
264
- // (`attrs` was just outer attributes, but `ret.attrs()` is outer
265
- // and inner attributes. That makes this check more precise than
266
- // `attrs.is_complete()` at the start of the function , and we can
267
- // skip the subsequent check on `R::SUPPORTS_CUSTOM_INNER_ATTRS`.
268
- && crate :: parser :: attr :: is_complete ( ret. attrs ( ) )
269
- // - We are not in `capture_cfg` mode, or we are but there are no
270
- // `#[cfg]` or `#[ cfg_attr]` attributes. (During normal
271
- // non-`capture_cfg` parsing, we don't need any special capturing
272
- // for those attributes, because they're builtin.)
273
- && ( ! self . capture_cfg || ! has_cfg_or_cfg_attr ( ret. attrs ( ) ) )
274
- {
255
+ // We must collect if anything could observe the collected tokens, i.e.
256
+ // if any of the following conditions hold.
257
+ // - We are force collecting tokens.
258
+ let needs_collection = matches ! ( force_collect, ForceCollect :: Yes )
259
+ // - Any of our outer *or* inner attributes require tokens.
260
+ // (`attr. attrs` was just outer attributes, but `ret.attrs()` is
261
+ // outer and inner attributes. So this check is more precise than
262
+ // the earlier `needs_tokens` check , and we don't need to
263
+ // check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
264
+ || needs_tokens ( ret. attrs ( ) )
265
+ // - We are in `capture_cfg` mode and there are `#[cfg]` or
266
+ // `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
267
+ // parsing, we don't need any special capturing for those
268
+ // attributes, because they're builtin.)
269
+ || ( self . capture_cfg && has_cfg_or_cfg_attr ( ret. attrs ( ) ) ) ;
270
+ if !needs_collection {
275
271
return Ok ( ret) ;
276
272
}
277
273
@@ -461,6 +457,19 @@ fn make_attr_token_stream(
461
457
AttrTokenStream :: new ( stack_top. inner )
462
458
}
463
459
460
+ /// Tokens are needed if:
461
+ /// - any non-single-segment attributes (other than doc comments) are present; or
462
+ /// - any `cfg_attr` attributes are present;
463
+ /// - any single-segment, non-builtin attributes are present.
464
+ fn needs_tokens ( attrs : & [ ast:: Attribute ] ) -> bool {
465
+ attrs. iter ( ) . any ( |attr| match attr. ident ( ) {
466
+ None => !attr. is_doc_comment ( ) ,
467
+ Some ( ident) => {
468
+ ident. name == sym:: cfg_attr || !rustc_feature:: is_builtin_attr_name ( ident. name )
469
+ }
470
+ } )
471
+ }
472
+
464
473
// Some types are used a lot. Make sure they don't unintentionally get bigger.
465
474
#[ cfg( target_pointer_width = "64" ) ]
466
475
mod size_asserts {
0 commit comments