Skip to content

Commit c6bbb95

Browse files
committed
syntax: Accept meta matchers in macros
This removes the `attr` matcher and adds a `meta` matcher. The previous `attr` matcher is now ambiguous because it doesn't disambiguate whether it means inner attribute or outer attribute. The new behavior can still be achieved by taking an argument of the form `#[$foo:meta]` (the brackets are part of the macro pattern). Closes #13067
1 parent cbfc0a5 commit c6bbb95

File tree

9 files changed

+68
-28
lines changed

9 files changed

+68
-28
lines changed

src/libstd/comm/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ use sync::arc::UnsafeArc;
252252
pub use comm::select::{Select, Handle};
253253

254254
macro_rules! test (
255-
{ fn $name:ident() $b:block $($a:attr)*} => (
255+
{ fn $name:ident() $b:block $(#[$a:meta])*} => (
256256
mod $name {
257257
#[allow(unused_imports)];
258258

@@ -265,8 +265,8 @@ macro_rules! test (
265265

266266
fn f() $b
267267

268-
$($a)* #[test] fn uv() { f() }
269-
$($a)* #[test] fn native() {
268+
$(#[$a])* #[test] fn uv() { f() }
269+
$(#[$a])* #[test] fn native() {
270270
use native;
271271
let (tx, rx) = channel();
272272
native::task::spawn(proc() { tx.send(f()) });

src/libstd/io/test.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use std::io::net::ip::*;
1919
use sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};
2020

2121
macro_rules! iotest (
22-
{ fn $name:ident() $b:block $($a:attr)* } => (
22+
{ fn $name:ident() $b:block $(#[$a:meta])* } => (
2323
mod $name {
2424
#[allow(unused_imports)];
2525

@@ -43,8 +43,8 @@ macro_rules! iotest (
4343

4444
fn f() $b
4545

46-
$($a)* #[test] fn green() { f() }
47-
$($a)* #[test] fn native() {
46+
$(#[$a])* #[test] fn green() { f() }
47+
$(#[$a])* #[test] fn native() {
4848
use native;
4949
let (tx, rx) = channel();
5050
native::task::spawn(proc() { tx.send(f()) });

src/libsyntax/ext/tt/macro_parser.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
441441
"path" => {
442442
token::NtPath(~p.parse_path(LifetimeAndTypesWithoutColons).path)
443443
}
444-
"attr" => token::NtAttr(@p.parse_attribute(false)),
444+
"meta" => token::NtMeta(p.parse_meta_item()),
445445
"tt" => {
446446
p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
447447
let res = token::NtTT(@p.parse_token_tree());

src/libsyntax/parse/attr.rs

+8-11
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,6 @@ impl<'a> ParserAttr for Parser<'a> {
3434
debug!("parse_outer_attributes: self.token={:?}",
3535
self.token);
3636
match self.token {
37-
token::INTERPOLATED(token::NtAttr(..)) => {
38-
attrs.push(self.parse_attribute(false));
39-
}
4037
token::POUND => {
4138
attrs.push(self.parse_attribute(false));
4239
}
@@ -66,11 +63,6 @@ impl<'a> ParserAttr for Parser<'a> {
6663
debug!("parse_attributes: permit_inner={:?} self.token={:?}",
6764
permit_inner, self.token);
6865
let (span, value, mut style) = match self.token {
69-
INTERPOLATED(token::NtAttr(attr)) => {
70-
assert!(attr.node.style == ast::AttrOuter);
71-
self.bump();
72-
(attr.span, attr.node.value, ast::AttrOuter)
73-
}
7466
token::POUND => {
7567
let lo = self.span.lo;
7668
self.bump();
@@ -133,9 +125,6 @@ impl<'a> ParserAttr for Parser<'a> {
133125
let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new();
134126
loop {
135127
let attr = match self.token {
136-
token::INTERPOLATED(token::NtAttr(..)) => {
137-
self.parse_attribute(true)
138-
}
139128
token::POUND => {
140129
self.parse_attribute(true)
141130
}
@@ -163,6 +152,14 @@ impl<'a> ParserAttr for Parser<'a> {
163152
// | IDENT = lit
164153
// | IDENT meta_seq
165154
fn parse_meta_item(&mut self) -> @ast::MetaItem {
155+
match self.token {
156+
token::INTERPOLATED(token::NtMeta(e)) => {
157+
self.bump();
158+
return e
159+
}
160+
_ => {}
161+
}
162+
166163
let lo = self.span.lo;
167164
let ident = self.parse_ident();
168165
let name = self.id_to_interned_str(ident);

src/libsyntax/parse/token.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ pub enum Nonterminal {
113113
NtExpr(@ast::Expr),
114114
NtTy( P<ast::Ty>),
115115
NtIdent(~ast::Ident, bool),
116-
NtAttr(@ast::Attribute), // #[foo]
116+
NtMeta(@ast::MetaItem), // stuff inside brackets for attributes
117117
NtPath(~ast::Path),
118118
NtTT( @ast::TokenTree), // needs @ed to break a circularity
119119
NtMatchers(Vec<ast::Matcher> )
@@ -129,7 +129,7 @@ impl fmt::Show for Nonterminal {
129129
NtExpr(..) => f.pad("NtExpr(..)"),
130130
NtTy(..) => f.pad("NtTy(..)"),
131131
NtIdent(..) => f.pad("NtIdent(..)"),
132-
NtAttr(..) => f.pad("NtAttr(..)"),
132+
NtMeta(..) => f.pad("NtMeta(..)"),
133133
NtPath(..) => f.pad("NtPath(..)"),
134134
NtTT(..) => f.pad("NtTT(..)"),
135135
NtMatchers(..) => f.pad("NtMatchers(..)"),
@@ -241,15 +241,15 @@ pub fn to_str(t: &Token) -> ~str {
241241
INTERPOLATED(ref nt) => {
242242
match nt {
243243
&NtExpr(e) => ::print::pprust::expr_to_str(e),
244-
&NtAttr(e) => ::print::pprust::attribute_to_str(e),
244+
&NtMeta(e) => ::print::pprust::meta_item_to_str(e),
245245
_ => {
246246
~"an interpolated " +
247247
match *nt {
248248
NtItem(..) => ~"item",
249249
NtBlock(..) => ~"block",
250250
NtStmt(..) => ~"statement",
251251
NtPat(..) => ~"pattern",
252-
NtAttr(..) => fail!("should have been handled"),
252+
NtMeta(..) => fail!("should have been handled"),
253253
NtExpr(..) => fail!("should have been handled above"),
254254
NtTy(..) => ~"type",
255255
NtIdent(..) => ~"identifier",

src/test/compile-fail/macro-inner-attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#[feature(macro_rules)];
1212

1313
macro_rules! test ( ($nm:ident,
14-
$a:attr,
15-
$i:item) => (mod $nm { $a; $i }); )
14+
#[$a:meta],
15+
$i:item) => (mod $nm { #![$a] $i }); )
1616

1717
test!(a,
1818
#[cfg(qux)],

src/test/compile-fail/macro-outer-attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@
1111
#[feature(macro_rules)];
1212

1313
macro_rules! test ( ($nm:ident,
14-
$a:attr,
15-
$i:item) => (mod $nm { $a $i }); )
14+
#[$a:meta],
15+
$i:item) => (mod $nm { #[$a] $i }); )
1616

1717
test!(a,
1818
#[cfg(qux)],

src/test/run-pass/macro-attributes.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@
1313
#[feature(macro_rules)];
1414

1515
macro_rules! compiles_fine {
16-
($at:attr) => {
16+
(#[$at:meta]) => {
1717
// test that the different types of attributes work
1818
#[attribute]
1919
/// Documentation!
20-
$at
20+
#[$at]
2121

2222
// check that the attributes are recognised by requiring this
2323
// to be removed to avoid a compile error

src/test/run-pass/macro-meta-items.rs

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// ignore-pretty - token trees can't pretty print
12+
// compile-flags: --cfg foo
13+
14+
#[feature(macro_rules)];
15+
16+
macro_rules! compiles_fine {
17+
($at:meta) => {
18+
#[cfg($at)]
19+
static MISTYPED: () = "foo";
20+
}
21+
}
22+
macro_rules! emit {
23+
($at:meta) => {
24+
#[cfg($at)]
25+
static MISTYPED: &'static str = "foo";
26+
}
27+
}
28+
29+
// item
30+
compiles_fine!(bar)
31+
emit!(foo)
32+
33+
fn foo() {
34+
println!("{}", MISTYPED);
35+
}
36+
37+
pub fn main() {
38+
// statement
39+
compiles_fine!(baz);
40+
emit!(baz);
41+
println!("{}", MISTYPED);
42+
}
43+

0 commit comments

Comments
 (0)