#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct Mac_ {
pub path: Path,
+ pub delim: MacDelimiter,
pub tts: ThinTokenStream,
}
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum MacDelimiter {
+ Parenthesis,
+ Bracket,
+ Brace,
+}
+
impl Mac_ {
pub fn stream(&self) -> TokenStream {
self.tts.clone().into()
dummy_spanned(ast::Mac_ {
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
tts: TokenStream::empty().into(),
+ delim: ast::MacDelimiter::Brace,
})
}
node: Mac_ {
tts: fld.fold_tts(node.stream()).into(),
path: fld.fold_path(node.path),
+ delim: node.delim,
},
span: fld.new_span(span)
}
use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind, UintTy};
use ast::Local;
use ast::MacStmtStyle;
-use ast::{Mac, Mac_};
+use ast::{Mac, Mac_, MacDelimiter};
use ast::{MutTy, Mutability};
use ast::{Pat, PatKind, PathSegment};
use ast::{PolyTraitRef, QSelf};
let path = self.parse_path(PathStyle::Type)?;
if self.eat(&token::Not) {
// Macro invocation in type position
- let (_, tts) = self.expect_delimited_token_tree()?;
- TyKind::Mac(respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts }))
+ let (delim, tts) = self.expect_delimited_token_tree()?;
+ let node = Mac_ { path, tts, delim };
+ TyKind::Mac(respan(lo.to(self.prev_span), node))
} else {
// Just a type path or bound list (trait object type) starting with a trait.
// `Type`
})
}
- fn expect_delimited_token_tree(&mut self) -> PResult<'a, (token::DelimToken, ThinTokenStream)> {
- match self.token {
- token::OpenDelim(delim) => match self.parse_token_tree() {
- TokenTree::Delimited(_, delimited) => Ok((delim, delimited.stream().into())),
- _ => unreachable!(),
- },
+ fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
+ let delim = match self.token {
+ token::OpenDelim(delim) => delim,
_ => {
let msg = "expected open delimiter";
let mut err = self.fatal(msg);
err.span_label(self.span, msg);
- Err(err)
+ return Err(err)
}
- }
+ };
+ let delimited = match self.parse_token_tree() {
+ TokenTree::Delimited(_, delimited) => delimited,
+ _ => unreachable!(),
+ };
+ let delim = match delim {
+ token::Paren => MacDelimiter::Parenthesis,
+ token::Bracket => MacDelimiter::Bracket,
+ token::Brace => MacDelimiter::Brace,
+ token::NoDelim => self.bug("unexpected no delimiter"),
+ };
+ Ok((delim, delimited.stream().into()))
}
/// At the bottom (top?) of the precedence hierarchy,
// `!`, as an operator, is prefix, so we know this isn't that
if self.eat(&token::Not) {
// MACRO INVOCATION expression
- let (_, tts) = self.expect_delimited_token_tree()?;
+ let (delim, tts) = self.expect_delimited_token_tree()?;
let hi = self.prev_span;
- return Ok(self.mk_mac_expr(lo.to(hi), Mac_ { path: pth, tts: tts }, attrs));
+ let node = Mac_ { path: pth, tts, delim };
+ return Ok(self.mk_mac_expr(lo.to(hi), node, attrs))
}
if self.check(&token::OpenDelim(token::Brace)) {
// This is a struct literal, unless we're prohibited
token::Not if qself.is_none() => {
// Parse macro invocation
self.bump();
- let (_, tts) = self.expect_delimited_token_tree()?;
- let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
+ let (delim, tts) = self.expect_delimited_token_tree()?;
+ let mac = respan(lo.to(self.prev_span), Mac_ { path, tts, delim });
pat = PatKind::Mac(mac);
}
token::DotDotDot | token::DotDotEq | token::DotDot => {
let ident = self.parse_ident()?;
let (delim, tokens) = self.expect_delimited_token_tree()?;
- if delim != token::Brace {
+ if delim != MacDelimiter::Brace {
if !self.eat(&token::Semi) {
let msg = "macros that expand to items must either \
be surrounded with braces or followed by a semicolon";
// check that we're pointing at delimiters (need to check
// again after the `if`, because of `parse_ident`
// consuming more tokens).
- let delim = match self.token {
- token::OpenDelim(delim) => delim,
+ match self.token {
+ token::OpenDelim(_) => {}
_ => {
// we only expect an ident if we didn't parse one
// above.
err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
return Err(err)
},
- };
+ }
- let (_, tts) = self.expect_delimited_token_tree()?;
+ let (delim, tts) = self.expect_delimited_token_tree()?;
let hi = self.prev_span;
- let style = if delim == token::Brace {
+ let style = if delim == MacDelimiter::Brace {
MacStmtStyle::Braces
} else {
MacStmtStyle::NoBraces
};
if id.name == keywords::Invalid.name() {
- let mac = respan(lo.to(hi), Mac_ { path: pth, tts: tts });
- let node = if delim == token::Brace ||
+ let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
+ let node = if delim == MacDelimiter::Brace ||
self.token == token::Semi || self.token == token::Eof {
StmtKind::Mac(P((mac, style, attrs.into())))
}
node: StmtKind::Item({
self.mk_item(
span, id /*id is good here*/,
- ItemKind::Mac(respan(span, Mac_ { path: pth, tts: tts })),
+ ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
respan(lo, VisibilityKind::Inherited),
attrs)
}),
};
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
- if delim != token::Brace {
+ if delim != MacDelimiter::Brace {
if !self.eat(&token::Semi) {
self.span_err(self.prev_span,
"macros that expand to items must either \
}
let hi = self.prev_span;
- let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts: tts });
+ let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
return Ok(Some(item));
}
// eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?;
- if delim != token::Brace {
+ if delim != MacDelimiter::Brace {
self.expect(&token::Semi)?
}
- Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts })))
+ Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))
} else {
Ok(None)
}
use rustc_target::spec::abi::{self, Abi};
use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
-use ast::Attribute;
+use ast::{Attribute, MacDelimiter};
use util::parser::{self, AssocOp, Fixity};
use attr;
use codemap::{self, CodeMap};
}
pub fn mac_to_string(arg: &ast::Mac) -> String {
- to_string(|s| s.print_mac(arg, ::parse::token::Paren))
+ to_string(|s| s.print_mac(arg))
}
pub fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
self.s.word("Self")?;
}
ast::TyKind::Mac(ref m) => {
- self.print_mac(m, token::Paren)?;
+ self.print_mac(m)?;
}
}
self.end()
self.end() // end the outer cbox
}
ast::ForeignItemKind::Macro(ref m) => {
- self.print_mac(m, token::Paren)?;
- self.s.word(";")
+ self.print_mac(m)?;
+ match m.node.delim {
+ MacDelimiter::Brace => Ok(()),
+ _ => self.s.word(";")
+ }
}
}
}
self.print_where_clause(&generics.where_clause)?;
self.s.word(";")?;
}
- ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
- self.print_path(&node.path, false, 0)?;
- self.s.word("! ")?;
- self.print_ident(item.ident)?;
- self.cbox(INDENT_UNIT)?;
- self.popen()?;
- self.print_tts(node.stream())?;
- self.pclose()?;
- self.s.word(";")?;
- self.end()?;
+ ast::ItemKind::Mac(ref mac) => {
+ if item.ident.name == keywords::Invalid.name() {
+ self.print_mac(mac)?;
+ match mac.node.delim {
+ MacDelimiter::Brace => {}
+ _ => self.s.word(";")?,
+ }
+ } else {
+ self.print_path(&mac.node.path, false, 0)?;
+ self.s.word("! ")?;
+ self.print_ident(item.ident)?;
+ self.cbox(INDENT_UNIT)?;
+ self.popen()?;
+ self.print_tts(mac.node.stream())?;
+ self.pclose()?;
+ self.s.word(";")?;
+ self.end()?;
+ }
}
ast::ItemKind::MacroDef(ref tts) => {
self.s.word("macro_rules! ")?;
self.print_associated_type(ti.ident, Some(bounds),
default.as_ref().map(|ty| &**ty))?;
}
- ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
- // code copied from ItemKind::Mac:
- self.print_path(&node.path, false, 0)?;
- self.s.word("! ")?;
- self.cbox(INDENT_UNIT)?;
- self.popen()?;
- self.print_tts(node.stream())?;
- self.pclose()?;
- self.s.word(";")?;
- self.end()?
+ ast::TraitItemKind::Macro(ref mac) => {
+ self.print_mac(mac)?;
+ match mac.node.delim {
+ MacDelimiter::Brace => {}
+ _ => self.s.word(";")?,
+ }
}
}
self.ann.post(self, NodeSubItem(ti.id))
ast::ImplItemKind::Type(ref ty) => {
self.print_associated_type(ii.ident, None, Some(ty))?;
}
- ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
- // code copied from ItemKind::Mac:
- self.print_path(&node.path, false, 0)?;
- self.s.word("! ")?;
- self.cbox(INDENT_UNIT)?;
- self.popen()?;
- self.print_tts(node.stream())?;
- self.pclose()?;
- self.s.word(";")?;
- self.end()?
+ ast::ImplItemKind::Macro(ref mac) => {
+ self.print_mac(mac)?;
+ match mac.node.delim {
+ MacDelimiter::Brace => {}
+ _ => self.s.word(";")?,
+ }
}
}
self.ann.post(self, NodeSubItem(ii.id))
let (ref mac, style, ref attrs) = **mac;
self.space_if_not_bol()?;
self.print_outer_attributes(attrs)?;
- let delim = match style {
- ast::MacStmtStyle::Braces => token::Brace,
- _ => token::Paren
- };
- self.print_mac(mac, delim)?;
+ self.print_mac(mac)?;
if style == ast::MacStmtStyle::Semicolon {
self.s.word(";")?;
}
self.print_else(elseopt)
}
- pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
- -> io::Result<()> {
+ pub fn print_mac(&mut self, m: &ast::Mac) -> io::Result<()> {
self.print_path(&m.node.path, false, 0)?;
self.s.word("!")?;
- match delim {
- token::Paren => self.popen()?,
- token::Bracket => self.s.word("[")?,
- token::Brace => {
+ match m.node.delim {
+ MacDelimiter::Parenthesis => self.popen()?,
+ MacDelimiter::Bracket => self.s.word("[")?,
+ MacDelimiter::Brace => {
self.head("")?;
self.bopen()?;
}
- token::NoDelim => {}
}
self.print_tts(m.node.stream())?;
- match delim {
- token::Paren => self.pclose(),
- token::Bracket => self.s.word("]"),
- token::Brace => self.bclose(m.span),
- token::NoDelim => Ok(()),
+ match m.node.delim {
+ MacDelimiter::Parenthesis => self.pclose(),
+ MacDelimiter::Bracket => self.s.word("]"),
+ MacDelimiter::Brace => self.bclose(m.span),
}
}
self.pclose()?;
}
- ast::ExprKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
+ ast::ExprKind::Mac(ref m) => self.print_mac(m)?,
ast::ExprKind::Paren(ref e) => {
self.popen()?;
self.print_inner_attributes_inline(attrs)?;
self.print_pat(inner)?;
self.pclose()?;
}
- PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
+ PatKind::Mac(ref m) => self.print_mac(m)?,
}
self.ann.post(self, NodePat(pat))
}
),
)).into()
},
+ delim: MacDelimiter::Parenthesis,
};
let if_expr = cx.expr_if(
sp,
--- /dev/null
+// Copyright 2018 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+use proc_macro::*;
+
+#[proc_macro_attribute]
+pub fn doit(_: TokenStream, input: TokenStream) -> TokenStream {
+ input.into_iter().collect()
+}
--- /dev/null
+// Copyright 2018 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.
+
+// aux-build:macro-brackets.rs
+
+#![feature(proc_macro)]
+
+extern crate macro_brackets as bar;
+use bar::doit;
+
+macro_rules! id {
+ ($($t:tt)*) => ($($t)*)
+}
+
+#[doit]
+id![static X: u32 = 'a';]; //~ ERROR: mismatched types
+
+
+fn main() {}
--- /dev/null
+error[E0308]: mismatched types
+ --> $DIR/macro-brackets.rs:23:21
+ |
+LL | id![static X: u32 = 'a';]; //~ ERROR: mismatched types
+ | ^^^ expected u32, found char
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.