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

+3
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

+1-1
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

+5
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

+8-1
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

+1-1
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

+10-2
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

+9-2
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

+5-3
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

+1
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)))
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+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } }
2+
PRINT-ATTR INPUT (DEBUG): TokenStream [
3+
Ident {
4+
ident: "fn",
5+
span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0),
6+
},
7+
Ident {
8+
ident: "main",
9+
span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0),
10+
},
11+
Group {
12+
delimiter: Parenthesis,
13+
stream: TokenStream [],
14+
span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0),
15+
},
16+
Group {
17+
delimiter: Brace,
18+
stream: TokenStream [
19+
Ident {
20+
ident: "match",
21+
span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0),
22+
},
23+
Group {
24+
delimiter: Parenthesis,
25+
stream: TokenStream [],
26+
span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0),
27+
},
28+
Group {
29+
delimiter: Brace,
30+
stream: TokenStream [
31+
Punct {
32+
ch: '|',
33+
spacing: Alone,
34+
span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0),
35+
},
36+
Group {
37+
delimiter: Parenthesis,
38+
stream: TokenStream [],
39+
span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0),
40+
},
41+
Punct {
42+
ch: '=',
43+
spacing: Joint,
44+
span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
45+
},
46+
Punct {
47+
ch: '>',
48+
spacing: Alone,
49+
span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
50+
},
51+
Group {
52+
delimiter: Parenthesis,
53+
stream: TokenStream [],
54+
span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0),
55+
},
56+
],
57+
span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0),
58+
},
59+
],
60+
span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0),
61+
},
62+
]

src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs

+1
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ fn take_pat(from: &mut Pat) -> Pat {
340340
id: DUMMY_NODE_ID,
341341
kind: Wild,
342342
span: DUMMY_SP,
343+
leading_vert: false,
343344
tokens: None,
344345
};
345346
mem::replace(from, dummy)

0 commit comments

Comments
 (0)