Skip to content

Commit a137d00

Browse files
committed
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 rust-lang#43081. Closes rust-lang#50840
1 parent ff8fa5c commit a137d00

File tree

9 files changed

+156
-82
lines changed

9 files changed

+156
-82
lines changed

src/libsyntax/ast.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1239,9 +1239,17 @@ pub type Mac = Spanned<Mac_>;
12391239
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
12401240
pub struct Mac_ {
12411241
pub path: Path,
1242+
pub delim: MacDelimiter,
12421243
pub tts: ThinTokenStream,
12431244
}
12441245

1246+
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
1247+
pub enum MacDelimiter {
1248+
Parenthesis,
1249+
Bracket,
1250+
Brace,
1251+
}
1252+
12451253
impl Mac_ {
12461254
pub fn stream(&self) -> TokenStream {
12471255
self.tts.clone().into()

src/libsyntax/ext/placeholders.rs

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub fn placeholder(kind: ExpansionKind, id: ast::NodeId) -> Expansion {
2727
dummy_spanned(ast::Mac_ {
2828
path: ast::Path { span: DUMMY_SP, segments: Vec::new() },
2929
tts: TokenStream::empty().into(),
30+
delim: ast::MacDelimiter::Brace,
3031
})
3132
}
3233

src/libsyntax/fold.rs

+1
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,7 @@ pub fn noop_fold_mac<T: Folder>(Spanned {node, span}: Mac, fld: &mut T) -> Mac {
520520
node: Mac_ {
521521
tts: fld.fold_tts(node.stream()).into(),
522522
path: fld.fold_path(node.path),
523+
delim: node.delim,
523524
},
524525
span: fld.new_span(span)
525526
}

src/libsyntax/parse/parser.rs

+38-28
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use ast::{Ident, ImplItem, IsAuto, Item, ItemKind};
2626
use ast::{Label, Lifetime, LifetimeDef, Lit, LitKind, UintTy};
2727
use ast::Local;
2828
use ast::MacStmtStyle;
29-
use ast::{Mac, Mac_};
29+
use ast::{Mac, Mac_, MacDelimiter};
3030
use ast::{MutTy, Mutability};
3131
use ast::{Pat, PatKind, PathSegment};
3232
use ast::{PolyTraitRef, QSelf};
@@ -1611,8 +1611,9 @@ impl<'a> Parser<'a> {
16111611
let path = self.parse_path(PathStyle::Type)?;
16121612
if self.eat(&token::Not) {
16131613
// Macro invocation in type position
1614-
let (_, tts) = self.expect_delimited_token_tree()?;
1615-
TyKind::Mac(respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts }))
1614+
let (delim, tts) = self.expect_delimited_token_tree()?;
1615+
let node = Mac_ { path, tts, delim };
1616+
TyKind::Mac(respan(lo.to(self.prev_span), node))
16161617
} else {
16171618
// Just a type path or bound list (trait object type) starting with a trait.
16181619
// `Type`
@@ -2181,19 +2182,27 @@ impl<'a> Parser<'a> {
21812182
})
21822183
}
21832184

2184-
fn expect_delimited_token_tree(&mut self) -> PResult<'a, (token::DelimToken, ThinTokenStream)> {
2185-
match self.token {
2186-
token::OpenDelim(delim) => match self.parse_token_tree() {
2187-
TokenTree::Delimited(_, delimited) => Ok((delim, delimited.stream().into())),
2188-
_ => unreachable!(),
2189-
},
2185+
fn expect_delimited_token_tree(&mut self) -> PResult<'a, (MacDelimiter, ThinTokenStream)> {
2186+
let delim = match self.token {
2187+
token::OpenDelim(delim) => delim,
21902188
_ => {
21912189
let msg = "expected open delimiter";
21922190
let mut err = self.fatal(msg);
21932191
err.span_label(self.span, msg);
2194-
Err(err)
2192+
return Err(err)
21952193
}
2196-
}
2194+
};
2195+
let delimited = match self.parse_token_tree() {
2196+
TokenTree::Delimited(_, delimited) => delimited,
2197+
_ => unreachable!(),
2198+
};
2199+
let delim = match delim {
2200+
token::Paren => MacDelimiter::Parenthesis,
2201+
token::Bracket => MacDelimiter::Bracket,
2202+
token::Brace => MacDelimiter::Brace,
2203+
token::NoDelim => self.bug("unexpected no delimiter"),
2204+
};
2205+
Ok((delim, delimited.stream().into()))
21972206
}
21982207

