about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorAlex Crichton <alex@alexcrichton.com>2018-05-22 08:01:21 -0700
committerAlex Crichton <alex@alexcrichton.com>2018-05-22 11:56:41 -0700
commita137d00ce52e9db78bb803d1384fdf3a4c4e63ea (patch)
treef262aeefdcdae7d68afcc9eb797e579b7aed7dbd /src/libsyntax
parentff8fa5cc69db5567b32ceca1ee4ac0dcfa3a81bc (diff)
downloadrust-a137d00ce52e9db78bb803d1384fdf3a4c4e63ea.tar.gz
rust-a137d00ce52e9db78bb803d1384fdf3a4c4e63ea.zip
rustc: Correctly pretty-print macro delimiters
This commit updates the `Mac_` AST structure to keep track of the delimiters
that it originally had for its invocation. This allows us to faithfully
pretty-print macro invocations not using parentheses (e.g. `vec![...]`). This in
turn helps procedural macros due to #43081.

Closes #50840
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast.rs8
-rw-r--r--src/libsyntax/ext/placeholders.rs1
-rw-r--r--src/libsyntax/fold.rs1
-rw-r--r--src/libsyntax/parse/parser.rs66
-rw-r--r--src/libsyntax/print/pprust.rs104
5 files changed, 98 insertions, 82 deletions
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 0ce9763ded8..8991398ae44 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1239,9 +1239,17 @@ pub type Mac = Spanned<Mac_>;
 #[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()
diff --git a/src/libsyntax/ext/placeholders.rs b/src/libsyntax/ext/placeholders.rs
index 9f60882ca29..5c1c661fffd 100644
--- a/src/libsyntax/ext/placeholders.rs
+++ b/src/libsyntax/ext/placeholders.rs
@@ -27,6 +27,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
         dummy_spanned(ast::Mac_ {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
             tts: TokenStream::empty().into(),
+            delim: ast::MacDelimiter::Brace,
         })
     }
 
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 28fb95f165f..190fef2a997 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -520,6 +520,7 @@ pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
         node: Mac_ {
             tts: fld.fold_tts(node.stream()).into(),
             path: fld.fold_path(node.path),
+            delim: node.delim,
         },
         span: fld.new_span(span)
     }
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 729ad491fd5..7cfb34fab84 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -26,7 +26,7 @@ use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
 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};
@@ -1611,8 +1611,9 @@ impl<'a> Parser<'a> {
             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`
@@ -2181,19 +2182,27 @@ impl<'a> Parser<'a> {
         })
     }
 
-    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,
@@ -2406,9 +2415,10 @@ impl<'a> Parser<'a> {
                     // `!`, 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
@@ -3881,8 +3891,8 @@ impl<'a> Parser<'a> {
                     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 => {
@@ -4275,7 +4285,7 @@ impl<'a> Parser<'a> {
 
                 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";
@@ -4360,8 +4370,8 @@ impl<'a> Parser<'a> {
             // 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.
@@ -4377,20 +4387,20 @@ impl<'a> Parser<'a> {
                     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())))
                 }
@@ -4438,7 +4448,7 @@ impl<'a> Parser<'a> {
                     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)
                     }),
@@ -6871,7 +6881,7 @@ impl<'a> Parser<'a> {
             };
             // 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 \
@@ -6881,7 +6891,7 @@ impl<'a> Parser<'a> {
             }
 
             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));
         }
@@ -6925,11 +6935,11 @@ impl<'a> Parser<'a> {
 
             // 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)
         }
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index be3408ce565..585d49d7076 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -13,7 +13,7 @@ pub use self::AnnNode::*;
 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};
@@ -422,7 +422,7 @@ pub fn arg_to_string(arg: &ast::Arg) -> String {
 }
 
 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 {
@@ -1098,7 +1098,7 @@ impl<'a> State<'a> {
                 self.s.word("Self")?;
             }
             ast::TyKind::Mac(ref m) => {
-                self.print_mac(m, token::Paren)?;
+                self.print_mac(m)?;
             }
         }
         self.end()
@@ -1140,8 +1140,11 @@ impl<'a> State<'a> {
                 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(";")
+                }
             }
         }
     }
@@ -1394,16 +1397,24 @@ impl<'a> State<'a> {
                 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! ")?;
@@ -1609,16 +1620,12 @@ impl<'a> State<'a> {
                 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))
@@ -1643,16 +1650,12 @@ impl<'a> State<'a> {
             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))
@@ -1695,11 +1698,7 @@ impl<'a> State<'a> {
                 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(";")?;
                 }
@@ -1829,25 +1828,22 @@ impl<'a> State<'a> {
         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),
         }
     }
 
@@ -2333,7 +2329,7 @@ impl<'a> State<'a> {
 
                 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)?;
@@ -2660,7 +2656,7 @@ impl<'a> State<'a> {
                 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))
     }