Skip to content

Preserve leading vert when pretty-printing patterns #76188

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,8 @@ pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
pub span: Span,
/// Whether or not this pattern starts with a leading `|`
pub leading_vert: bool,
Copy link
Member

@matklad matklad Sep 1, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is vert terminology used elsewhere? Looking at the two TokenKinds (one in ast, one in rustc_lexer), the name for the thing is Or, so maybe stick with leading_or?

OTOH, I don't really enjoy and / or names for & and | symbols, so we might want to rename those (obviously, in a separate PR). In rust-analyzer, those are called amp and pipe, but vert or vbar also would work for | I think (although i do find vert specifically confusing a bit).

EDIT: to clarify on the naming thing: I don't like and / or because they name operations that the symbols somtimes represent, and not the symbols themselves. In contrast, ampersand & vertical bar are the names of the glyphs.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vert terminology is used in parse_top_pat, which is why I picked it.

pub tokens: Option<TokenStream>,
}

Expand Down Expand Up @@ -2140,6 +2142,7 @@ impl Param {
id: DUMMY_NODE_ID,
kind: PatKind::Ident(BindingMode::ByValue(mutbl), eself_ident, None),
span,
leading_vert: false,
tokens: None,
}),
span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,7 @@ pub fn noop_flat_map_foreign_item<T: MutVisitor>(
}

pub fn noop_visit_pat<T: MutVisitor>(pat: &mut P<Pat>, vis: &mut T) {
let Pat { id, kind, span, tokens: _ } = pat.deref_mut();
let Pat { id, kind, span, leading_vert: _, tokens: _ } = pat.deref_mut();
vis.visit_id(id);
match kind {
PatKind::Wild | PatKind::Rest => {}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_ast_pretty/src/pprust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2302,6 +2302,11 @@ impl<'a> State<'a> {
crate fn print_pat(&mut self, pat: &ast::Pat) {
self.maybe_print_comment(pat.span.lo());
self.ann.pre(self, AnnNode::Pat(pat));

if pat.leading_vert {
self.s.word_space("|");
}

/* Pat isn't normalized, but the beauty of it
is that it doesn't matter */
match pat.kind {
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ impl MacResult for MacEager {
id: ast::DUMMY_NODE_ID,
span: e.span,
kind: PatKind::Lit(e),
leading_vert: false,
tokens: None,
}));
}
Expand Down Expand Up @@ -598,7 +599,13 @@ impl DummyResult {

/// A plain dummy pattern.
pub fn raw_pat(sp: Span) -> ast::Pat {
ast::Pat { id: ast::DUMMY_NODE_ID, kind: PatKind::Wild, span: sp, tokens: None }
ast::Pat {
id: ast::DUMMY_NODE_ID,
kind: PatKind::Wild,
span: sp,
leading_vert: false,
tokens: None,
}
}

/// A plain dummy type.
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_expand/src/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ impl<'a> ExtCtxt<'a> {
}

pub fn pat(&self, span: Span, kind: PatKind) -> P<ast::Pat> {
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, tokens: None })
P(ast::Pat { id: ast::DUMMY_NODE_ID, kind, span, leading_vert: false, tokens: None })
}
pub fn pat_wild(&self, span: Span) -> P<ast::Pat> {
self.pat(span, PatKind::Wild)
Expand Down
12 changes: 10 additions & 2 deletions compiler/rustc_expand/src/placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,15 @@ pub fn placeholder(
})
};
let ty = || P(ast::Ty { id, kind: ast::TyKind::MacCall(mac_placeholder()), span });
let pat =
|| P(ast::Pat { id, kind: ast::PatKind::MacCall(mac_placeholder()), span, tokens: None });
let pat = || {
P(ast::Pat {
id,
kind: ast::PatKind::MacCall(mac_placeholder()),
span,
leading_vert: false,
tokens: None,
})
};

