Skip to content

Commit 372b567

Browse files
committed
Always collect tokens when we are already inside a collect_tokens call
Fixes #81007 This is needed to ensure that the `LazyTokenStream` we use does not include attributes - the outer call may include the attributes, which we don't want to include in the `LazyTokenSTream`.
1 parent 18ec4a9 commit 372b567

File tree

8 files changed

+166
-18
lines changed

8 files changed

+166
-18
lines changed

compiler/rustc_parse/src/parser/attr.rs

+1-13
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_ast::attr;
44
use rustc_ast::token::{self, Nonterminal};
55
use rustc_ast_pretty::pprust;
66
use rustc_errors::{error_code, PResult};
7-
use rustc_span::{sym, Span};
7+
use rustc_span::Span;
88

99
use tracing::debug;
1010

@@ -304,15 +304,3 @@ impl<'a> Parser<'a> {
304304
Err(self.struct_span_err(self.token.span, &msg))
305305
}
306306
}
307-
308-
pub fn maybe_needs_tokens(attrs: &[ast::Attribute]) -> bool {
309-
// One of the attributes may either itself be a macro, or apply derive macros (`derive`),
310-
// or expand to macro attributes (`cfg_attr`).
311-
attrs.iter().any(|attr| {
312-
attr.ident().map_or(true, |ident| {
313-
ident.name == sym::derive
314-
|| ident.name == sym::cfg_attr
315-
|| !rustc_feature::is_builtin_attr_name(ident.name)
316-
})
317-
})
318-
}

compiler/rustc_parse/src/parser/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -472,7 +472,7 @@ impl<'a> Parser<'a> {
472472
/// Parses a prefix-unary-operator expr.
473473
fn parse_prefix_expr(&mut self, attrs: Option<AttrVec>) -> PResult<'a, P<Expr>> {
474474
let attrs = self.parse_or_use_outer_attributes(attrs)?;
475-
let needs_tokens = super::attr::maybe_needs_tokens(&attrs);
475+
let needs_tokens = self.maybe_needs_tokens(&attrs);
476476
let do_parse = |this: &mut Parser<'a>| {
477477
let lo = this.token.span;
478478
// Note: when adding new unary operators, don't forget to adjust TokenKind::can_begin_expr()

compiler/rustc_parse/src/parser/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ impl<'a> Parser<'a> {
116116
Some(item.into_inner())
117117
});
118118

119-
let needs_tokens = super::attr::maybe_needs_tokens(&attrs);
119+
let needs_tokens = self.maybe_needs_tokens(&attrs);
120120

121121
let mut unclosed_delims = vec![];
122122
let parse_item = |this: &mut Self| {

compiler/rustc_parse/src/parser/mod.rs

+31-1
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub struct Parser<'a> {
116116
pub last_type_ascription: Option<(Span, bool /* likely path typo */)>,
117117
/// If present, this `Parser` is not parsing Rust code but rather a macro call.
118118
subparser_name: Option<&'static str>,
119+
collecting: bool,
119120
}
120121

121122
impl<'a> Drop for Parser<'a> {
@@ -367,6 +368,7 @@ impl<'a> Parser<'a> {
367368
last_unexpected_token_span: None,
368369
last_type_ascription: None,
369370
subparser_name,
371+
collecting: false,
370372
};
371373

372374
// Make parser point to the first token.
@@ -1218,6 +1220,31 @@ impl<'a> Parser<'a> {
12181220
}
12191221
}
12201222

1223+
/// Returns `true` if we might need to have tokens available for
1224+
/// the attribute target, and `false` if we definitely do not need tokens.
1225+
pub(super) fn maybe_needs_tokens(&self, attrs: &[ast::Attribute]) -> bool {
1226+
// If we are already inside a call to `collect_tokens`, then always
1227+
// collect tokens. If the outer `collect_tokens` call ends up returning
1228+
// the same AST node (for example, during nonterminal parsing), we
1229+
// want to make sure that we already have a `LazyTokenStream` set
1230+
// (from the inner `collect_tokens` call). The innermost call
1231+
// will correctly exclude the attributes from the `TokenStream`,
1232+
// while the outer call will end up capturing the attribute tokens
1233+
// in its (discarded) `LazyTokenStream`
1234+
self.collecting || {
1235+
// One of the attributes may either itself be a macro,
1236+
// or expand to macro attributes (`cfg_attr`). In either case,
1237+
// we need tokens available to pass to the macro invocation
1238+
attrs.iter().any(|attr| {
1239+
attr.ident().map_or(true, |ident| {
1240+
ident.name == sym::derive
1241+
|| ident.name == sym::cfg_attr
1242+
|| !rustc_feature::is_builtin_attr_name(ident.name)
1243+
})
1244+
})
1245+
}
1246+
}
1247+
12211248
/// Records all tokens consumed by the provided callback,
12221249
/// including the current token. These tokens are collected
12231250
/// into a `LazyTokenStream`, and returned along with the result
@@ -1249,7 +1276,10 @@ impl<'a> Parser<'a> {
12491276
append_unglued_token: self.token_cursor.append_unglued_token.clone(),
12501277
};
12511278

1252-
let mut ret = f(self)?;
1279+
let prev_collecting = std::mem::replace(&mut self.collecting, true);
1280+
let ret = f(self);
1281+
self.collecting = prev_collecting;
1282+
let mut ret = ret?;
12531283

