Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1b55759

Browse files
Fix a problem with metavars and inner attributes.
1 parent 9e549be commit 1b55759

File tree

2 files changed

+53
-22
lines changed

2 files changed

+53
-22
lines changed

‎compiler/rustc_ast/src/tokenstream.rs‎

Lines changed: 39 additions & 22 deletions
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

Lines changed: 14 additions & 0 deletions
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)

AltStyle によって変換されたページ (->オリジナル) /