@@ -60,10 +60,6 @@ impl AttrWrapper {
6060 pub fn is_empty ( & self ) -> bool {
6161 self . attrs . is_empty ( )
6262 }
63-
64- pub fn is_complete ( & self ) -> bool {
65- crate :: parser:: attr:: is_complete ( & self . attrs )
66- }
6763}
6864
6965/// Returns `true` if `attrs` contains a `cfg` or `cfg_attr` attribute
@@ -199,20 +195,20 @@ impl<'a> Parser<'a> {
199195 force_collect : ForceCollect ,
200196 f : impl FnOnce ( & mut Self , ast:: AttrVec ) -> PResult < ' a , ( R , bool ) > ,
201197 ) -> 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
210206 // 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
213209 // the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
214- && ! self . capture_cfg
215- {
210+ || self . capture_cfg ;
211+ if !needs_collection {
216212 return Ok ( f ( self , attrs. attrs ) ?. 0 ) ;
217213 }
218214
@@ -250,28 +246,28 @@ impl<'a> Parser<'a> {
250246 return Ok ( ret) ;
251247 }
252248
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
255251 // information available. (If we return early here that means the
256252 // setup, such as cloning the token cursor, was unnecessary. That's
257253 // hard to avoid.)
258254 //
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 {
275271 return Ok ( ret) ;
276272 }
277273
@@ -461,6 +457,19 @@ fn make_attr_token_stream(
461457 AttrTokenStream :: new ( stack_top. inner )
462458}
463459
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+
464473// Some types are used a lot. Make sure they don't unintentionally get bigger.
465474#[ cfg( target_pointer_width = "64" ) ]
466475mod size_asserts {
0 commit comments