match kind {
AstFragmentKind::Expr => AstFragment::Expr(expr_placeholder()),
Expand Down Expand Up @@ -86,6 +93,7 @@ pub fn placeholder(
id,
span,
kind: ast::PatKind::MacCall(mac_placeholder()),
leading_vert: false,
tokens: None,
})),
AstFragmentKind::Ty => {
Expand Down
11 changes: 9 additions & 2 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ pub(super) fn dummy_arg(ident: Ident) -> Param {
id: ast::DUMMY_NODE_ID,
kind: PatKind::Ident(BindingMode::ByValue(Mutability::Not), ident, None),
span: ident.span,
leading_vert: false,
tokens: None,
});
let ty = Ty { kind: TyKind::Err, span: ident.span, id: ast::DUMMY_NODE_ID };
Expand Down Expand Up @@ -88,6 +89,7 @@ impl RecoverQPath for Pat {
span: path.span,
kind: PatKind::Path(qself, path),
id: ast::DUMMY_NODE_ID,
leading_vert: false,
tokens: None,
}
}
Expand Down Expand Up @@ -1532,8 +1534,13 @@ impl<'a> Parser<'a> {
.emit();

// Pretend the pattern is `_`, to avoid duplicate errors from AST validation.
let pat =
P(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID, tokens: None });
let pat = P(Pat {
kind: PatKind::Wild,
span: pat.span,
id: ast::DUMMY_NODE_ID,
leading_vert: false,
tokens: None,
});
Ok((pat, ty))
}

Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ impl<'a> Parser<'a> {
/// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
pub(super) fn parse_top_pat(&mut self, gate_or: GateOr) -> PResult<'a, P<Pat>> {
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
let gated_leading_vert = self.eat_or_separator(None) && gate_or == GateOr::Yes;
let leading_vert = self.eat_or_separator(None);
let gated_leading_vert = leading_vert && gate_or == GateOr::Yes;
let leading_vert_span = self.prev_token.span;

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

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

Ok(pat)
}
Expand Down Expand Up @@ -1007,6 +1009,6 @@ impl<'a> Parser<'a> {
}

fn mk_pat(&self, span: Span, kind: PatKind) -> P<Pat> {
P(Pat { kind, span, id: ast::DUMMY_NODE_ID, tokens: None })
P(Pat { kind, span, id: ast::DUMMY_NODE_ID, leading_vert: false, tokens: None })
}
}
1 change: 1 addition & 0 deletions src/test/ui-fulldeps/pprust-expr-roundtrip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
id: DUMMY_NODE_ID,
kind: PatKind::Wild,
span: DUMMY_SP,
leading_vert: false,
tokens: None,
});
iter_exprs(depth - 1, &mut |e| g(ExprKind::Let(pat.clone(), e)))
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/proc-macro/issue-76182-leading-vert-pat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// check-pass
// aux-build:test-macros.rs
// compile-flags: -Z span-debug
//
// Regression test for issue #76182
// Tests that we properly handle patterns with a leading vert

#![no_std] // Don't load unnecessary hygiene information from std
extern crate std;

extern crate test_macros;

#[test_macros::print_attr]
fn main() {
match () { | () => () }
}
62 changes: 62 additions & 0 deletions src/test/ui/proc-macro/issue-76182-leading-vert-pat.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
PRINT-ATTR INPUT (DISPLAY): fn main() { match() { | () => () } }
PRINT-ATTR INPUT (DEBUG): TokenStream [
Ident {
ident: "fn",
span: $DIR/issue-76182-leading-vert-pat.rs:14:1: 14:3 (#0),
},
Ident {
ident: "main",
span: $DIR/issue-76182-leading-vert-pat.rs:14:4: 14:8 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: $DIR/issue-76182-leading-vert-pat.rs:14:8: 14:10 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
Ident {
ident: "match",
span: $DIR/issue-76182-leading-vert-pat.rs:15:5: 15:10 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: $DIR/issue-76182-leading-vert-pat.rs:15:11: 15:13 (#0),
},
Group {
delimiter: Brace,
stream: TokenStream [
Punct {
ch: '|',
spacing: Alone,
span: $DIR/issue-76182-leading-vert-pat.rs:15:16: 15:17 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: $DIR/issue-76182-leading-vert-pat.rs:15:18: 15:20 (#0),
},
Punct {
ch: '=',
spacing: Joint,
span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
},
Punct {
ch: '>',
spacing: Alone,
span: $DIR/issue-76182-leading-vert-pat.rs:15:21: 15:23 (#0),
},
Group {
delimiter: Parenthesis,
stream: TokenStream [],
span: $DIR/issue-76182-leading-vert-pat.rs:15:24: 15:26 (#0),
},
],
span: $DIR/issue-76182-leading-vert-pat.rs:15:14: 15:28 (#0),
},
],
span: $DIR/issue-76182-leading-vert-pat.rs:14:11: 16:2 (#0),
},
]
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_lints/src/unnested_or_patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ fn take_pat(from: &mut Pat) -> Pat {
id: DUMMY_NODE_ID,
kind: Wild,
span: DUMMY_SP,
leading_vert: false,
tokens: None,
};
mem::replace(from, dummy)
Expand Down