12541284
// Produces a `TokenStream` on-demand. Using `cursor_snapshot`
12551285
// and `num_calls`, we can reconstruct the `TokenStream` seen
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
1+
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":null}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
1+
{"module":{"inner":{"lo":0,"hi":0},"unsafety":"No","items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":"Empty","tokens":null},null]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"kind":"Inherited","span":{"lo":0,"hi":0},"tokens":null},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}],"tokens":null},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"kind":{"variant":"Interpolated","fields":[{"variant":"NtExpr","fields":[{"id":0,"kind":{"variant":"Lit","fields":[{"token":{"kind":"Str","symbol":"lib","suffix":null},"kind":{"variant":"Str","fields":["lib","Cooked"]},"span":{"lo":0,"hi":0}}]},"span":{"lo":0,"hi":0},"attrs":{"0":null},"tokens":{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}}]}]},"span":{"lo":0,"hi":0}}]},"tokens":null},{"0":[[{"variant":"Token","fields":[{"kind":"Pound","span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Not","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Delimited","fields":[{"open":{"lo":0,"hi":0},"close":{"lo":0,"hi":0}},"Bracket",{"0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate_type",false]},"span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":"Eq","span":{"lo":0,"hi":0}}]},"Alone"],[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"Alone"]]}]},"Alone"]]}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// check-pass
2+
// edition:2018
3+
// compile-flags: -Z span-debug
4+
// aux-build:test-macros.rs
5+
6+
#![feature(rustc_attrs)]
7+
8+
#![no_std] // Don't load unnecessary hygiene information from std
9+
extern crate std;
10+
11+
#[macro_use] extern crate test_macros;
12+
13+
macro_rules! capture_item {
14+
($item:item) => {
15+
#[print_attr]
16+
$item
17+
}
18+
}
19+
20+
capture_item! {
21+
/// A doc comment
22+
struct Foo {}
23+
}
24+
25+
capture_item! {
26+
#[rustc_dummy]
27+
/// Another comment comment
28+
struct Bar {}
29+
}
30+
31+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
PRINT-ATTR INPUT (DISPLAY): #[doc = r" A doc comment"] struct Foo { }
2+
PRINT-ATTR INPUT (DEBUG): TokenStream [
3+
Punct {
4+
ch: '#',
5+
spacing: Alone,
6+
span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
7+
},
8+
Group {
9+
delimiter: Bracket,
10+
stream: TokenStream [
11+
Ident {
12+
ident: "doc",
13+
span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
14+
},
15+
Punct {
16+
ch: '=',
17+
spacing: Alone,
18+
span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
19+
},
20+
Literal {
21+
kind: StrRaw(0),
22+
symbol: " A doc comment",
23+
suffix: None,
24+
span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
25+
},
26+
],
27+
span: $DIR/issue-81007-item-attrs.rs:21:5: 21:22 (#0),
28+
},
29+
Ident {
30+
ident: "struct",
31+
span: $DIR/issue-81007-item-attrs.rs:22:5: 22:11 (#0),
32+
},
33+
Ident {
34+
ident: "Foo",
35+
span: $DIR/issue-81007-item-attrs.rs:22:12: 22:15 (#0),
36+
},
37+
Group {
38+
delimiter: Brace,
39+
stream: TokenStream [],
40+
span: $DIR/issue-81007-item-attrs.rs:22:16: 22:18 (#0),
41+
},
42+
]
43+
PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] #[doc = r" Another comment comment"] struct Bar { }
44+
PRINT-ATTR INPUT (DEBUG): TokenStream [
45+
Punct {
46+
ch: '#',
47+
spacing: Alone,
48+
span: $DIR/issue-81007-item-attrs.rs:26:5: 26:6 (#0),
49+
},
50+
Group {
51+
delimiter: Bracket,
52+
stream: TokenStream [
53+
Ident {
54+
ident: "rustc_dummy",
55+
span: $DIR/issue-81007-item-attrs.rs:26:7: 26:18 (#0),
56+
},
57+
],
58+
span: $DIR/issue-81007-item-attrs.rs:26:6: 26:19 (#0),
59+
},
60+
Punct {
61+
ch: '#',
62+
spacing: Alone,
63+
span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
64+
},
65+
Group {
66+
delimiter: Bracket,
67+
stream: TokenStream [
68+
Ident {
69+
ident: "doc",
70+
span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
71+
},
72+
Punct {
73+
ch: '=',
74+
spacing: Alone,
75+
span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
76+
},
77+
Literal {
78+
kind: StrRaw(0),
79+
symbol: " Another comment comment",
80+
suffix: None,
81+
span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
82+
},
83+
],
84+
span: $DIR/issue-81007-item-attrs.rs:27:5: 27:32 (#0),
85+
},
86+
Ident {
87+
ident: "struct",
88+
span: $DIR/issue-81007-item-attrs.rs:28:5: 28:11 (#0),
89+
},
90+
Ident {
91+
ident: "Bar",
92+
span: $DIR/issue-81007-item-attrs.rs:28:12: 28:15 (#0),
93+
},
94+
Group {
95+
delimiter: Brace,
96+
stream: TokenStream [],
97+
span: $DIR/issue-81007-item-attrs.rs:28:16: 28:18 (#0),
98+
},
99+
]

0 commit comments

Comments
 (0)