Simplify pattern grammar by allowing nested leading vert

Along the way, we also implement a handful of diagnostics improvements
and fixes, particularly with respect to the special handling of `||` in
place of `|` and when there are leading verts in function params, which
don't allow top-level or-patterns anyway.
This commit is contained in:
mark 2021-02-07 20:40:33 -06:00
parent d1206f950f
commit aee1e59e6f
18 changed files with 189 additions and 303 deletions

View File

@ -22,7 +22,7 @@ use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_errors::{Applicability, PResult}; use rustc_errors::{Applicability, PResult};
use rustc_feature::Features; use rustc_feature::Features;
use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, Parser}; use rustc_parse::parser::{AttemptLocalParseRecovery, ForceCollect, GateOr, Parser, RecoverComma};
use rustc_parse::validate_attr; use rustc_parse::validate_attr;
use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS; use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::lint::BuiltinLintDiagnostics;
@ -914,7 +914,9 @@ pub fn parse_ast_fragment<'a>(
} }
} }
AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?), AstFragmentKind::Ty => AstFragment::Ty(this.parse_ty()?),
AstFragmentKind::Pat => AstFragment::Pat(this.parse_pat(None)?), AstFragmentKind::Pat => {
AstFragment::Pat(this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?)
}
AstFragmentKind::Arms AstFragmentKind::Arms
| AstFragmentKind::Fields | AstFragmentKind::Fields
| AstFragmentKind::FieldPats | AstFragmentKind::FieldPats

View File

