Skip to content

Commit 2b812b5

Browse files
committed
Preserve leading vert when pretty-printing patterns
Fixes #76182 Previously, we did not preserve the precense of a leading vert ('|') when parsing a pattern. This lead to an instance of #43081 when invoking a proc-macro, since the pretty-printed tokens would be missing the '|' present in the captured tokens.
1 parent d824b23 commit 2b812b5

File tree

12 files changed

+122
-10
lines changed

12 files changed

+122
-10
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,8 @@ pub struct Pat {
550550
pub id: NodeId,
551551
pub kind: PatKind,
552552
pub span: Span,
553+
/// Whether or not this pattern starts with a leading `|`
554+
pub leading_vert: bool,
553555
pub tokens: Option<TokenStream>,
554556
}
555557

@@ -2140,6 +2142,7 @@ impl Param {
21402142
id: DUMMY_NODE_ID,
21412143
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
21422144
span,
2145+
leading_vert: false,
21432146
tokens: None,
21442147
}),
21452148
span,

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1054,7 +1054,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
10541054
}
10551055

10561056
pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
1057-
let Pat { id, kind, span, tokens: _ } = pat.deref_mut();
1057+
let Pat { id, kind, span, leading_vert: _, tokens: _ } = pat.deref_mut();
10581058
vis.visit_id(id);
10591059
match kind {
10601060
PatKind::Wild | PatKind::Rest => {}

compiler/rustc_ast_pretty/src/pprust.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2302,6 +2302,11 @@ impl<'a> State<'a> {
23022302
crate fn print_pat(&mut self, pat: &ast::Pat) {
23032303
self.maybe_print_comment(pat.span.lo());
23042304
self.ann.pre(self, AnnNode::Pat(pat));
2305+
2306+
if pat.leading_vert {
2307+
self.s.word_space("|");
2308+
}
2309+
23052310
/* Pat isn't normalized, but the beauty of it
23062311
is that it doesn't matter */
23072312
match pat.kind {

compiler/rustc_expand/src/base.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ impl MacResult for MacEager {
551551
id: ast::DUMMY_NODE_ID,
552552
span: e.span,
553553
kind: PatKind::Lit(e),
554+
leading_vert: false,
554555
tokens: None,
555556
}));
556557
}
@@ -598,7 +599,13 @@ impl DummyResult {
598599

599600
/// A plain dummy pattern.
600601
pub fn raw_pat(sp: Span) -> ast::Pat {
601-
ast::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp, tokens: None }
602+
ast::Pat {
603+
id: ast::DUMMY_NODE_ID,
604+
kind: PatKind::Wild,
605+
span: sp,
606+
leading_vert: false,
607+
tokens: None,
608+
}
602609
}
603610

604611
/// A plain dummy type.

compiler/rustc_expand/src/build.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ impl<'a> ExtCtxt<'a> {
392392
}
393393

394394
pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
395-
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
395+
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, leading_vert: false, tokens: None })
396396
}
397397
pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
398398
self.pat(span, PatKind::Wild)

compiler/rustc_expand/src/placeholders.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,15 @@ pub fn placeholder(
3838
})
3939
};
4040
let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
41-
let pat =
42-
|| P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
41+
let pat = || {
42+
P(ast::Pat {
43+
id,
44+
kind: ast::PatKind::MacCall(mac_placeholder()),
45+
span,
46+
leading_vert: false,
47+
tokens: None,
48+
})
49+
};
4350

4451
match kind {
4552
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
@@ -86,6 +93,7 @@ pub fn placeholder(
8693
id,
8794
span,
8895
kind: ast::PatKind::MacCall(mac_placeholder()),
96+
leading_vert: false,
8997
tokens: None,
9098
})),
9199
AstFragmentKind::Ty => {

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
2626
id: ast::DUMMY_NODE_ID,
2727
kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
2828
span: ident.span,
29+
leading_vert: false,
2930
tokens: None,
3031
});
3132
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID };
@@ -88,6 +89,7 @@ impl RecoverQPath for Pat {
8889
span: path.span,
8990
kind: PatKind::Path(qself, path),
9091
id: ast::DUMMY_NODE_ID,
92+
leading_vert: false,
9193
tokens: None,
9294
}
9395
}
@@ -1532,8 +1534,13 @@ impl<'a> Parser<'a> {
15321534
.emit();
15331535

15341536
// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
1535-
let pat =
1536-
P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None });
1537+
let pat = P(Pat {
1538+
kind: PatKind::Wild,
1539+
span: pat.span,
1540+
id: ast::DUMMY_NODE_ID,
1541+
leading_vert: false,
1542+
tokens: None,
1543+
});
15371544
Ok((pat, ty))
15381545
}
15391546

compiler/rustc_parse/src/parser/pat.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ impl<'a> Parser<'a> {
4545
/// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
4646
pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> {
4747
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
48-
let gated_leading_vert = self.eat_or_separator(None) && gate_or == GateOr::Yes;
48+
let leading_vert = self.eat_or_separator(None);
49+
let gated_leading_vert = leading_vert && gate_or == GateOr::Yes;
4950
let leading_vert_span = self.prev_token.span;
5051

5152
// Parse the possibly-or-pattern.
52-
let pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?;
53+
let mut pat = self.parse_pat_with_or(None, gate_or, RecoverComma::Yes)?;
5354

5455
// If we parsed a leading `|` which should be gated,
5556
// and no other gated or-pattern has been parsed thus far,
@@ -58,6 +59,7 @@ impl<'a> Parser<'a> {
5859
if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) {
5960
self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
6061
}
62+
pat.leading_vert = leading_vert;
6163

6264
Ok(pat)
6365
}
@@ -1007,6 +1009,6 @@ impl<'a> Parser<'a> {
10071009
}
10081010

10091011
fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
1010-
P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
1012+
P(Pat { kind, span, id: ast::DUMMY_NODE_ID, leading_vert: false, tokens: None })
10111013
}
10121014
}

src/test/ui-fulldeps/pprust-expr-roundtrip.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
164164
id: DUMMY_NODE_ID,
165165
kind: PatKind::Wild,
166166
span: DUMMY_SP,
167+
leading_vert: false,
167168
tokens: None,
168169
});
169170
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// check-pass
2+
// aux-build:test-macros.rs
3+
// compile-flags: -Z span-debug
4+
//
5+
// Regression test for issue #76182
6+
// Tests that we properly handle patterns with a leading vert
7+
8+
#![no_std] // Don't load unnecessary hygiene information from std
9+
extern crate std;
10+
11+
extern crate test_macros;
12+
13+
#[test_macros::print_attr]
14+
fn main() {
15+
match () { | () => () }
16+
}

0 commit comments

Comments
 (0)