21992208
/// At the bottom (top?) of the precedence hierarchy,
@@ -2406,9 +2415,10 @@ impl<'a> Parser<'a> {
24062415
// `!`, as an operator, is prefix, so we know this isn't that
24072416
if self.eat(&token::Not) {
24082417
// MACRO INVOCATION expression
2409-
let (_, tts) = self.expect_delimited_token_tree()?;
2418+
let (delim, tts) = self.expect_delimited_token_tree()?;
24102419
let hi = self.prev_span;
2411-
return Ok(self.mk_mac_expr(lo.to(hi), Mac_ { path: pth, tts: tts }, attrs));
2420+
let node = Mac_ { path: pth, tts, delim };
2421+
return Ok(self.mk_mac_expr(lo.to(hi), node, attrs))
24122422
}
24132423
if self.check(&token::OpenDelim(token::Brace)) {
24142424
// This is a struct literal, unless we're prohibited
@@ -3881,8 +3891,8 @@ impl<'a> Parser<'a> {
38813891
token::Not if qself.is_none() => {
38823892
// Parse macro invocation
38833893
self.bump();
3884-
let (_, tts) = self.expect_delimited_token_tree()?;
3885-
let mac = respan(lo.to(self.prev_span), Mac_ { path: path, tts: tts });
3894+
let (delim, tts) = self.expect_delimited_token_tree()?;
3895+
let mac = respan(lo.to(self.prev_span), Mac_ { path, tts, delim });
38863896
pat = PatKind::Mac(mac);
38873897
}
38883898
token::DotDotDot | token::DotDotEq | token::DotDot => {
@@ -4275,7 +4285,7 @@ impl<'a> Parser<'a> {
42754285

42764286
let ident = self.parse_ident()?;
42774287
let (delim, tokens) = self.expect_delimited_token_tree()?;
4278-
if delim != token::Brace {
4288+
if delim != MacDelimiter::Brace {
42794289
if !self.eat(&token::Semi) {
42804290
let msg = "macros that expand to items must either \
42814291
be surrounded with braces or followed by a semicolon";
@@ -4360,8 +4370,8 @@ impl<'a> Parser<'a> {
43604370
// check that we're pointing at delimiters (need to check
43614371
// again after the `if`, because of `parse_ident`
43624372
// consuming more tokens).
4363-
let delim = match self.token {
4364-
token::OpenDelim(delim) => delim,
4373+
match self.token {
4374+
token::OpenDelim(_) => {}
43654375
_ => {
43664376
// we only expect an ident if we didn't parse one
43674377
// above.
@@ -4377,20 +4387,20 @@ impl<'a> Parser<'a> {
43774387
err.span_label(self.span, format!("expected {}`(` or `{{`", ident_str));
43784388
return Err(err)
43794389
},
4380-
};
4390+
}
43814391

4382-
let (_, tts) = self.expect_delimited_token_tree()?;
4392+
let (delim, tts) = self.expect_delimited_token_tree()?;
43834393
let hi = self.prev_span;
43844394

4385-
let style = if delim == token::Brace {
4395+
let style = if delim == MacDelimiter::Brace {
43864396
MacStmtStyle::Braces
43874397
} else {
43884398
MacStmtStyle::NoBraces
43894399
};
43904400

43914401
if id.name == keywords::Invalid.name() {
4392-
let mac = respan(lo.to(hi), Mac_ { path: pth, tts: tts });
4393-
let node = if delim == token::Brace ||
4402+
let mac = respan(lo.to(hi), Mac_ { path: pth, tts, delim });
4403+
let node = if delim == MacDelimiter::Brace ||
43944404
self.token == token::Semi || self.token == token::Eof {
43954405
StmtKind::Mac(P((mac, style, attrs.into())))
43964406
}
@@ -4438,7 +4448,7 @@ impl<'a> Parser<'a> {
44384448
node: StmtKind::Item({
44394449
self.mk_item(
44404450
span, id /*id is good here*/,
4441-
ItemKind::Mac(respan(span, Mac_ { path: pth, tts: tts })),
4451+
ItemKind::Mac(respan(span, Mac_ { path: pth, tts, delim })),
44424452
respan(lo, VisibilityKind::Inherited),
44434453
attrs)
44444454
}),
@@ -6871,7 +6881,7 @@ impl<'a> Parser<'a> {
68716881
};
68726882
// eat a matched-delimiter token tree:
68736883
let (delim, tts) = self.expect_delimited_token_tree()?;
6874-
if delim != token::Brace {
6884+
if delim != MacDelimiter::Brace {
68756885
if !self.eat(&token::Semi) {
68766886
self.span_err(self.prev_span,
68776887
"macros that expand to items must either \
@@ -6881,7 +6891,7 @@ impl<'a> Parser<'a> {
68816891
}
68826892

68836893
let hi = self.prev_span;
6884-
let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts: tts });
6894+
let mac = respan(mac_lo.to(hi), Mac_ { path: pth, tts, delim });
68856895
let item = self.mk_item(lo.to(hi), id, ItemKind::Mac(mac), visibility, attrs);
68866896
return Ok(Some(item));
68876897
}
@@ -6925,11 +6935,11 @@ impl<'a> Parser<'a> {
69256935

69266936
// eat a matched-delimiter token tree:
69276937
let (delim, tts) = self.expect_delimited_token_tree()?;
6928-
if delim != token::Brace {
6938+
if delim != MacDelimiter::Brace {
69296939
self.expect(&token::Semi)?
69306940
}
69316941

6932-
Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts: tts })))
6942+
Ok(Some(respan(lo.to(self.prev_span), Mac_ { path: pth, tts, delim })))
69336943
} else {
69346944
Ok(None)
69356945
}

src/libsyntax/print/pprust.rs

+50-54
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ pub use self::AnnNode::*;
1313
use rustc_target::spec::abi::{self, Abi};
1414
use ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
1515
use ast::{SelfKind, RegionTyParamBound, TraitTyParamBound, TraitBoundModifier};
16-
use ast::Attribute;
16+
use ast::{Attribute, MacDelimiter};
1717
use util::parser::{self, AssocOp, Fixity};
1818
use attr;
1919
use codemap::{self, CodeMap};
@@ -422,7 +422,7 @@ pub fn arg_to_string(arg: &ast::Arg) -> String {
422422
}
423423

424424
pub fn mac_to_string(arg: &ast::Mac) -> String {
425-
to_string(|s| s.print_mac(arg, ::parse::token::Paren))
425+
to_string(|s| s.print_mac(arg))
426426
}
427427

428428
pub fn foreign_item_to_string(arg: &ast::ForeignItem) -> String {
@@ -1098,7 +1098,7 @@ impl<'a> State<'a> {
10981098
self.s.word("Self")?;
10991099
}
11001100
ast::TyKind::Mac(ref m) => {
1101-
self.print_mac(m, token::Paren)?;
1101+
self.print_mac(m)?;
11021102
}
11031103
}
11041104
self.end()
@@ -1140,8 +1140,11 @@ impl<'a> State<'a> {
11401140
self.end() // end the outer cbox
11411141
}
11421142
ast::ForeignItemKind::Macro(ref m) => {
1143-
self.print_mac(m, token::Paren)?;
1144-
self.s.word(";")
1143+
self.print_mac(m)?;
1144+
match m.node.delim {
1145+
MacDelimiter::Brace => Ok(()),
1146+
_ => self.s.word(";")
1147+
}
11451148
}
11461149
}
11471150
}
@@ -1394,16 +1397,24 @@ impl<'a> State<'a> {
13941397
self.print_where_clause(&generics.where_clause)?;
13951398
self.s.word(";")?;
13961399
}
1397-
ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
1398-
self.print_path(&node.path, false, 0)?;
1399-
self.s.word("! ")?;
1400-
self.print_ident(item.ident)?;
1401-
self.cbox(INDENT_UNIT)?;
1402-
self.popen()?;
1403-
self.print_tts(node.stream())?;
1404-
self.pclose()?;
1405-
self.s.word(";")?;
1406-
self.end()?;
1400+
ast::ItemKind::Mac(ref mac) => {
1401+
if item.ident.name == keywords::Invalid.name() {
1402+
self.print_mac(mac)?;
1403+
match mac.node.delim {
1404+
MacDelimiter::Brace => {}
1405+
_ => self.s.word(";")?,
1406+
}
1407+
} else {
1408+
self.print_path(&mac.node.path, false, 0)?;
1409+
self.s.word("! ")?;
1410+
self.print_ident(item.ident)?;
1411+
self.cbox(INDENT_UNIT)?;
1412+
self.popen()?;
1413+
self.print_tts(mac.node.stream())?;
1414+
self.pclose()?;
1415+
self.s.word(";")?;
1416+
self.end()?;
1417+
}
14071418
}
14081419
ast::ItemKind::MacroDef(ref tts) => {
14091420
self.s.word("macro_rules! ")?;
@@ -1609,16 +1620,12 @@ impl<'a> State<'a> {
16091620
self.print_associated_type(ti.ident, Some(bounds),
16101621
default.as_ref().map(|ty| &**ty))?;
16111622
}
1612-
ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
1613-
// code copied from ItemKind::Mac:
1614-
self.print_path(&node.path, false, 0)?;
1615-
self.s.word("! ")?;
1616-
self.cbox(INDENT_UNIT)?;
1617-
self.popen()?;
1618-
self.print_tts(node.stream())?;
1619-
self.pclose()?;
1620-
self.s.word(";")?;
1621-
self.end()?
1623+
ast::TraitItemKind::Macro(ref mac) => {
1624+
self.print_mac(mac)?;
1625+
match mac.node.delim {
1626+
MacDelimiter::Brace => {}
1627+
_ => self.s.word(";")?,
1628+
}
16221629
}
16231630
}
16241631
self.ann.post(self, NodeSubItem(ti.id))
@@ -1643,16 +1650,12 @@ impl<'a> State<'a> {
16431650
ast::ImplItemKind::Type(ref ty) => {
16441651
self.print_associated_type(ii.ident, None, Some(ty))?;
16451652
}
1646-
ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
1647-
// code copied from ItemKind::Mac:
1648-
self.print_path(&node.path, false, 0)?;
1649-
self.s.word("! ")?;
1650-
self.cbox(INDENT_UNIT)?;
1651-
self.popen()?;
1652-
self.print_tts(node.stream())?;
1653-
self.pclose()?;
1654-
self.s.word(";")?;
1655-
self.end()?
1653+
ast::ImplItemKind::Macro(ref mac) => {
1654+
self.print_mac(mac)?;
1655+
match mac.node.delim {
1656+
MacDelimiter::Brace => {}
1657+
_ => self.s.word(";")?,
1658+
}
16561659
}
16571660
}
16581661
self.ann.post(self, NodeSubItem(ii.id))
@@ -1695,11 +1698,7 @@ impl<'a> State<'a> {
16951698
let (ref mac, style, ref attrs) = **mac;
16961699
self.space_if_not_bol()?;
16971700
self.print_outer_attributes(attrs)?;
1698-
let delim = match style {
1699-
ast::MacStmtStyle::Braces => token::Brace,
1700-
_ => token::Paren
1701-
};
1702-
self.print_mac(mac, delim)?;
1701+
self.print_mac(mac)?;
17031702
if style == ast::MacStmtStyle::Semicolon {
17041703
self.s.word(";")?;
17051704
}
@@ -1829,25 +1828,22 @@ impl<'a> State<'a> {
18291828
self.print_else(elseopt)
18301829
}
18311830

1832-
pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
1833-
-> io::Result<()> {
1831+
pub fn print_mac(&mut self, m: &ast::Mac) -> io::Result<()> {
18341832
self.print_path(&m.node.path, false, 0)?;
18351833
self.s.word("!")?;
1836-
match delim {
1837-
token::Paren => self.popen()?,
1838-
token::Bracket => self.s.word("[")?,
1839-
token::Brace => {
1834+
match m.node.delim {
1835+
MacDelimiter::Parenthesis => self.popen()?,
1836+
MacDelimiter::Bracket => self.s.word("[")?,
1837+
MacDelimiter::Brace => {
18401838
self.head("")?;
18411839
self.bopen()?;
18421840
}
1843-
token::NoDelim => {}
18441841
}
18451842
self.print_tts(m.node.stream())?;
1846-
match delim {
1847-
token::Paren => self.pclose(),
1848-
token::Bracket => self.s.word("]"),
1849-
token::Brace => self.bclose(m.span),
1850-
token::NoDelim => Ok(()),
1843+
match m.node.delim {
1844+
MacDelimiter::Parenthesis => self.pclose(),
1845+
MacDelimiter::Bracket => self.s.word("]"),
1846+
MacDelimiter::Brace => self.bclose(m.span),
18511847
}
18521848
}
18531849

@@ -2333,7 +2329,7 @@ impl<'a> State<'a> {
23332329

23342330
self.pclose()?;
23352331
}
2336-
ast::ExprKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
2332+
ast::ExprKind::Mac(ref m) => self.print_mac(m)?,
23372333
ast::ExprKind::Paren(ref e) => {
23382334
self.popen()?;
23392335
self.print_inner_attributes_inline(attrs)?;
@@ -2660,7 +2656,7 @@ impl<'a> State<'a> {
26602656
self.print_pat(inner)?;
26612657
self.pclose()?;
26622658
}
2663-
PatKind::Mac(ref m) => self.print_mac(m, token::Paren)?,
2659+
PatKind::Mac(ref m) => self.print_mac(m)?,
26642660
}
26652661
self.ann.post(self, NodePat(pat))
26662662
}

src/libsyntax_ext/assert.rs

+1
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ pub fn expand_assert<'cx>(
5353
),
5454
)).into()
5555
},
56+
delim: MacDelimiter::Parenthesis,
5657
};
5758
let if_expr = cx.expr_if(
5859
sp,

0 commit comments

Comments
 (0)