Skip to content

Commit

Permalink
syntax: Accept meta matchers in macros
Browse files Browse the repository at this point in the history
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 rust-lang#13067
  • Loading branch information
alexcrichton committed Mar 28, 2014
1 parent cbfc0a5 commit c6bbb95
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 28 deletions.
6 changes: 3 additions & 3 deletions src/libstd/comm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ use sync::arc::UnsafeArc;
pub use comm::select::{Select, Handle};

macro_rules! test (
{ fn $name:ident() $b:block $($a:attr)*} => (
{ fn $name:ident() $b:block $(#[$a:meta])*} => (
mod $name {
#[allow(unused_imports)];

Expand All @@ -265,8 +265,8 @@ macro_rules! test (

fn f() $b

$($a)* #[test] fn uv() { f() }
$($a)* #[test] fn native() {
$(#[$a])* #[test] fn uv() { f() }
$(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
native::task::spawn(proc() { tx.send(f()) });
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/io/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use std::io::net::ip::*;
use sync::atomics::{AtomicUint, INIT_ATOMIC_UINT, Relaxed};

macro_rules! iotest (
{ fn $name:ident() $b:block $($a:attr)* } => (
{ fn $name:ident() $b:block $(#[$a:meta])* } => (
mod $name {
#[allow(unused_imports)];

Expand All @@ -43,8 +43,8 @@ macro_rules! iotest (

fn f() $b

$($a)* #[test] fn green() { f() }
$($a)* #[test] fn native() {
$(#[$a])* #[test] fn green() { f() }
$(#[$a])* #[test] fn native() {
use native;
let (tx, rx) = channel();
native::task::spawn(proc() { tx.send(f()) });
Expand Down
2 changes: 1 addition & 1 deletion src/libsyntax/ext/tt/macro_parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ pub fn parse_nt(p: &mut Parser, name: &str) -> Nonterminal {
"path" => {
token::NtPath(~p.parse_path(LifetimeAndTypesWithoutColons).path)
}
"attr" => token::NtAttr(@p.parse_attribute(false)),
"meta" => token::NtMeta(p.parse_meta_item()),
"tt" => {
p.quote_depth += 1u; //but in theory, non-quoted tts might be useful
let res = token::NtTT(@p.parse_token_tree());
Expand Down
19 changes: 8 additions & 11 deletions src/libsyntax/parse/attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@ impl<'a> ParserAttr for Parser<'a> {
debug!("parse_outer_attributes: self.token={:?}",
self.token);
match self.token {
token::INTERPOLATED(token::NtAttr(..)) => {
attrs.push(self.parse_attribute(false));
}
token::POUND => {
attrs.push(self.parse_attribute(false));
}
Expand Down Expand Up @@ -66,11 +63,6 @@ impl<'a> ParserAttr for Parser<'a> {
debug!("parse_attributes: permit_inner={:?} self.token={:?}",
permit_inner, self.token);
let (span, value, mut style) = match self.token {
INTERPOLATED(token::NtAttr(attr)) => {
assert!(attr.node.style == ast::AttrOuter);
self.bump();
(attr.span, attr.node.value, ast::AttrOuter)
}
token::POUND => {
let lo = self.span.lo;
self.bump();
Expand Down Expand Up @@ -133,9 +125,6 @@ impl<'a> ParserAttr for Parser<'a> {
let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new();
loop {
let attr = match self.token {
token::INTERPOLATED(token::NtAttr(..)) => {
self.parse_attribute(true)
}
token::POUND => {
self.parse_attribute(true)
}
Expand Down Expand Up @@ -163,6 +152,14 @@ impl<'a> ParserAttr for Parser<'a> {
// | IDENT = lit
// | IDENT meta_seq
fn parse_meta_item(&mut self) -> @ast::MetaItem {
match self.token {
token::INTERPOLATED(token::NtMeta(e)) => {
self.bump();
return e
}
_ => {}
}

let lo = self.span.lo;
let ident = self.parse_ident();
let name = self.id_to_interned_str(ident);
Expand Down
8 changes: 4 additions & 4 deletions src/libsyntax/parse/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ pub enum Nonterminal {
NtExpr(@ast::Expr),
NtTy( P<ast::Ty>),
NtIdent(~ast::Ident, bool),
NtAttr(@ast::Attribute), // #[foo]
NtMeta(@ast::MetaItem), // stuff inside brackets for attributes
NtPath(~ast::Path),
NtTT( @ast::TokenTree), // needs @ed to break a circularity
NtMatchers(Vec<ast::Matcher> )
Expand All @@ -129,7 +129,7 @@ impl fmt::Show for Nonterminal {
NtExpr(..) => f.pad("NtExpr(..)"),
NtTy(..) => f.pad("NtTy(..)"),
NtIdent(..) => f.pad("NtIdent(..)"),
NtAttr(..) => f.pad("NtAttr(..)"),
NtMeta(..) => f.pad("NtMeta(..)"),
NtPath(..) => f.pad("NtPath(..)"),
NtTT(..) => f.pad("NtTT(..)"),
NtMatchers(..) => f.pad("NtMatchers(..)"),
Expand Down Expand Up @@ -241,15 +241,15 @@ pub fn to_str(t: &Token) -> ~str {
INTERPOLATED(ref nt) => {
match nt {
&NtExpr(e) => ::print::pprust::expr_to_str(e),
&NtAttr(e) => ::print::pprust::attribute_to_str(e),
&NtMeta(e) => ::print::pprust::meta_item_to_str(e),
_ => {
~"an interpolated " +
match *nt {
NtItem(..) => ~"item",
NtBlock(..) => ~"block",
NtStmt(..) => ~"statement",
NtPat(..) => ~"pattern",
NtAttr(..) => fail!("should have been handled"),
NtMeta(..) => fail!("should have been handled"),
NtExpr(..) => fail!("should have been handled above"),
NtTy(..) => ~"type",
NtIdent(..) => ~"identifier",
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/macro-inner-attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#[feature(macro_rules)];

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

test!(a,
#[cfg(qux)],
Expand Down
4 changes: 2 additions & 2 deletions src/test/compile-fail/macro-outer-attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@
#[feature(macro_rules)];

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

test!(a,
#[cfg(qux)],
Expand Down
4 changes: 2 additions & 2 deletions src/test/run-pass/macro-attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
#[feature(macro_rules)];

macro_rules! compiles_fine {
($at:attr) => {
(#[$at:meta]) => {
// test that the different types of attributes work
#[attribute]
/// Documentation!
$at
#[$at]

// check that the attributes are recognised by requiring this
// to be removed to avoid a compile error
Expand Down
43 changes: 43 additions & 0 deletions src/test/run-pass/macro-meta-items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-pretty - token trees can't pretty print
// compile-flags: --cfg foo

#[feature(macro_rules)];

macro_rules! compiles_fine {
($at:meta) => {
#[cfg($at)]
static MISTYPED: () = "foo";
}
}
macro_rules! emit {
($at:meta) => {
#[cfg($at)]
static MISTYPED: &'static str = "foo";
}
}

// item
compiles_fine!(bar)
emit!(foo)

fn foo() {
println!("{}", MISTYPED);
}

pub fn main() {
// statement
compiles_fine!(baz);
emit!(baz);
println!("{}", MISTYPED);
}

0 comments on commit c6bbb95

Please sign in to comment.