@ -1654,7 +1654,7 @@ impl<'a> Parser<'a> {
} }
pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> { pub(super) fn recover_arg_parse(&mut self) -> PResult<'a, (P<ast::Pat>, P<ast::Ty>)> {
let pat = self.parse_pat(Some("argument name"))?; let pat = self.parse_pat_no_top_alt(Some("argument name"))?;
self.expect(&token::Colon)?; self.expect(&token::Colon)?;
let ty = self.parse_ty()?; let ty = self.parse_ty()?;

View File

@ -1726,7 +1726,7 @@ impl<'a> Parser<'a> {
let lo = self.token.span; let lo = self.token.span;
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let pat = this.parse_pat(PARAM_EXPECTED)?; let pat = this.parse_pat_no_top_alt(PARAM_EXPECTED)?;
let ty = if this.eat(&token::Colon) { let ty = if this.eat(&token::Colon) {
this.parse_ty()? this.parse_ty()?
} else { } else {
@ -1803,7 +1803,7 @@ impl<'a> Parser<'a> {
/// The `let` token has already been eaten. /// The `let` token has already been eaten.
fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> { fn parse_let_expr(&mut self, attrs: AttrVec) -> PResult<'a, P<Expr>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let pat = self.parse_top_pat(GateOr::No, RecoverComma::Yes)?; let pat = self.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| { let expr = self.with_res(self.restrictions | Restrictions::NO_STRUCT_LITERAL, |this| {
this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into()) this.parse_assoc_expr_with(1 + prec_let_scrutinee_needs_par(), None.into())
@ -1866,7 +1866,7 @@ impl<'a> Parser<'a> {
_ => None, _ => None,
}; };
let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?; let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
if !self.eat_keyword(kw::In) { if !self.eat_keyword(kw::In) {
self.error_missing_in_for_loop(); self.error_missing_in_for_loop();
} }
@ -1977,7 +1977,7 @@ impl<'a> Parser<'a> {
let attrs = self.parse_outer_attributes()?; let attrs = self.parse_outer_attributes()?;
self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| { self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
let lo = this.token.span; let lo = this.token.span;
let pat = this.parse_top_pat(GateOr::No, RecoverComma::Yes)?; let pat = this.parse_pat_allow_top_alt(None, GateOr::No, RecoverComma::Yes)?;
let guard = if this.eat_keyword(kw::If) { let guard = if this.eat_keyword(kw::If) {
let if_span = this.prev_token.span; let if_span = this.prev_token.span;
let cond = this.parse_expr()?; let cond = this.parse_expr()?;

View File

@ -14,6 +14,7 @@ use crate::lexer::UnmatchedBrace;
pub use attr_wrapper::AttrWrapper; pub use attr_wrapper::AttrWrapper;
pub use diagnostics::AttemptLocalParseRecovery; pub use diagnostics::AttemptLocalParseRecovery;
use diagnostics::Error; use diagnostics::Error;
pub use pat::{GateOr, RecoverComma};
pub use path::PathStyle; pub use path::PathStyle;
use rustc_ast::ptr::P; use rustc_ast::ptr::P;

View File

@ -120,9 +120,9 @@ impl<'a> Parser<'a> {
}, },
NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => { NonterminalKind::Pat2018 { .. } | NonterminalKind::Pat2021 { .. } => {
token::NtPat(self.collect_tokens_no_attrs(|this| match kind { token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
NonterminalKind::Pat2018 { .. } => this.parse_pat(None), NonterminalKind::Pat2018 { .. } => this.parse_pat_no_top_alt(None),
NonterminalKind::Pat2021 { .. } => { NonterminalKind::Pat2021 { .. } => {
this.parse_top_pat(GateOr::Yes, RecoverComma::No) this.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
} }
_ => unreachable!(), _ => unreachable!(),
})?) })?)

View File

@ -19,14 +19,14 @@ const WHILE_PARSING_OR_MSG: &str = "while parsing this or-pattern starting here"
/// Whether or not an or-pattern should be gated when occurring in the current context. /// Whether or not an or-pattern should be gated when occurring in the current context.
#[derive(PartialEq, Clone, Copy)] #[derive(PartialEq, Clone, Copy)]
pub(super) enum GateOr { pub enum GateOr {
Yes, Yes,
No, No,
} }
/// Whether or not to recover a `,` when parsing or-patterns. /// Whether or not to recover a `,` when parsing or-patterns.
#[derive(PartialEq, Copy, Clone)] #[derive(PartialEq, Copy, Clone)]
pub(super) enum RecoverComma { pub enum RecoverComma {
Yes, Yes,
No, No,
} }
@ -37,80 +37,57 @@ impl<'a> Parser<'a> {
/// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns /// Corresponds to `pat<no_top_alt>` in RFC 2535 and does not admit or-patterns
/// at the top level. Used when parsing the parameters of lambda expressions, /// at the top level. Used when parsing the parameters of lambda expressions,
/// functions, function pointers, and `pat` macro fragments. /// functions, function pointers, and `pat` macro fragments.
pub fn parse_pat(&mut self, expected: Expected) -> PResult<'a, P<Pat>> { pub fn parse_pat_no_top_alt(&mut self, expected: Expected) -> PResult<'a, P<Pat>> {
self.parse_pat_with_range_pat(true, expected) self.parse_pat_with_range_pat(true, expected)
} }
/// Entry point to the main pattern parser. /// Parses a pattern.
///
/// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level. /// Corresponds to `top_pat` in RFC 2535 and allows or-pattern at the top level.
pub(super) fn parse_top_pat( /// Used for parsing patterns in all cases when `pat<no_top_alt>` is not used.
&mut self, ///
gate_or: GateOr, /// Note that after the FCP in <https://github.com/rust-lang/rust/issues/81415>,
rc: RecoverComma, /// a leading vert is allowed in nested or-patterns, too. This allows us to
) -> PResult<'a, P<Pat>> { /// simplify the grammar somewhat.
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535). pub fn parse_pat_allow_top_alt(
let gated_leading_vert = self.eat_or_separator(None) && 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, rc)?;
// If we parsed a leading `|` which should be gated,
// and no other gated or-pattern has been parsed thus far,
// then we should really gate the leading `|`.
// This complicated procedure is done purely for diagnostics UX.
if gated_leading_vert && self.sess.gated_spans.is_ungated(sym::or_patterns) {
self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
}
Ok(pat)
}
/// Parse the pattern for a function or function pointer parameter.
/// Special recovery is provided for or-patterns and leading `|`.
pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
self.recover_leading_vert(None, "not allowed in a parameter pattern");
let pat = self.parse_pat_with_or(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;
if let PatKind::Or(..) = &pat.kind {
self.ban_illegal_fn_param_or_pat(&pat);
}
Ok(pat)
}
/// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
let msg = "wrap the pattern in parenthesis";
let fix = format!("({})", pprust::pat_to_string(pat));
self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parenthesis")
.span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
.emit();
}
/// Parses a pattern, that may be a or-pattern (e.g. `Foo | Bar` in `Some(Foo | Bar)`).
/// Corresponds to `pat<allow_top_alt>` in RFC 2535.
fn parse_pat_with_or(
&mut self, &mut self,
expected: Expected, expected: Expected,
gate_or: GateOr, gate_or: GateOr,
rc: RecoverComma, rc: RecoverComma,
) -> PResult<'a, P<Pat>> { ) -> PResult<'a, P<Pat>> {
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
let leading_vert_span =
if self.eat_or_separator(None) { Some(self.prev_token.span) } else { None };
// Parse the first pattern (`p_0`). // Parse the first pattern (`p_0`).
let first_pat = self.parse_pat(expected)?; let first_pat = self.parse_pat_no_top_alt(expected)?;
self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?; self.maybe_recover_unexpected_comma(first_pat.span, rc, gate_or)?;
// If the next token is not a `|`, // If the next token is not a `|`,
// this is not an or-pattern and we should exit here. // this is not an or-pattern and we should exit here.
if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr { if !self.check(&token::BinOp(token::Or)) && self.token != token::OrOr {
// If we parsed a leading `|` which should be gated,
// then we should really gate the leading `|`.
// This complicated procedure is done purely for diagnostics UX.
if let Some(leading_vert_span) = leading_vert_span {
if gate_or == GateOr::Yes && self.sess.gated_spans.is_ungated(sym::or_patterns) {
self.sess.gated_spans.gate(sym::or_patterns, leading_vert_span);
}
// If there was a leading vert, treat this as an or-pattern. This improves
// diagnostics.
let span = leading_vert_span.to(self.prev_token.span);
return Ok(self.mk_pat(span, PatKind::Or(vec![first_pat])));
}
return Ok(first_pat); return Ok(first_pat);
} }
// Parse the patterns `p_1 | ... | p_n` where `n > 0`. // Parse the patterns `p_1 | ... | p_n` where `n > 0`.
let lo = first_pat.span; let lo = leading_vert_span.unwrap_or(first_pat.span);
let mut pats = vec![first_pat]; let mut pats = vec![first_pat];
while self.eat_or_separator(Some(lo)) { while self.eat_or_separator(Some(lo)) {
let pat = self.parse_pat(expected).map_err(|mut err| { let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| {
err.span_label(lo, WHILE_PARSING_OR_MSG); err.span_label(lo, WHILE_PARSING_OR_MSG);
err err
})?; })?;
@ -127,6 +104,62 @@ impl<'a> Parser<'a> {
Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
} }
/// Parse the pattern for a function or function pointer parameter.
pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
// We actually do _not_ allow top-level or-patterns in function params, but we use
// `parse_pat_allow_top_alt` anyway so that we can detect when a user tries to use it. This
// allows us to print a better error message.
//
// In order to get good UX, we first recover in the case of a leading vert for an illegal
// top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
// a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
// separately.
if let token::OrOr = self.token.kind {
let span = self.token.span;
let mut err = self.struct_span_err(span, "unexpected `||` before function parameter");
err.span_suggestion(
span,
"remove the `||`",
String::new(),
Applicability::MachineApplicable,
);
err.note("alternatives in or-patterns are separated with `|`, not `||`");
err.emit();
self.bump();
}
let pat = self.parse_pat_allow_top_alt(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;
if let PatKind::Or(..) = &pat.kind {
self.ban_illegal_fn_param_or_pat(&pat);
}
Ok(pat)
}
/// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
// If all we have a leading vert, then print a special message. This is the case if
// `parse_pat_allow_top_alt` returns an or-pattern with one variant.
let (msg, fix) = match &pat.kind {
PatKind::Or(pats) if pats.len() == 1 => {
let msg = "remove the leading `|`";
let fix = pprust::pat_to_string(pat);
(msg, fix)
}
_ => {
let msg = "wrap the pattern in parentheses";
let fix = format!("({})", pprust::pat_to_string(pat));
(msg, fix)
}
};
self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parentheses")
.span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
.emit();
}
/// Eat the or-pattern `|` separator. /// Eat the or-pattern `|` separator.
/// If instead a `||` token is encountered, recover and pretend we parsed `|`. /// If instead a `||` token is encountered, recover and pretend we parsed `|`.
fn eat_or_separator(&mut self, lo: Option<Span>) -> bool { fn eat_or_separator(&mut self, lo: Option<Span>) -> bool {
@ -179,7 +212,7 @@ impl<'a> Parser<'a> {
/// We have parsed `||` instead of `|`. Error and suggest `|` instead. /// We have parsed `||` instead of `|`. Error and suggest `|` instead.
fn ban_unexpected_or_or(&mut self, lo: Option<Span>) { fn ban_unexpected_or_or(&mut self, lo: Option<Span>) {
let mut err = self.struct_span_err(self.token.span, "unexpected token `||` after pattern"); let mut err = self.struct_span_err(self.token.span, "unexpected token `||` in pattern");
err.span_suggestion( err.span_suggestion(
self.token.span, self.token.span,
"use a single `|` to separate multiple alternative patterns", "use a single `|` to separate multiple alternative patterns",
@ -244,7 +277,7 @@ impl<'a> Parser<'a> {
/// sequence of patterns until `)` is reached. /// sequence of patterns until `)` is reached.
fn skip_pat_list(&mut self) -> PResult<'a, ()> { fn skip_pat_list(&mut self) -> PResult<'a, ()> {
while !self.check(&token::CloseDelim(token::Paren)) { while !self.check(&token::CloseDelim(token::Paren)) {
self.parse_pat(None)?; self.parse_pat_no_top_alt(None)?;
if !self.eat(&token::Comma) { if !self.eat(&token::Comma) {
return Ok(()); return Ok(());
} }
@ -252,22 +285,6 @@ impl<'a> Parser<'a> {
Ok(()) Ok(())
} }
/// Recursive possibly-or-pattern parser with recovery for an erroneous leading `|`.
/// See `parse_pat_with_or` for details on parsing or-patterns.
fn parse_pat_with_or_inner(&mut self) -> PResult<'a, P<Pat>> {
self.recover_leading_vert(None, "only allowed in a top-level pattern");
self.parse_pat_with_or(None, GateOr::Yes, RecoverComma::No)
}
/// Recover if `|` or `||` is here.
/// The user is thinking that a leading `|` is allowed in this position.
fn recover_leading_vert(&mut self, lo: Option<Span>, ctx: &str) {
if let token::BinOp(token::Or) | token::OrOr = self.token.kind {
self.ban_illegal_vert(lo, "leading", ctx);
self.bump();
}
}
/// A `|` or possibly `||` token shouldn't be here. Ban it. /// A `|` or possibly `||` token shouldn't be here. Ban it.
fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) { fn ban_illegal_vert(&mut self, lo: Option<Span>, pos: &str, ctx: &str) {
let span = self.token.span; let span = self.token.span;
@ -305,8 +322,9 @@ impl<'a> Parser<'a> {
self.parse_pat_tuple_or_parens()? self.parse_pat_tuple_or_parens()?
} else if self.check(&token::OpenDelim(token::Bracket)) { } else if self.check(&token::OpenDelim(token::Bracket)) {
// Parse `[pat, pat,...]` as a slice pattern. // Parse `[pat, pat,...]` as a slice pattern.
let (pats, _) = let (pats, _) = self.parse_delim_comma_seq(token::Bracket, |p| {
self.parse_delim_comma_seq(token::Bracket, |p| p.parse_pat_with_or_inner())?; p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
})?;
PatKind::Slice(pats) PatKind::Slice(pats)
} else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) { } else if self.check(&token::DotDot) && !self.is_pat_range_end_start(1) {
// A rest pattern `..`. // A rest pattern `..`.
@ -429,7 +447,7 @@ impl<'a> Parser<'a> {
// At this point we attempt to parse `@ $pat_rhs` and emit an error. // At this point we attempt to parse `@ $pat_rhs` and emit an error.
self.bump(); // `@` self.bump(); // `@`
let mut rhs = self.parse_pat(None)?; let mut rhs = self.parse_pat_no_top_alt(None)?;
let sp = lhs.span.to(rhs.span); let sp = lhs.span.to(rhs.span);
if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind { if let PatKind::Ident(_, _, ref mut sub @ None) = rhs.kind {
@ -518,8 +536,9 @@ impl<'a> Parser<'a> {
/// Parse a tuple or parenthesis pattern. /// Parse a tuple or parenthesis pattern.
fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> { fn parse_pat_tuple_or_parens(&mut self) -> PResult<'a, PatKind> {
let (fields, trailing_comma) = let (fields, trailing_comma) = self.parse_paren_comma_seq(|p| {
self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?; p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
})?;
// Here, `(pat,)` is a tuple pattern. // Here, `(pat,)` is a tuple pattern.
// For backward compatibility, `(..)` is a tuple pattern as well. // For backward compatibility, `(..)` is a tuple pattern as well.
@ -548,7 +567,7 @@ impl<'a> Parser<'a> {
} }
// Parse the pattern we hope to be an identifier. // Parse the pattern we hope to be an identifier.
let mut pat = self.parse_pat(Some("identifier"))?; let mut pat = self.parse_pat_no_top_alt(Some("identifier"))?;
// If we don't have `mut $ident (@ pat)?`, error. // If we don't have `mut $ident (@ pat)?`, error.
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind { if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind {
@ -793,7 +812,7 @@ impl<'a> Parser<'a> {
fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> { fn parse_pat_ident(&mut self, binding_mode: BindingMode) -> PResult<'a, PatKind> {
let ident = self.parse_ident()?; let ident = self.parse_ident()?;
let sub = if self.eat(&token::At) { let sub = if self.eat(&token::At) {
Some(self.parse_pat(Some("binding pattern"))?) Some(self.parse_pat_no_top_alt(Some("binding pattern"))?)
} else { } else {
None None
}; };
@ -832,7 +851,9 @@ impl<'a> Parser<'a> {
if qself.is_some() { if qself.is_some() {
return self.error_qpath_before_pat(&path, "("); return self.error_qpath_before_pat(&path, "(");
} }
let (fields, _) = self.parse_paren_comma_seq(|p| p.parse_pat_with_or_inner())?; let (fields, _) = self.parse_paren_comma_seq(|p| {
p.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)
})?;
Ok(PatKind::TupleStruct(path, fields)) Ok(PatKind::TupleStruct(path, fields))
} }
@ -998,7 +1019,7 @@ impl<'a> Parser<'a> {
// Parsing a pattern of the form `fieldname: pat`. // Parsing a pattern of the form `fieldname: pat`.
let fieldname = self.parse_field_name()?; let fieldname = self.parse_field_name()?;
self.bump(); self.bump();
let pat = self.parse_pat_with_or_inner()?; let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::No)?;
hi = pat.span; hi = pat.span;
(pat, fieldname, false) (pat, fieldname, false)
} else { } else {

View File

@ -220,7 +220,7 @@ impl<'a> Parser<'a> {
/// Parses a local variable declaration. /// Parses a local variable declaration.
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> { fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
let lo = self.prev_token.span; let lo = self.prev_token.span;
let pat = self.parse_top_pat(GateOr::Yes, RecoverComma::Yes)?; let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
let (err, ty) = if self.eat(&token::Colon) { let (err, ty) = if self.eat(&token::Colon) {
// Save the state of the parser before parsing type normally, in case there is a `:` // Save the state of the parser before parsing type normally, in case there is a `:`

View File

@ -8,10 +8,10 @@ LL | Some(0 | 1 | 2) => {}
= help: add `#![feature(or_patterns)]` to the crate attributes to enable = help: add `#![feature(or_patterns)]` to the crate attributes to enable
error[E0658]: or-patterns syntax is experimental error[E0658]: or-patterns syntax is experimental
--> $DIR/feature-gate-or_patterns.rs:28:11 --> $DIR/feature-gate-or_patterns.rs:28:9
| |
LL | let | A | B; LL | let | A | B;
| ^^^^^ | ^^^^^^^
| |
= note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
= help: add `#![feature(or_patterns)]` to the crate attributes to enable = help: add `#![feature(or_patterns)]` to the crate attributes to enable
@ -26,10 +26,10 @@ LL | let A | B;
= help: add `#![feature(or_patterns)]` to the crate attributes to enable = help: add `#![feature(or_patterns)]` to the crate attributes to enable
error[E0658]: or-patterns syntax is experimental error[E0658]: or-patterns syntax is experimental
--> $DIR/feature-gate-or_patterns.rs:30:11 --> $DIR/feature-gate-or_patterns.rs:30:9
| |
LL | for | A | B in 0 {} LL | for | A | B in 0 {}
| ^^^^^ | ^^^^^^^
| |
= note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information = note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
= help: add `#![feature(or_patterns)]` to the crate attributes to enable = help: add `#![feature(or_patterns)]` to the crate attributes to enable

View File

@ -11,4 +11,4 @@ enum E { A, B }
use E::*; use E::*;
#[cfg(FALSE)] #[cfg(FALSE)]
fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses

View File

@ -11,4 +11,4 @@ enum E { A, B }
use E::*; use E::*;
#[cfg(FALSE)] #[cfg(FALSE)]
fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses

View File

@ -1,8 +1,8 @@
error: an or-pattern parameter must be wrapped in parenthesis error: an or-pattern parameter must be wrapped in parentheses
--> $DIR/fn-param-wrap-parens.rs:14:9 --> $DIR/fn-param-wrap-parens.rs:14:9
| |
LL | fn fun1(A | B: E) {} LL | fn fun1(A | B: E) {}
| ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` | ^^^^^ help: wrap the pattern in parentheses: `(A | B)`
error: aborting due to previous error error: aborting due to previous error

View File

@ -4,41 +4,41 @@ fn main() {
let x = 3; let x = 3;
match x { match x {
1 | 2 || 3 => (), //~ ERROR unexpected token `||` after pattern 1 | 2 || 3 => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
match x { match x {
(1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern (1 | 2 || 3) => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
match (x,) { match (x,) {
(1 | 2 || 3,) => (), //~ ERROR unexpected token `||` after pattern (1 | 2 || 3,) => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
struct TS(u8); struct TS(u8);
match TS(x) { match TS(x) {
TS(1 | 2 || 3) => (), //~ ERROR unexpected token `||` after pattern TS(1 | 2 || 3) => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
struct NS { f: u8 } struct NS { f: u8 }
match (NS { f: x }) { match (NS { f: x }) {
NS { f: 1 | 2 || 3 } => (), //~ ERROR unexpected token `||` after pattern NS { f: 1 | 2 || 3 } => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
match [x] { match [x] {
[1 | 2 || 3] => (), //~ ERROR unexpected token `||` after pattern [1 | 2 || 3] => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
match x { match x {
|| 1 | 2 | 3 => (), //~ ERROR unexpected token `||` after pattern || 1 | 2 | 3 => (), //~ ERROR unexpected token `||` in pattern
_ => (), _ => (),
} }
} }

View File

@ -1,4 +1,4 @@
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:7:15 --> $DIR/multiple-pattern-typo.rs:7:15
| |
LL | 1 | 2 || 3 => (), LL | 1 | 2 || 3 => (),
@ -6,7 +6,7 @@ LL | 1 | 2 || 3 => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:12:16 --> $DIR/multiple-pattern-typo.rs:12:16
| |
LL | (1 | 2 || 3) => (), LL | (1 | 2 || 3) => (),
@ -14,7 +14,7 @@ LL | (1 | 2 || 3) => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:17:16 --> $DIR/multiple-pattern-typo.rs:17:16
| |
LL | (1 | 2 || 3,) => (), LL | (1 | 2 || 3,) => (),
@ -22,7 +22,7 @@ LL | (1 | 2 || 3,) => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:24:18 --> $DIR/multiple-pattern-typo.rs:24:18
| |
LL | TS(1 | 2 || 3) => (), LL | TS(1 | 2 || 3) => (),
@ -30,7 +30,7 @@ LL | TS(1 | 2 || 3) => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:31:23 --> $DIR/multiple-pattern-typo.rs:31:23
| |
LL | NS { f: 1 | 2 || 3 } => (), LL | NS { f: 1 | 2 || 3 } => (),
@ -38,7 +38,7 @@ LL | NS { f: 1 | 2 || 3 } => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:36:16 --> $DIR/multiple-pattern-typo.rs:36:16
| |
LL | [1 | 2 || 3] => (), LL | [1 | 2 || 3] => (),
@ -46,7 +46,7 @@ LL | [1 | 2 || 3] => (),
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/multiple-pattern-typo.rs:41:9 --> $DIR/multiple-pattern-typo.rs:41:9
| |
LL | || 1 | 2 | 3 => (), LL | || 1 | 2 | 3 => (),

View File

@ -14,29 +14,8 @@ fn no_top_level_or_patterns() {
// -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`. // -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`.
// ...and for now neither do we allow or-patterns at the top level of functions. // ...and for now neither do we allow or-patterns at the top level of functions.
fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parenthesis fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
fn fun2(| A | B: E) {} fn fun2(| A | B: E) {}
//~^ ERROR a leading `|` is not allowed in a parameter pattern //~^ ERROR an or-pattern parameter must be wrapped in parentheses
//~| ERROR an or-pattern parameter must be wrapped in parenthesis
}
// We also do not allow a leading `|` when not in a top level position:
fn no_leading_inner() {
struct TS(E);
struct NS { f: E }
let ( | A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern
let ( | A | B,) = (E::B,); //~ ERROR a leading `|` is only allowed in a top-level pattern
let [ | A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern
let TS( | A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern
let NS { f: | A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern
let ( || A | B) = E::A; //~ ERROR a leading `|` is only allowed in a top-level pattern
let [ || A | B ] = [E::A]; //~ ERROR a leading `|` is only allowed in a top-level pattern
let TS( || A | B ); //~ ERROR a leading `|` is only allowed in a top-level pattern
let NS { f: || A | B }; //~ ERROR a leading `|` is only allowed in a top-level pattern
let recovery_witness: String = 0; //~ ERROR mismatched types
} }

View File

@ -1,82 +1,14 @@
error: an or-pattern parameter must be wrapped in parenthesis error: an or-pattern parameter must be wrapped in parentheses
--> $DIR/or-patterns-syntactic-fail.rs:17:13 --> $DIR/or-patterns-syntactic-fail.rs:17:13
| |
LL | fn fun1(A | B: E) {} LL | fn fun1(A | B: E) {}
| ^^^^^ help: wrap the pattern in parenthesis: `(A | B)` | ^^^^^ help: wrap the pattern in parentheses: `(A | B)`
error: a leading `|` is not allowed in a parameter pattern error: an or-pattern parameter must be wrapped in parentheses
--> $DIR/or-patterns-syntactic-fail.rs:19:13 --> $DIR/or-patterns-syntactic-fail.rs:19:13
| |
LL | fn fun2(| A | B: E) {} LL | fn fun2(| A | B: E) {}
| ^ help: remove the `|` | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)`
error: an or-pattern parameter must be wrapped in parenthesis
--> $DIR/or-patterns-syntactic-fail.rs:19:15
|
LL | fn fun2(| A | B: E) {}
| ^^^^^ help: wrap the pattern in parenthesis: `(A | B)`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:30:11
|
LL | let ( | A | B) = E::A;
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:31:11
|
LL | let ( | A | B,) = (E::B,);
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:32:11
|
LL | let [ | A | B ] = [E::A];
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:33:13
|
LL | let TS( | A | B );
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:34:17
|
LL | let NS { f: | A | B };
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:36:11
|
LL | let ( || A | B) = E::A;
| ^^ help: remove the `||`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:37:11
|
LL | let [ || A | B ] = [E::A];
| ^^ help: remove the `||`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:38:13
|
LL | let TS( || A | B );
| ^^ help: remove the `||`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/or-patterns-syntactic-fail.rs:39:17
|
LL | let NS { f: || A | B };
| ^^ help: remove the `||`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error[E0369]: no implementation for `E | ()` error[E0369]: no implementation for `E | ()`
--> $DIR/or-patterns-syntactic-fail.rs:13:22 --> $DIR/or-patterns-syntactic-fail.rs:13:22
@ -88,17 +20,6 @@ LL | let _ = |A | B: E| ();
| |
= note: an implementation of `std::ops::BitOr` might be missing for `E` = note: an implementation of `std::ops::BitOr` might be missing for `E`
error[E0308]: mismatched types error: aborting due to 3 previous errors
--> $DIR/or-patterns-syntactic-fail.rs:41:36
|
LL | let recovery_witness: String = 0;
| ------ ^
| | |
| | expected struct `String`, found integer
| | help: try using a conversion method: `0.to_string()`
| expected due to this
error: aborting due to 14 previous errors For more information about this error, try `rustc --explain E0369`.
Some errors have detailed explanations: E0308, E0369.
For more information about an error, try `rustc --explain E0308`.

View File

@ -9,17 +9,17 @@ fn main() {}
#[cfg(FALSE)] #[cfg(FALSE)]
fn leading() { fn leading() {
fn fun1( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern fn fun1( A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
fn fun2( A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter
let ( A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern let ( | A): E;
let ( A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern let ( | A): (E); //~ ERROR unexpected token `||` in pattern
let ( A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern let ( | A,): (E,);
let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern let [ | A ]: [E; 1];
let [ A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern let [ | A ]: [E; 1]; //~ ERROR unexpected token `||` in pattern
let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern let TS( | A ): TS;
let TS( A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern let TS( | A ): TS; //~ ERROR unexpected token `||` in pattern
let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern let NS { f: | A }: NS;
let NS { f: A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern let NS { f: | A }: NS; //~ ERROR unexpected token `||` in pattern
} }
#[cfg(FALSE)] #[cfg(FALSE)]
@ -29,12 +29,12 @@ fn trailing() {
let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern let ( A | B ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern let [ A | B ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern
let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern let S { f: B }; //~ ERROR a trailing `|` is not allowed in an or-pattern
let ( A | B ): E; //~ ERROR unexpected token `||` after pattern let ( A | B ): E; //~ ERROR unexpected token `||` in pattern
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern
match A { match A {
A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern A => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
A | B => {} //~ ERROR unexpected token `||` after pattern A | B => {} //~ ERROR unexpected token `||` in pattern
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern
| A | B => {} | A | B => {}
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern

View File

@ -9,17 +9,17 @@ fn main() {}
#[cfg(FALSE)] #[cfg(FALSE)]
fn leading() { fn leading() {
fn fun1( | A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern fn fun1( | A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
fn fun2( || A: E) {} //~ ERROR a leading `|` is not allowed in a parameter pattern fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter
let ( | A): E; //~ ERROR a leading `|` is only allowed in a top-level pattern let ( | A): E;
let ( || A): (E); //~ ERROR a leading `|` is only allowed in a top-level pattern let ( || A): (E); //~ ERROR unexpected token `||` in pattern
let ( | A,): (E,); //~ ERROR a leading `|` is only allowed in a top-level pattern let ( | A,): (E,);
let [ | A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern let [ | A ]: [E; 1];
let [ || A ]: [E; 1]; //~ ERROR a leading `|` is only allowed in a top-level pattern let [ || A ]: [E; 1]; //~ ERROR unexpected token `||` in pattern
let TS( | A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern let TS( | A ): TS;
let TS( || A ): TS; //~ ERROR a leading `|` is only allowed in a top-level pattern let TS( || A ): TS; //~ ERROR unexpected token `||` in pattern
let NS { f: | A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern let NS { f: | A }: NS;
let NS { f: || A }: NS; //~ ERROR a leading `|` is only allowed in a top-level pattern let NS { f: || A }: NS; //~ ERROR unexpected token `||` in pattern
} }
#[cfg(FALSE)] #[cfg(FALSE)]
@ -29,12 +29,12 @@ fn trailing() {
let ( A | B | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern let ( A | B | ): E; //~ ERROR a trailing `|` is not allowed in an or-pattern
let [ A | B | ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern let [ A | B | ]: [E; 1]; //~ ERROR a trailing `|` is not allowed in an or-pattern
let S { f: B | }; //~ ERROR a trailing `|` is not allowed in an or-pattern let S { f: B | }; //~ ERROR a trailing `|` is not allowed in an or-pattern
let ( A || B | ): E; //~ ERROR unexpected token `||` after pattern let ( A || B | ): E; //~ ERROR unexpected token `||` in pattern
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern
match A { match A {
A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern A | => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern A || => {} //~ ERROR a trailing `|` is not allowed in an or-pattern
A || B | => {} //~ ERROR unexpected token `||` after pattern A || B | => {} //~ ERROR unexpected token `||` in pattern
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern
| A | B | => {} | A | B | => {}
//~^ ERROR a trailing `|` is not allowed in an or-pattern //~^ ERROR a trailing `|` is not allowed in an or-pattern

View File

@ -1,10 +1,10 @@
error: a leading `|` is not allowed in a parameter pattern error: an or-pattern parameter must be wrapped in parentheses
--> $DIR/remove-leading-vert.rs:12:14 --> $DIR/remove-leading-vert.rs:12:14
| |
LL | fn fun1( | A: E) {} LL | fn fun1( | A: E) {}
| ^ help: remove the `|` | ^^^ help: remove the leading `|`: `A`
error: a leading `|` is not allowed in a parameter pattern error: unexpected `||` before function parameter
--> $DIR/remove-leading-vert.rs:13:14 --> $DIR/remove-leading-vert.rs:13:14
| |
LL | fn fun2( || A: E) {} LL | fn fun2( || A: E) {}
@ -12,67 +12,29 @@ LL | fn fun2( || A: E) {}
| |
= note: alternatives in or-patterns are separated with `|`, not `||` = note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:14:11
|
LL | let ( | A): E;
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/remove-leading-vert.rs:15:11 --> $DIR/remove-leading-vert.rs:15:11
| |
LL | let ( || A): (E); LL | let ( || A): (E);
| ^^ help: remove the `||` | ^^ help: use a single `|` to separate multiple alternative patterns: `|`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:16:11
|
LL | let ( | A,): (E,);
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/remove-leading-vert.rs:17:11
|
LL | let [ | A ]: [E; 1];
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/remove-leading-vert.rs:18:11 --> $DIR/remove-leading-vert.rs:18:11
| |
LL | let [ || A ]: [E; 1]; LL | let [ || A ]: [E; 1];
| ^^ help: remove the `||` | ^^ help: use a single `|` to separate multiple alternative patterns: `|`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:19:13
|
LL | let TS( | A ): TS;
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/remove-leading-vert.rs:20:13 --> $DIR/remove-leading-vert.rs:20:13
| |
LL | let TS( || A ): TS; LL | let TS( || A ): TS;
| ^^ help: remove the `||` | ^^ help: use a single `|` to separate multiple alternative patterns: `|`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a leading `|` is only allowed in a top-level pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:21:17
|
LL | let NS { f: | A }: NS;
| ^ help: remove the `|`
error: a leading `|` is only allowed in a top-level pattern
--> $DIR/remove-leading-vert.rs:22:17 --> $DIR/remove-leading-vert.rs:22:17
| |
LL | let NS { f: || A }: NS; LL | let NS { f: || A }: NS;
| ^^ help: remove the `||` | ^^ help: use a single `|` to separate multiple alternative patterns: `|`
|
= note: alternatives in or-patterns are separated with `|`, not `||`
error: a trailing `|` is not allowed in an or-pattern error: a trailing `|` is not allowed in an or-pattern
--> $DIR/remove-leading-vert.rs:27:13 --> $DIR/remove-leading-vert.rs:27:13
@ -114,7 +76,7 @@ LL | let S { f: B | };
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:32:13 --> $DIR/remove-leading-vert.rs:32:13
| |
LL | let ( A || B | ): E; LL | let ( A || B | ): E;
@ -148,7 +110,7 @@ LL | A || => {}
| |
= note: alternatives in or-patterns are separated with `|`, not `||` = note: alternatives in or-patterns are separated with `|`, not `||`
error: unexpected token `||` after pattern error: unexpected token `||` in pattern
--> $DIR/remove-leading-vert.rs:37:11 --> $DIR/remove-leading-vert.rs:37:11
| |
LL | A || B | => {} LL | A || B | => {}
@ -196,5 +158,5 @@ LL | let a | ;
| | | |
| while parsing this or-pattern starting here | while parsing this or-pattern starting here
error: aborting due to 26 previous errors error: aborting due to 21 previous errors