Skip to content

Commit 7f6b06c

Browse files
committed
Fix a problem with metavars and inner attributes.
1 parent 4df3024 commit 7f6b06c

File tree

2 files changed

+53
-22
lines changed

2 files changed

+53
-22
lines changed

compiler/rustc_ast/src/tokenstream.rs

+39-22
Original file line numberDiff line numberDiff line change
@@ -233,35 +233,52 @@ fn attrs_and_tokens_to_token_trees(
233233

234234
// Insert inner attribute tokens.
235235
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.
236+
let found = insert_inner_attrs(inner_attrs, res);
237+
assert!(found, "Failed to find trailing delimited group in: {res:?}");
238+
}
239+
240+
// Inner attributes are only supported on blocks, functions, impls, and
241+
// modules. All of these have their inner attributes placed at the
242+
// beginning of the rightmost outermost braced group:
243+
// e.g. `fn foo() { #![my_attr] }`. (Note: the braces may be within
244+
// invisible delimiters.)
245+
//
246+
// Therefore, we can insert them back into the right location without
247+
// needing to do any extra position tracking.
248+
//
249+
// Note: Outline modules are an exception - they can have attributes like
250+
// `#![my_attr]` at the start of a file. Support for custom attributes in
251+
// this position is not properly implemented - we always synthesize fake
252+
// tokens, so we never reach this code.
253+
fn insert_inner_attrs(inner_attrs: &[Attribute], tts: &mut Vec<TokenTree>) -> bool {
254+
for tree in tts.iter_mut().rev() {
255+
if let TokenTree::Delimited(span, spacing, Delimiter::Brace, stream) = tree {
256+
// Found it: the rightmost, outermost braced group.
253257
let mut tts = vec![];
254258
for inner_attr in inner_attrs {
255259
tts.extend(inner_attr.token_trees());
256260
}
257-
tts.extend(delim_tokens.0.iter().cloned());
261+
tts.extend(stream.0.iter().cloned());
258262
let stream = TokenStream::new(tts);
259-
*tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
260-
found = true;
261-
break;
263+
*tree = TokenTree::Delimited(*span, *spacing, Delimiter::Brace, stream);
264+
return true;
265+
} else if let TokenTree::Delimited(span, spacing, Delimiter::Invisible(src), stream) =
266+
tree
267+
{
268+
// Recurse inside invisible delimiters.
269+
let mut vec: Vec<_> = stream.iter().cloned().collect();
270+
if insert_inner_attrs(inner_attrs, &mut vec) {
271+
*tree = TokenTree::Delimited(
272+
*span,
273+
*spacing,
274+
Delimiter::Invisible(*src),
275+
TokenStream::new(vec),
276+
);
277+
return true;
278+
}
262279
}
263280
}
264-
assert!(found, "Failed to find trailing delimited group in: {res:?}");
281+
false
265282
}
266283
}
267284

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ check-pass
2+
//
3+
// During `Nonterminal` removal (#124141) there was at one point a problem with
4+
// calling from_ast on expressions with inner attributes within metavars -- the
5+
// inner attributes were being inserted in the wrong place in `from_ast`. This
6+
// test covers that case.
7+
8+
macro_rules! m3 { ($e:expr) => {} }
9+
macro_rules! m2 { ($e:expr) => { m3!($e); } }
10+
macro_rules! m1 { ($e:expr) => { m2!($e); } }
11+
12+
m1!({ #![allow(unused)] 0 });
13+
14+
fn main() {}

0 commit comments

Comments
 (0)