1616use crate :: ast:: { AttrStyle , StmtKind } ;
1717use crate :: ast_traits:: { HasAttrs , HasTokens } ;
1818use crate :: token:: { self , Delimiter , Nonterminal , Token , TokenKind } ;
19- use crate :: AttrVec ;
19+ use crate :: { AttrVec , Attribute } ;
2020
2121use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
2222use rustc_data_structures:: sync:: { self , Lrc } ;
@@ -179,11 +179,10 @@ impl AttrTokenStream {
179179 AttrTokenStream ( Lrc :: new ( tokens) )
180180 }
181181
182- /// Converts this `AttrTokenStream` to a plain `Vec<TokenTree>`.
183- /// During conversion, `AttrTokenTree::AttrsTarget` get 'flattened'
184- /// back to a `TokenStream` of the form `outer_attr attr_target`.
185- /// If there are inner attributes, they are inserted into the proper
186- /// place in the attribute target tokens.
182+ /// Converts this `AttrTokenStream` to a plain `Vec<TokenTree>`. During
183+ /// conversion, any `AttrTokenTree::AttrsTarget` gets "flattened" back to a
184+ /// `TokenStream`, as described in the comment on
185+ /// `attrs_and_tokens_to_token_trees`.
187186 pub fn to_token_trees ( & self ) -> Vec < TokenTree > {
188187 let mut res = Vec :: with_capacity ( self . 0 . len ( ) ) ;
189188 for tree in self . 0 . iter ( ) {
@@ -200,67 +199,84 @@ impl AttrTokenStream {
200199 ) )
201200 }
202201 AttrTokenTree :: AttrsTarget ( target) => {
203- let idx = target
204- . attrs
205- . partition_point ( |attr| matches ! ( attr. style, crate :: AttrStyle :: Outer ) ) ;
206- let ( outer_attrs, inner_attrs) = target. attrs . split_at ( idx) ;
207-
208- let mut target_tokens = target. tokens . to_attr_token_stream ( ) . to_token_trees ( ) ;
209- if !inner_attrs. is_empty ( ) {
210- let mut found = false ;
211- // Check the last two trees (to account for a trailing semi)
212- for tree in target_tokens. iter_mut ( ) . rev ( ) . take ( 2 ) {
213- if let TokenTree :: Delimited ( span, spacing, delim, delim_tokens) = tree {
214- // Inner attributes are only supported on extern blocks, functions,
215- // impls, and modules. All of these have their inner attributes
216- // placed at the beginning of the rightmost outermost braced group:
217- // e.g. fn foo() { #![my_attr] }
218- //
219- // Therefore, we can insert them back into the right location
220- // without needing to do any extra position tracking.
221- //
222- // Note: Outline modules are an exception - they can
223- // have attributes like `#![my_attr]` at the start of a file.
224- // Support for custom attributes in this position is not
225- // properly implemented - we always synthesize fake tokens,
226- // so we never reach this code.
227-
228- let mut stream = TokenStream :: default ( ) ;
229- for inner_attr in inner_attrs {
230- stream. push_stream ( inner_attr. get_tokens ( ) ) ;
231- }
232- stream. push_stream ( delim_tokens. clone ( ) ) ;
233- * tree = TokenTree :: Delimited ( * span, * spacing, * delim, stream) ;
234- found = true ;
235- break ;
236- }
237- }
238-
239- assert ! (
240- found,
241- "Failed to find trailing delimited group in: {target_tokens:?}"
242- ) ;
243- }
244- for attr in outer_attrs {
245- res. extend ( attr. get_tokens ( ) . 0 . iter ( ) . cloned ( ) ) ;
246- }
247- res. extend ( target_tokens) ;
202+ attrs_and_tokens_to_token_trees ( & target. attrs , & target. tokens , & mut res) ;
248203 }
249204 }
250205 }
251206 res
252207 }
253208}
254209
210+ // Converts multiple attributes and the tokens for a target AST node into token trees, and appends
211+ // them to `res`.
212+ //
213+ // Example: if the AST node is "fn f() { blah(); }", then:
214+ // - Simple if no attributes are present, e.g. "fn f() { blah(); }"
215+ // - Simple if only outer attribute are present, e.g. "#[outer1] #[outer2] fn f() { blah(); }"
216+ // - Trickier if inner attributes are present, because they must be moved within the AST node's
217+ // tokens, e.g. "#[outer] fn f() { #![inner] blah() }"
218+ fn attrs_and_tokens_to_token_trees (
219+ attrs : & [ Attribute ] ,
220+ target_tokens : & LazyAttrTokenStream ,
221+ res : & mut Vec < TokenTree > ,
222+ ) {
223+ let idx = attrs. partition_point ( |attr| matches ! ( attr. style, crate :: AttrStyle :: Outer ) ) ;
224+ let ( outer_attrs, inner_attrs) = attrs. split_at ( idx) ;
225+
226+ // Add outer attribute tokens.
227+ for attr in outer_attrs {
228+ res. extend ( attr. token_trees ( ) ) ;
229+ }
230+
231+ // Add target AST node tokens.
232+ res. extend ( target_tokens. to_attr_token_stream ( ) . to_token_trees ( ) ) ;
233+
234+ // Insert inner attribute tokens.
235+ if !inner_attrs. is_empty ( ) {
236+ let mut found = false ;
237+ // Check the last two trees (to account for a trailing semi)
238+ for tree in res. iter_mut ( ) . rev ( ) . take ( 2 ) {
239+ if let TokenTree :: Delimited ( span, spacing, delim, delim_tokens) = tree {
240+ // Inner attributes are only supported on extern blocks, functions,
241+ // impls, and modules. All of these have their inner attributes
242+ // placed at the beginning of the rightmost outermost braced group:
243+ // e.g. fn foo() { #![my_attr] }
244+ //
245+ // Therefore, we can insert them back into the right location
246+ // without needing to do any extra position tracking.
247+ //
248+ // Note: Outline modules are an exception - they can
249+ // have attributes like `#![my_attr]` at the start of a file.
250+ // Support for custom attributes in this position is not
251+ // properly implemented - we always synthesize fake tokens,
252+ // so we never reach this code.
253+ let mut tts = vec ! [ ] ;
254+ for inner_attr in inner_attrs {
255+ tts. extend ( inner_attr. token_trees ( ) ) ;
256+ }
257+ tts. extend ( delim_tokens. 0 . iter ( ) . cloned ( ) ) ;
258+ let stream = TokenStream :: new ( tts) ;
259+ * tree = TokenTree :: Delimited ( * span, * spacing, * delim, stream) ;
260+ found = true ;
261+ break ;
262+ }
263+ }
264+ assert ! ( found, "Failed to find trailing delimited group in: {res:?}" ) ;
265+ }
266+ }
267+
255268/// Stores the tokens for an attribute target, along
256269/// with its attributes.
257270///
258271/// This is constructed during parsing when we need to capture
259- /// tokens.
272+ /// tokens, for `cfg` and `cfg_attr` attributes .
260273///
261274/// For example, `#[cfg(FALSE)] struct Foo {}` would
262275/// have an `attrs` field containing the `#[cfg(FALSE)]` attr,
263276/// and a `tokens` field storing the (unparsed) tokens `struct Foo {}`
277+ ///
278+ /// The `cfg`/`cfg_attr` processing occurs in
279+ /// `StripUnconfigured::configure_tokens`.
264280#[ derive( Clone , Debug , Encodable , Decodable ) ]
265281pub struct AttrsTarget {
266282 /// Attributes, both outer and inner.
@@ -437,18 +453,10 @@ impl TokenStream {
437453 }
438454
439455 pub fn from_ast ( node : & ( impl HasAttrs + HasTokens + fmt:: Debug ) ) -> TokenStream {
440- let Some ( tokens) = node. tokens ( ) else {
441- panic ! ( "missing tokens for node: {:?}" , node) ;
442- } ;
443- let attrs = node. attrs ( ) ;
444- let attr_stream = if attrs. is_empty ( ) {
445- tokens. to_attr_token_stream ( )
446- } else {
447- let target =
448- AttrsTarget { attrs : attrs. iter ( ) . cloned ( ) . collect ( ) , tokens : tokens. clone ( ) } ;
449- AttrTokenStream :: new ( vec ! [ AttrTokenTree :: AttrsTarget ( target) ] )
450- } ;
451- TokenStream :: new ( attr_stream. to_token_trees ( ) )
456+ let tokens = node. tokens ( ) . unwrap_or_else ( || panic ! ( "missing tokens for node: {:?}" , node) ) ;
457+ let mut tts = vec ! [ ] ;
458+ attrs_and_tokens_to_token_trees ( node. attrs ( ) , tokens, & mut tts) ;
459+ TokenStream :: new ( tts)
452460 }
453461
454462 pub fn from_nonterminal_ast ( nt : & Nonterminal ) -> TokenStream {
0 commit comments