Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 81ebaa6

Browse files
committedAug 17, 2019
Auto merge of #63674 - petrochenkov:meta2, r=<try>
syntax: Support modern attribute syntax in the `meta` matcher Where "modern" means #57367: ``` PATH PATH `(` TOKEN_STREAM `)` PATH `[` TOKEN_STREAM `]` PATH `{` TOKEN_STREAM `}` ``` Unfortunately, `meta` wasn't future-proofed using the `FOLLOW` token set like other matchers (#34011), so code like `$meta:meta {` or `$meta:meta [` may break, and we need a crater run to find out how often this happens in practice. Closes #49629 (by fully supporting `meta` rather than removing it.)
2 parents 2111aed + d73c85e commit 81ebaa6

File tree

14 files changed

+106
-84
lines changed

14 files changed

+106
-84
lines changed
 

‎src/librustc/hir/lowering.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -986,10 +986,12 @@ impl<'a> LoweringContext<'a> {
986986
// lower attributes (we use the AST version) there is nowhere to keep
987987
// the `HirId`s. We don't actually need HIR version of attributes anyway.
988988
Attribute {
989+
item: AttrItem {
990+
path: attr.path.clone(),
991+
tokens: self.lower_token_stream(attr.tokens.clone()),
992+
},
989993
id: attr.id,
990994
style: attr.style,
991-
path: attr.path.clone(),
992-
tokens: self.lower_token_stream(attr.tokens.clone()),
993995
is_sugared_doc: attr.is_sugared_doc,
994996
span: attr.span,
995997
}

‎src/librustc/ich/impls_syntax.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,11 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Path {
227227
}
228228
}
229229

230+
impl_stable_hash_for!(struct ::syntax::ast::AttrItem {
231+
path,
232+
tokens,
233+
});
234+
230235
impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
231236
fn hash_stable<W: StableHasherResult>(&self,
232237
hcx: &mut StableHashingContext<'a>,
@@ -236,19 +241,15 @@ impl<'a> HashStable<StableHashingContext<'a>> for ast::Attribute {
236241
debug_assert!(!self.is_sugared_doc);
237242

238243
let ast::Attribute {
244+
ref item,
239245
id: _,
240246
style,
241-
ref path,
242-
ref tokens,
243247
is_sugared_doc: _,
244248
span,
245249
} = *self;
246250

251+
item.hash_stable(hcx, hasher);
247252
style.hash_stable(hcx, hasher);
248-
path.hash_stable(hcx, hasher);
249-
for tt in tokens.trees() {
250-
tt.hash_stable(hcx, hasher);
251-
}
252253
span.hash_stable(hcx, hasher);
253254
}
254255
}

‎src/libsyntax/ast.rs

+12-2
Original file line numberDiff line numberDiff line change
@@ -2124,18 +2124,28 @@ impl rustc_serialize::Decodable for AttrId {
21242124
}
21252125
}
21262126

2127+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2128+
pub struct AttrItem {
2129+
pub path: Path,
2130+
pub tokens: TokenStream,
2131+
}
2132+
21272133
/// Metadata associated with an item.
21282134
/// Doc-comments are promoted to attributes that have `is_sugared_doc = true`.
21292135
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
21302136
pub struct Attribute {
2137+
pub item: AttrItem,
21312138
pub id: AttrId,
21322139
pub style: AttrStyle,
2133-
pub path: Path,
2134-
pub tokens: TokenStream,
21352140
pub is_sugared_doc: bool,
21362141
pub span: Span,
21372142
}
21382143

2144+
impl std::ops::Deref for Attribute {
2145+
type Target = AttrItem;
2146+
fn deref(&self) -> &Self::Target { &self.item }
2147+
}
2148+
21392149
/// `TraitRef`s appear in impls.
21402150
///
21412151
/// Resolution maps each `TraitRef`'s `ref_id` to its defining trait; that's all

‎src/libsyntax/attr/mod.rs

+21-17
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub use StabilityLevel::*;
99
pub use crate::ast::Attribute;
1010

1111
use crate::ast;
12-
use crate::ast::{AttrId, AttrStyle, Name, Ident, Path, PathSegment};
12+
use crate::ast::{AttrItem, AttrId, AttrStyle, Name, Ident, Path, PathSegment};
1313
use crate::ast::{MetaItem, MetaItemKind, NestedMetaItem};
1414
use crate::ast::{Lit, LitKind, Expr, Item, Local, Stmt, StmtKind, GenericParam};
1515
use crate::mut_visit::visit_clobber;
@@ -254,9 +254,8 @@ impl MetaItem {
254254
}
255255
}
256256

257-
impl Attribute {
258-
/// Extracts the MetaItem from inside this Attribute.
259-
pub fn meta(&self) -> Option<MetaItem> {
257+
impl AttrItem {
258+
crate fn meta(&self, span: Span) -> Option<MetaItem> {
260259
let mut tokens = self.tokens.trees().peekable();
261260
Some(MetaItem {
262261
path: self.path.clone(),
@@ -268,9 +267,16 @@ impl Attribute {
268267
} else {
269268
return None;
270269
},
271-
span: self.span,
270+
span,
272271
})
273272
}
273+
}
274+
275+
impl Attribute {
276+
/// Extracts the MetaItem from inside this Attribute.
277+
pub fn meta(&self) -> Option<MetaItem> {
278+
self.item.meta(self.span)
279+
}
274280

275281
pub fn parse<'a, T, F>(&self, sess: &'a ParseSess, mut f: F) -> PResult<'a, T>
276282
where F: FnMut(&mut Parser<'a>) -> PResult<'a, T>,
@@ -332,10 +338,9 @@ impl Attribute {
332338
DUMMY_SP,
333339
);
334340
f(&Attribute {
341+
item: AttrItem { path: meta.path, tokens: meta.node.tokens(meta.span) },
335342
id: self.id,
336343
style: self.style,
337-
path: meta.path,
338-
tokens: meta.node.tokens(meta.span),
339344
is_sugared_doc: true,
340345
span: self.span,
341346
})
@@ -384,10 +389,9 @@ crate fn mk_attr_id() -> AttrId {
384389
/// Returns an inner attribute with the given value and span.
385390
pub fn mk_attr_inner(item: MetaItem) -> Attribute {
386391
Attribute {
392+
item: AttrItem { path: item.path, tokens: item.node.tokens(item.span) },
387393
id: mk_attr_id(),
388394
style: ast::AttrStyle::Inner,
389-
path: item.path,
390-
tokens: item.node.tokens(item.span),
391395
is_sugared_doc: false,
392396
span: item.span,
393397
}
@@ -396,10 +400,9 @@ pub fn mk_attr_inner(item: MetaItem) -> Attribute {
396400
/// Returns an outer attribute with the given value and span.
397401
pub fn mk_attr_outer(item: MetaItem) -> Attribute {
398402
Attribute {
403+
item: AttrItem { path: item.path, tokens: item.node.tokens(item.span) },
399404
id: mk_attr_id(),
400405
style: ast::AttrStyle::Outer,
401-
path: item.path,
402-
tokens: item.node.tokens(item.span),
403406
is_sugared_doc: false,
404407
span: item.span,
405408
}
@@ -410,10 +413,12 @@ pub fn mk_sugared_doc_attr(text: Symbol, span: Span) -> Attribute {
410413
let lit_kind = LitKind::Str(text, ast::StrStyle::Cooked);
411414
let lit = Lit::from_lit_kind(lit_kind, span);
412415
Attribute {
416+
item: AttrItem {
417+
path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)),
418+
tokens: MetaItemKind::NameValue(lit).tokens(span),
419+
},
413420
id: mk_attr_id(),
414421
style,
415-
path: Path::from_ident(Ident::with_dummy_span(sym::doc).with_span_pos(span)),
416-
tokens: MetaItemKind::NameValue(lit).tokens(span),
417422
is_sugared_doc: true,
418423
span,
419424
}
@@ -502,7 +507,7 @@ impl MetaItem {
502507
}
503508
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
504509
token::Nonterminal::NtIdent(ident, _) => Path::from_ident(ident),
505-
token::Nonterminal::NtMeta(ref meta) => return Some(meta.clone()),
510+
token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
506511
token::Nonterminal::NtPath(ref path) => path.clone(),
507512
_ => return None,
508513
},
@@ -726,7 +731,7 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
726731
);
727732

728733
let start_span = parser.token.span;
729-
let (path, tokens) = panictry!(parser.parse_meta_item_unrestricted());
734+
let item = panictry!(parser.parse_attr_item());
730735
let end_span = parser.token.span;
731736
if parser.token != token::Eof {
732737
parse_sess.span_diagnostic
@@ -735,10 +740,9 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
735740
}
736741

737742
krate.attrs.push(Attribute {
743+
item,
738744
id: mk_attr_id(),
739745
style: AttrStyle::Inner,
740-
path,
741-
tokens,
742746
is_sugared_doc: false,
743747
span: start_span.to(end_span),
744748
});

‎src/libsyntax/config.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ impl<'a> StripUnconfigured<'a> {
122122

123123
while !parser.check(&token::CloseDelim(token::Paren)) {
124124
let lo = parser.token.span.lo();
125-
let (path, tokens) = parser.parse_meta_item_unrestricted()?;
126-
expanded_attrs.push((path, tokens, parser.prev_span.with_lo(lo)));
125+
let item = parser.parse_attr_item()?;
126+
expanded_attrs.push((item, parser.prev_span.with_lo(lo)));
127127
parser.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Paren)])?;
128128
}
129129

@@ -150,11 +150,10 @@ impl<'a> StripUnconfigured<'a> {
150150
// `cfg_attr` inside of another `cfg_attr`. E.g.
151151
// `#[cfg_attr(false, cfg_attr(true, some_attr))]`.
152152
expanded_attrs.into_iter()
153-
.flat_map(|(path, tokens, span)| self.process_cfg_attr(ast::Attribute {
153+
.flat_map(|(item, span)| self.process_cfg_attr(ast::Attribute {
154+
item,
154155
id: attr::mk_attr_id(),
155156
style: attr.style,
156-
path,
157-
tokens,
158157
is_sugared_doc: false,
159158
span,
160159
}))

‎src/libsyntax/ext/expand.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::ast::{self, Block, Ident, LitKind, NodeId, PatKind, Path};
1+
use crate::ast::{self, AttrItem, Block, Ident, LitKind, NodeId, PatKind, Path};
22
use crate::ast::{MacStmtStyle, StmtKind, ItemKind};
33
use crate::attr::{self, HasAttrs};
44
use crate::source_map::respan;
@@ -526,9 +526,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
526526
Annotatable::Stmt(stmt) => token::NtStmt(stmt.into_inner()),
527527
Annotatable::Expr(expr) => token::NtExpr(expr),
528528
})), DUMMY_SP).into();
529-
let input = self.extract_proc_macro_attr_input(attr.tokens, span);
529+
let input = self.extract_proc_macro_attr_input(attr.item.tokens, span);
530530
let tok_result = expander.expand(self.cx, span, input, item_tok);
531-
let res = self.parse_ast_fragment(tok_result, fragment_kind, &attr.path, span);
531+
let res =
532+
self.parse_ast_fragment(tok_result, fragment_kind, &attr.item.path, span);
532533
self.gate_proc_macro_expansion(span, &res);
533534
res
534535
}
@@ -1327,11 +1328,10 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13271328

13281329
let meta = attr::mk_list_item(Ident::with_dummy_span(sym::doc), items);
13291330
*at = attr::Attribute {
1331+
item: AttrItem { path: meta.path, tokens: meta.node.tokens(meta.span) },
13301332
span: at.span,
13311333
id: at.id,
13321334
style: at.style,
1333-
path: meta.path,
1334-
tokens: meta.node.tokens(meta.span),
13351335
is_sugared_doc: false,
13361336
};
13371337
} else {

‎src/libsyntax/ext/tt/macro_parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -936,7 +936,7 @@ fn parse_nt(p: &mut Parser<'_>, sp: Span, name: Symbol) -> Nonterminal {
936936
FatalError.raise()
937937
}
938938
sym::path => token::NtPath(panictry!(p.parse_path(PathStyle::Type))),
939-
sym::meta => token::NtMeta(panictry!(p.parse_meta_item())),
939+
sym::meta => token::NtMeta(panictry!(p.parse_attr_item())),
940940
sym::vis => token::NtVis(panictry!(p.parse_visibility(true))),
941941
sym::lifetime => if p.check_lifetime() {
942942
token::NtLifetime(p.expect_lifetime().ident)

‎src/libsyntax/mut_visit.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,8 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
527527
}
528528

529529
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
530-
let Attribute { id: _, style: _, path, tokens, is_sugared_doc: _, span } = attr;
530+
let Attribute { item: AttrItem { path, tokens }, id: _, style: _, is_sugared_doc: _, span }
531+
= attr;
531532
vis.visit_path(path);
532533
vis.visit_tts(tokens);
533534
vis.visit_span(span);
@@ -656,7 +657,10 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
656657
token::NtIdent(ident, _is_raw) => vis.visit_ident(ident),
657658
token::NtLifetime(ident) => vis.visit_ident(ident),
658659
token::NtLiteral(expr) => vis.visit_expr(expr),
659-
token::NtMeta(meta) => vis.visit_meta_item(meta),
660+
token::NtMeta(AttrItem { path, tokens }) => {
661+
vis.visit_path(path);
662+
vis.visit_tts(tokens);
663+
}
660664
token::NtPath(path) => vis.visit_path(path),
661665
token::NtTT(tt) => vis.visit_tt(tt),
662666
token::NtImplItem(item) =>

‎src/libsyntax/parse/attr.rs

+18-14
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ impl<'a> Parser<'a> {
9898
debug!("parse_attribute_with_inner_parse_policy: inner_parse_policy={:?} self.token={:?}",
9999
inner_parse_policy,
100100
self.token);
101-
let (span, path, tokens, style) = match self.token.kind {
101+
let (span, item, style) = match self.token.kind {
102102
token::Pound => {
103103
let lo = self.token.span;
104104
self.bump();
@@ -115,7 +115,7 @@ impl<'a> Parser<'a> {
115115
};
116116

117117
self.expect(&token::OpenDelim(token::Bracket))?;
118-
let (path, tokens) = self.parse_meta_item_unrestricted()?;
118+
let item = self.parse_attr_item()?;
119119
self.expect(&token::CloseDelim(token::Bracket))?;
120120
let hi = self.prev_span;
121121

@@ -150,7 +150,7 @@ impl<'a> Parser<'a> {
150150
}
151151
}
152152

153-
(attr_sp, path, tokens, style)
153+
(attr_sp, item, style)
154154
}
155155
_ => {
156156
let token_str = self.this_token_to_string();
@@ -159,10 +159,9 @@ impl<'a> Parser<'a> {
159159
};
160160

161161
Ok(ast::Attribute {
162+
item,
162163
id: attr::mk_attr_id(),
163164
style,
164-
path,
165-
tokens,
166165
is_sugared_doc: false,
167166
span,
168167
})
@@ -177,17 +176,17 @@ impl<'a> Parser<'a> {
177176
/// PATH
178177
/// PATH `=` TOKEN_TREE
179178
/// The delimiters or `=` are still put into the resulting token stream.
180-
crate fn parse_meta_item_unrestricted(&mut self) -> PResult<'a, (ast::Path, TokenStream)> {
181-
let meta = match self.token.kind {
179+
crate fn parse_attr_item(&mut self) -> PResult<'a, ast::AttrItem> {
180+
let item = match self.token.kind {
182181
token::Interpolated(ref nt) => match **nt {
183-
Nonterminal::NtMeta(ref meta) => Some(meta.clone()),
182+
Nonterminal::NtMeta(ref item) => Some(item.clone()),
184183
_ => None,
185184
},
186185
_ => None,
187186
};
188-
Ok(if let Some(meta) = meta {
187+
Ok(if let Some(item) = item {
189188
self.bump();
190-
(meta.path, meta.node.tokens(meta.span))
189+
item
191190
} else {
192191
let path = self.parse_path(PathStyle::Mod)?;
193192
let tokens = if self.check(&token::OpenDelim(DelimToken::Paren)) ||
@@ -214,7 +213,7 @@ impl<'a> Parser<'a> {
214213
} else {
215214
TokenStream::empty()
216215
};
217-
(path, tokens)
216+
ast::AttrItem { path, tokens }
218217
})
219218
}
220219

@@ -282,9 +281,14 @@ impl<'a> Parser<'a> {
282281
_ => None,
283282
};
284283

285-
if let Some(meta) = nt_meta {
286-
self.bump();
287-
return Ok(meta);
284+
if let Some(item) = nt_meta {
285+
return match item.meta(item.path.span) {
286+
Some(meta) => {
287+
self.bump();
288+
Ok(meta)
289+
}
290+
None => self.unexpected(),
291+
}
288292
}
289293

290294
let lo = self.token.span;

‎src/libsyntax/parse/parser/path.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -114,9 +114,9 @@ impl<'a> Parser<'a> {
114114
pub fn parse_path_allowing_meta(&mut self, style: PathStyle) -> PResult<'a, Path> {
115115
let meta_ident = match self.token.kind {
116116
token::Interpolated(ref nt) => match **nt {
117-
token::NtMeta(ref meta) => match meta.node {
118-
ast::MetaItemKind::Word => Some(meta.path.clone()),
119-
_ => None,
117+
token::NtMeta(ref item) => match item.tokens.is_empty() {
118+
true => Some(item.path.clone()),
119+
false => None,
120120
},
121121
_ => None,
122122
},

‎src/libsyntax/parse/token.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -690,7 +690,7 @@ pub enum Nonterminal {
690690
NtLifetime(ast::Ident),
691691
NtLiteral(P<ast::Expr>),
692692
/// Stuff inside brackets for attributes
693-
NtMeta(ast::MetaItem),
693+
NtMeta(ast::AttrItem),
694694
NtPath(ast::Path),
695695
NtVis(ast::Visibility),
696696
NtTT(TokenTree),

‎src/libsyntax/print/pprust.rs

+22-18
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
306306
crate fn nonterminal_to_string(nt: &Nonterminal) -> String {
307307
match *nt {
308308
token::NtExpr(ref e) => expr_to_string(e),
309-
token::NtMeta(ref e) => meta_item_to_string(e),
309+
token::NtMeta(ref e) => attr_item_to_string(e),
310310
token::NtTy(ref e) => ty_to_string(e),
311311
token::NtPath(ref e) => path_to_string(e),
312312
token::NtItem(ref e) => item_to_string(e),
@@ -398,8 +398,8 @@ pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String {
398398
to_string(|s| s.print_meta_list_item(li))
399399
}
400400

401-
pub fn meta_item_to_string(mi: &ast::MetaItem) -> String {
402-
to_string(|s| s.print_meta_item(mi))
401+
fn attr_item_to_string(ai: &ast::AttrItem) -> String {
402+
to_string(|s| s.print_attr_item(ai, ai.path.span))
403403
}
404404

405405
pub fn attribute_to_string(attr: &ast::Attribute) -> String {
@@ -603,24 +603,28 @@ pub trait PrintState<'a>: std::ops::Deref<Target=pp::Printer> + std::ops::DerefM
603603
ast::AttrStyle::Inner => self.word("#!["),
604604
ast::AttrStyle::Outer => self.word("#["),
605605
}
606-
self.ibox(0);
607-
match attr.tokens.trees().next() {
608-
Some(TokenTree::Delimited(_, delim, tts)) => {
609-
self.print_mac_common(
610-
Some(MacHeader::Path(&attr.path)), false, None, delim, tts, true, attr.span
611-
);
612-
}
613-
tree => {
614-
self.print_path(&attr.path, false, 0);
615-
if tree.is_some() {
616-
self.space();
617-
self.print_tts(attr.tokens.clone(), true);
618-
}
606+
self.print_attr_item(&attr.item, attr.span);
607+
self.word("]");
608+
}
609+
}
610+
611+
fn print_attr_item(&mut self, item: &ast::AttrItem, span: Span) {
612+
self.ibox(0);
613+
match item.tokens.trees().next() {
614+
Some(TokenTree::Delimited(_, delim, tts)) => {
615+
self.print_mac_common(
616+
Some(MacHeader::Path(&item.path)), false, None, delim, tts, true, span
617+
);
618+
}
619+
tree => {
620+
self.print_path(&item.path, false, 0);
621+
if tree.is_some() {
622+
self.space();
623+
self.print_tts(item.tokens.clone(), true);
619624
}
620625
}
621-
self.end();
622-
self.word("]");
623626
}
627+
self.end();
624628
}
625629

626630
fn print_meta_list_item(&mut self, item: &ast::NestedMetaItem) {

‎src/test/ui/cfg/cfg_stmt_expr.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ fn main() {
5757
// check that macro expanded code works
5858

5959
macro_rules! if_cfg {
60-
($cfg:meta $ib:block else $eb:block) => {
60+
($cfg:meta? $ib:block else $eb:block) => {
6161
{
6262
let r;
6363
#[cfg($cfg)]
@@ -69,7 +69,7 @@ fn main() {
6969
}
7070
}
7171

72-
let n = if_cfg!(unset {
72+
let n = if_cfg!(unset? {
7373
413
7474
} else {
7575
612

‎src/test/ui/macros/macro-first-set.rs

-6
Original file line numberDiff line numberDiff line change
@@ -252,12 +252,6 @@ test_path!(::std);
252252
test_path!(std::u8,);
253253
test_path!(any, super, super::super::self::path, X<Y>::Z<'a, T=U>);
254254

255-
macro_rules! test_meta_block {
256-
($($m:meta)* $b:block) => {};
257-
}
258-
259-
test_meta_block!(windows {});
260-
261255
macro_rules! test_lifetime {
262256
(1. $($l:lifetime)* $($b:block)*) => {};
263257
(2. $($b:block)* $($l:lifetime)*) => {};

0 commit comments

Comments
 (0)
Please sign in to comment.