diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index b611aebad01b0..335ceb775e85a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -847,7 +847,7 @@ impl EarlyLintPass for UnusedParens { fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { if let StmtKind::Local(ref local) = s.kind { - self.check_unused_parens_pat(cx, &local.pat, false, false); + self.check_unused_parens_pat(cx, &local.pat, true, false); } ::check_stmt(self, cx, s) diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 9668a24bf8ab6..a28595e6fae67 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1757,8 +1757,9 @@ impl<'a> Parser<'a> { let (pat, ty) = if is_name_required || this.is_named_param() { debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required); - let pat = this.parse_fn_param_pat()?; - if let Err(mut err) = this.expect(&token::Colon) { + let (pat, colon) = this.parse_fn_param_pat_colon()?; + if !colon { + let mut err = this.unexpected::<()>().unwrap_err(); return if let Some(ident) = this.parameter_without_type(&mut err, pat, is_name_required, first_param) { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 9e2e7359ca96e..5a68afdfa59f7 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -31,6 +31,18 @@ pub enum RecoverComma { No, } +/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid +/// emitting duplicate diagnostics. +#[derive(Debug, Clone, Copy)] +enum EatOrResult { + /// We recovered from a trailing vert. + TrailingVert, + /// We ate an `|` (or `||` and recovered). + AteOr, + /// We did not eat anything (i.e. the current token is not `|` or `||`). + None, +} + impl<'a> Parser<'a> { /// Parses a pattern. /// @@ -55,9 +67,26 @@ impl<'a> Parser<'a> { gate_or: GateOr, rc: RecoverComma, ) -> PResult<'a, P> { + self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat) + } + + /// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true = + /// recovered). + fn parse_pat_allow_top_alt_inner( + &mut self, + expected: Expected, + gate_or: GateOr, + rc: RecoverComma, + ) -> PResult<'a, (P, bool)> { + // Keep track of whether we recovered from a trailing vert so that we can avoid duplicated + // suggestions (which bothers rustfix). + // // 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 }; + let (leading_vert_span, mut trailing_vert) = match self.eat_or_separator(None) { + EatOrResult::AteOr => (Some(self.prev_token.span), false), + EatOrResult::TrailingVert => (None, true), + EatOrResult::None => (None, false), + }; // Parse the first pattern (`p_0`). let first_pat = self.parse_pat_no_top_alt(expected)?; @@ -77,16 +106,24 @@ impl<'a> Parser<'a> { // 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((self.mk_pat(span, PatKind::Or(vec![first_pat])), trailing_vert)); } - return Ok(first_pat); + return Ok((first_pat, trailing_vert)); } // Parse the patterns `p_1 | ... | p_n` where `n > 0`. let lo = leading_vert_span.unwrap_or(first_pat.span); let mut pats = vec![first_pat]; - while self.eat_or_separator(Some(lo)) { + loop { + match self.eat_or_separator(Some(lo)) { + EatOrResult::AteOr => {} + EatOrResult::None => break, + EatOrResult::TrailingVert => { + trailing_vert = true; + break; + } + } let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| { err.span_label(lo, WHILE_PARSING_OR_MSG); err @@ -101,15 +138,63 @@ impl<'a> Parser<'a> { self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span); } - Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats))) + Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert)) } - /// Parse the pattern for a function or function pointer parameter. - pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P> { - // 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. - // + /// Parse a pattern and (maybe) a `Colon` in positions where a pattern may be followed by a + /// type annotation (e.g. for `let` bindings or `fn` params). + /// + /// Generally, this corresponds to `pat_no_top_alt` followed by an optional `Colon`. It will + /// eat the `Colon` token if one is present. + /// + /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false` + /// otherwise). + pub(super) fn parse_pat_before_ty( + &mut self, + expected: Expected, + gate_or: GateOr, + rc: RecoverComma, + syntax_loc: &str, + ) -> PResult<'a, (P, bool)> { + // We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level + // or-patterns so that we can detect when a user tries to use it. This allows us to print a + // better error message. + let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, gate_or, rc)?; + let colon = self.eat(&token::Colon); + + if let PatKind::Or(pats) = &pat.kind { + let msg = format!("top-level or-patterns are not allowed in {}", syntax_loc); + let (help, fix) = if pats.len() == 1 { + // If all we have is 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 = "remove the `|`"; + let fix = pprust::pat_to_string(&pat); + (msg, fix) + } else { + let msg = "wrap the pattern in parentheses"; + let fix = format!("({})", pprust::pat_to_string(&pat)); + (msg, fix) + }; + + if trailing_vert { + // We already emitted an error and suggestion to remove the trailing vert. Don't + // emit again. + self.sess.span_diagnostic.delay_span_bug(pat.span, &msg); + } else { + self.struct_span_err(pat.span, &msg) + .span_suggestion(pat.span, help, fix, Applicability::MachineApplicable) + .emit(); + } + } + + Ok((pat, colon)) + } + + /// Parse the pattern for a function or function pointer parameter, followed by a colon. + /// + /// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false` + /// otherwise). + pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (P, bool)> { // 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 @@ -128,53 +213,28 @@ impl<'a> Parser<'a> { 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(); + self.parse_pat_before_ty( + PARAM_EXPECTED, + GateOr::No, + RecoverComma::No, + "function parameters", + ) } /// Eat the or-pattern `|` separator. /// If instead a `||` token is encountered, recover and pretend we parsed `|`. - fn eat_or_separator(&mut self, lo: Option) -> bool { + fn eat_or_separator(&mut self, lo: Option) -> EatOrResult { if self.recover_trailing_vert(lo) { - return false; - } - - match self.token.kind { - token::OrOr => { - // Found `||`; Recover and pretend we parsed `|`. - self.ban_unexpected_or_or(lo); - self.bump(); - true - } - _ => self.eat(&token::BinOp(token::Or)), + EatOrResult::TrailingVert + } else if matches!(self.token.kind, token::OrOr) { + // Found `||`; Recover and pretend we parsed `|`. + self.ban_unexpected_or_or(lo); + self.bump(); + EatOrResult::AteOr + } else if self.eat(&token::BinOp(token::Or)) { + EatOrResult::AteOr + } else { + EatOrResult::None } } @@ -190,14 +250,14 @@ impl<'a> Parser<'a> { matches!( &token.uninterpolate().kind, token::FatArrow // e.g. `a | => 0,`. - | token::Ident(kw::If, false) // e.g. `a | if expr`. - | token::Eq // e.g. `let a | = 0`. - | token::Semi // e.g. `let a |;`. - | token::Colon // e.g. `let a | :`. - | token::Comma // e.g. `let (a |,)`. - | token::CloseDelim(token::Bracket) // e.g. `let [a | ]`. - | token::CloseDelim(token::Paren) // e.g. `let (a | )`. - | token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`. + | token::Ident(kw::If, false) // e.g. `a | if expr`. + | token::Eq // e.g. `let a | = 0`. + | token::Semi // e.g. `let a |;`. + | token::Colon // e.g. `let a | :`. + | token::Comma // e.g. `let (a |,)`. + | token::CloseDelim(token::Bracket) // e.g. `let [a | ]`. + | token::CloseDelim(token::Paren) // e.g. `let (a | )`. + | token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`. ) }); match (is_end_ahead, &self.token.kind) { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 07746f2390dd9..cabe2b95a49f6 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -13,7 +13,8 @@ use rustc_ast::token::{self, TokenKind}; use rustc_ast::util::classify; use rustc_ast::AstLike; use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle}; -use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID}; +use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt}; +use rustc_ast::{StmtKind, DUMMY_NODE_ID}; use rustc_errors::{Applicability, PResult}; use rustc_span::source_map::{BytePos, Span}; use rustc_span::symbol::{kw, sym}; @@ -220,9 +221,10 @@ impl<'a> Parser<'a> { /// Parses a local variable declaration. fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P> { let lo = self.prev_token.span; - let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?; + let (pat, colon) = + self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?; - let (err, ty) = if self.eat(&token::Colon) { + let (err, ty) = if colon { // Save the state of the parser before parsing type normally, in case there is a `:` // instead of an `=` typo. let parser_snapshot_before_type = self.clone(); diff --git a/src/test/ui/or-patterns/already-bound-name.rs b/src/test/ui/or-patterns/already-bound-name.rs index 726e17b7ec226..543d7c21c8317 100644 --- a/src/test/ui/or-patterns/already-bound-name.rs +++ b/src/test/ui/or-patterns/already-bound-name.rs @@ -18,10 +18,10 @@ fn main() { let (A(a, _) | B(a), a) = (A(0, 1), 2); //~^ ERROR identifier `a` is bound more than once in the same pattern - let A(a, a) | B(a) = A(0, 1); + let (A(a, a) | B(a)) = A(0, 1); //~^ ERROR identifier `a` is bound more than once in the same pattern - let B(a) | A(a, a) = A(0, 1); + let (B(a) | A(a, a)) = A(0, 1); //~^ ERROR identifier `a` is bound more than once in the same pattern match A(0, 1) { @@ -29,17 +29,17 @@ fn main() { //~^ ERROR identifier `a` is bound more than once in the same pattern } - let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); + let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern //~| ERROR mismatched types - let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern //~| ERROR variable `a` is not bound in all patterns - let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); + let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); //~^ ERROR identifier `a` is bound more than once in the same pattern //~| ERROR identifier `a` is bound more than once in the same pattern } diff --git a/src/test/ui/or-patterns/already-bound-name.stderr b/src/test/ui/or-patterns/already-bound-name.stderr index 97933ca122944..483154a5e3274 100644 --- a/src/test/ui/or-patterns/already-bound-name.stderr +++ b/src/test/ui/or-patterns/already-bound-name.stderr @@ -23,16 +23,16 @@ LL | let (A(a, _) | B(a), a) = (A(0, 1), 2); | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:21:14 + --> $DIR/already-bound-name.rs:21:15 | -LL | let A(a, a) | B(a) = A(0, 1); - | ^ used in a pattern more than once +LL | let (A(a, a) | B(a)) = A(0, 1); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:24:21 + --> $DIR/already-bound-name.rs:24:22 | -LL | let B(a) | A(a, a) = A(0, 1); - | ^ used in a pattern more than once +LL | let (B(a) | A(a, a)) = A(0, 1); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern --> $DIR/already-bound-name.rs:28:21 @@ -41,55 +41,55 @@ LL | B(a) | A(a, a) => {} // Let's ensure `match` has no funny business. | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:36 + --> $DIR/already-bound-name.rs:32:37 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:32:46 + --> $DIR/already-bound-name.rs:32:47 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:36 + --> $DIR/already-bound-name.rs:37:37 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:37:46 + --> $DIR/already-bound-name.rs:37:47 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0408]: variable `a` is not bound in all patterns - --> $DIR/already-bound-name.rs:37:9 + --> $DIR/already-bound-name.rs:37:10 | -LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^^^^ pattern doesn't bind `a` - variable not in all patterns +LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^^^^ pattern doesn't bind `a` - variable not in all patterns error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:49 + --> $DIR/already-bound-name.rs:42:50 | -LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0416]: identifier `a` is bound more than once in the same pattern - --> $DIR/already-bound-name.rs:42:59 + --> $DIR/already-bound-name.rs:42:60 | -LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1)); - | ^ used in a pattern more than once +LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1)); + | ^ used in a pattern more than once error[E0308]: mismatched types - --> $DIR/already-bound-name.rs:32:31 + --> $DIR/already-bound-name.rs:32:32 | -LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1)); - | - ^ ------- this expression has type `E>` - | | | - | | expected integer, found enum `E` - | first introduced with type `{integer}` here +LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1)); + | - ^ ------- this expression has type `E>` + | | | + | | expected integer, found enum `E` + | first introduced with type `{integer}` here | = note: expected type `{integer}` found type `E<{integer}>` diff --git a/src/test/ui/or-patterns/consistent-bindings.rs b/src/test/ui/or-patterns/consistent-bindings.rs index 3ee57978bb009..853ddcf241232 100644 --- a/src/test/ui/or-patterns/consistent-bindings.rs +++ b/src/test/ui/or-patterns/consistent-bindings.rs @@ -8,9 +8,9 @@ fn main() { // One level: - let Ok(a) | Err(a) = Ok(0); - let Ok(ref a) | Err(ref a) = Ok(0); - let Ok(ref mut a) | Err(ref mut a) = Ok(0); + let (Ok(a) | Err(a)) = Ok(0); + let (Ok(ref a) | Err(ref a)) = Ok(0); + let (Ok(ref mut a) | Err(ref mut a)) = Ok(0); // Two levels: enum Tri { @@ -20,10 +20,10 @@ fn main() { } use Tri::*; - let Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b))): Result<_, Result<_, _>> = + let (Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b)))): Result<_, Result<_, _>> = Ok((V1(1), 1)); - let Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b))): Result< + let (Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b)))): Result< _, Result<_, _>, > = Ok((V1(1), 1)); diff --git a/src/test/ui/or-patterns/const-fn.rs b/src/test/ui/or-patterns/const-fn.rs index f4af2f0d2dd40..55c6f60915fa8 100644 --- a/src/test/ui/or-patterns/const-fn.rs +++ b/src/test/ui/or-patterns/const-fn.rs @@ -3,28 +3,28 @@ const fn foo((Ok(a) | Err(a)): Result) { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; } const X: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; static Y: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; static mut Z: () = { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; }; fn main() { let _: [(); { let x = Ok(3); - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; 2 }]; } diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs index a4ea4e25d861e..6c592550ec257 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs @@ -5,4 +5,5 @@ fn main() {} #[cfg(FALSE)] fn gated_leading_vert_in_let() { let | A; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed } diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr index 499f60dd545ff..d556532cd6ad8 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr @@ -1,3 +1,9 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 + | +LL | let | A; + | ^^^ help: remove the `|`: `A` + error[E0658]: or-patterns syntax is experimental --> $DIR/feature-gate-or_patterns-leading-let.rs:7:9 | @@ -7,6 +13,6 @@ LL | let | A; = note: see issue #54883 for more information = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to previous error +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.rs b/src/test/ui/or-patterns/feature-gate-or_patterns.rs index e638838147a4d..8bb45e606be96 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.rs +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.rs @@ -26,7 +26,9 @@ fn or_patterns() { // Gated: let | A | B; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed let A | B; //~ ERROR or-patterns syntax is experimental + //~^ ERROR top-level or-patterns are not allowed for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental for A | B in 0 {} //~ ERROR or-patterns syntax is experimental fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental diff --git a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr index c01d17c0b3d7e..7988af5b94213 100644 --- a/src/test/ui/or-patterns/feature-gate-or_patterns.stderr +++ b/src/test/ui/or-patterns/feature-gate-or_patterns.stderr @@ -1,3 +1,15 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns.rs:28:9 + | +LL | let | A | B; + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/feature-gate-or_patterns.rs:30:9 + | +LL | let A | B; + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + error[E0658]: or-patterns syntax is experimental --> $DIR/feature-gate-or_patterns.rs:5:14 | @@ -17,7 +29,7 @@ LL | let | A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:29:9 + --> $DIR/feature-gate-or_patterns.rs:30:9 | LL | let A | B; | ^^^^^ @@ -26,7 +38,7 @@ LL | let A | B; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:30:9 + --> $DIR/feature-gate-or_patterns.rs:32:9 | LL | for | A | B in 0 {} | ^^^^^^^ @@ -35,7 +47,7 @@ LL | for | A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:31:9 + --> $DIR/feature-gate-or_patterns.rs:33:9 | LL | for A | B in 0 {} | ^^^^^ @@ -44,7 +56,7 @@ LL | for A | B in 0 {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:32:13 + --> $DIR/feature-gate-or_patterns.rs:34:13 | LL | fn fun((A | B): _) {} | ^^^^^ @@ -53,7 +65,7 @@ LL | fn fun((A | B): _) {} = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:33:15 + --> $DIR/feature-gate-or_patterns.rs:35:15 | LL | let _ = |(A | B): u8| (); | ^^^^^ @@ -62,7 +74,7 @@ LL | let _ = |(A | B): u8| (); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:34:10 + --> $DIR/feature-gate-or_patterns.rs:36:10 | LL | let (A | B); | ^^^^^ @@ -71,7 +83,7 @@ LL | let (A | B); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:35:10 + --> $DIR/feature-gate-or_patterns.rs:37:10 | LL | let (A | B,); | ^^^^^ @@ -80,7 +92,7 @@ LL | let (A | B,); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:36:11 + --> $DIR/feature-gate-or_patterns.rs:38:11 | LL | let A(B | C); | ^^^^^ @@ -89,7 +101,7 @@ LL | let A(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:37:14 + --> $DIR/feature-gate-or_patterns.rs:39:14 | LL | let E::V(B | C); | ^^^^^ @@ -98,7 +110,7 @@ LL | let E::V(B | C); = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:38:17 + --> $DIR/feature-gate-or_patterns.rs:40:17 | LL | let S { f1: B | C, f2 }; | ^^^^^ @@ -107,7 +119,7 @@ LL | let S { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:39:20 + --> $DIR/feature-gate-or_patterns.rs:41:20 | LL | let E::V { f1: B | C, f2 }; | ^^^^^ @@ -116,7 +128,7 @@ LL | let E::V { f1: B | C, f2 }; = help: add `#![feature(or_patterns)]` to the crate attributes to enable error[E0658]: or-patterns syntax is experimental - --> $DIR/feature-gate-or_patterns.rs:40:10 + --> $DIR/feature-gate-or_patterns.rs:42:10 | LL | let [A | B]; | ^^^^^ @@ -169,6 +181,6 @@ LL | accept_pat!([p | q]); = note: see issue #54883 for more information = help: add `#![feature(or_patterns)]` to the crate attributes to enable -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed index bbc75d2b411eb..65e04325e16bd 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.fixed +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.fixed @@ -11,4 +11,4 @@ enum E { A, B } use E::*; #[cfg(FALSE)] -fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses +fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.rs b/src/test/ui/or-patterns/fn-param-wrap-parens.rs index 65b93dcbf7467..aeb4a05ea808e 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.rs +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.rs @@ -11,4 +11,4 @@ enum E { A, B } use E::*; #[cfg(FALSE)] -fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses +fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed diff --git a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr index 0e6424a430043..96193c17ae23f 100644 --- a/src/test/ui/or-patterns/fn-param-wrap-parens.stderr +++ b/src/test/ui/or-patterns/fn-param-wrap-parens.stderr @@ -1,4 +1,4 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/fn-param-wrap-parens.rs:14:9 | LL | fn fun1(A | B: E) {} diff --git a/src/test/ui/or-patterns/inconsistent-modes.rs b/src/test/ui/or-patterns/inconsistent-modes.rs index fd5cb01ab42c5..2300e9f9f3b7b 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.rs +++ b/src/test/ui/or-patterns/inconsistent-modes.rs @@ -4,23 +4,23 @@ #![allow(non_camel_case_types)] fn main() { // One level: - let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); + let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); //~^ ERROR variable `a` is bound inconsistently - let Ok(ref mut a) | Err(a): Result = Ok(0); + let (Ok(ref mut a) | Err(a)): Result = Ok(0); //~^ ERROR variable `a` is bound inconsistently - let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); + let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); //~^ ERROR variable `a` is bound inconsistently //~| ERROR mismatched types - let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); + let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); //~^ ERROR variable `a` is bound inconsistently //~| ERROR variable `b` is bound inconsistently //~| ERROR mismatched types // Two levels: - let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); + let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); //~^ ERROR variable `a` is bound inconsistently // Three levels: - let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); + let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); //~^ ERROR variable `a` is bound inconsistently } diff --git a/src/test/ui/or-patterns/inconsistent-modes.stderr b/src/test/ui/or-patterns/inconsistent-modes.stderr index 15790771043df..99791431eaf25 100644 --- a/src/test/ui/or-patterns/inconsistent-modes.stderr +++ b/src/test/ui/or-patterns/inconsistent-modes.stderr @@ -1,74 +1,74 @@ error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:7:25 + --> $DIR/inconsistent-modes.rs:7:26 | -LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:9:29 + --> $DIR/inconsistent-modes.rs:9:30 | -LL | let Ok(ref mut a) | Err(a): Result = Ok(0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(ref mut a) | Err(a)): Result = Ok(0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:11:33 + --> $DIR/inconsistent-modes.rs:11:34 | -LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); - | - first binding ^ bound in different ways +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:39 + --> $DIR/inconsistent-modes.rs:14:40 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | - first binding ^ bound in different ways +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:14:46 + --> $DIR/inconsistent-modes.rs:14:47 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | - first binding ^ bound in different ways +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | - first binding ^ bound in different ways error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:20:38 + --> $DIR/inconsistent-modes.rs:20:39 | -LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0); + | - ^ bound in different ways + | | + | first binding error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|` - --> $DIR/inconsistent-modes.rs:24:33 + --> $DIR/inconsistent-modes.rs:24:34 | -LL | let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1); - | - ^ bound in different ways - | | - | first binding +LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1); + | - ^ bound in different ways + | | + | first binding error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:11:25 + --> $DIR/inconsistent-modes.rs:11:26 | -LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0); - | ----- ^^^^^^^^^ -------------------- expected due to this - | | | - | | types differ in mutability - | first introduced with type `&&u8` here +LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0); + | ----- ^^^^^^^^^ -------------------- expected due to this + | | | + | | types differ in mutability + | first introduced with type `&&u8` here | = note: expected type `&&u8` found type `&mut &mut u8` = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/inconsistent-modes.rs:14:31 + --> $DIR/inconsistent-modes.rs:14:32 | -LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0)); - | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` - | | | - | | types differ in mutability - | first introduced with type `&{integer}` here +LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0)); + | ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>` + | | | + | | types differ in mutability + | first introduced with type `&{integer}` here | = note: expected type `&{integer}` found type `&mut _` diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs index 59533cefea64c..8e83acc6dcbc0 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs @@ -1,7 +1,7 @@ #![feature(or_patterns)] fn main() { - let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding + let (0 | (1 | 2)) = 0; //~ ERROR refutable pattern in local binding match 0 { //~^ ERROR non-exhaustive patterns 0 | (1 | 2) => {} diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr index 2acf1f41c6fa6..9ed942d9e0fd5 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr @@ -1,16 +1,16 @@ error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered - --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9 + --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:10 | -LL | let 0 | (1 | 2) = 0; - | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered +LL | let (0 | (1 | 2)) = 0; + | ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered | = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html = note: the matched value is of type `i32` help: you might want to use `if let` to ignore the variant that isn't matched | -LL | if let 0 | (1 | 2) = 0 { /* */ } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | if let (0 | (1 | 2)) = 0 { /* */ } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11 diff --git a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs index 1de563dedbf18..2f080ebf7830b 100644 --- a/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs +++ b/src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs @@ -3,7 +3,7 @@ #![feature(or_patterns)] fn main() { - let 0 | (1 | _) = 0; + let (0 | (1 | _)) = 0; if let 0 | (1 | 2) = 0 {} if let x @ 0 | x @ (1 | 2) = 0 {} } diff --git a/src/test/ui/or-patterns/let-pattern.rs b/src/test/ui/or-patterns/let-pattern.rs index 07e37412ce842..7f22aa9d9f980 100644 --- a/src/test/ui/or-patterns/let-pattern.rs +++ b/src/test/ui/or-patterns/let-pattern.rs @@ -3,7 +3,7 @@ // run-pass fn or_pat_let(x: Result) -> u32 { - let Ok(y) | Err(y) = x; + let (Ok(y) | Err(y)) = x; y } diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs index 5c5c68f81d1f2..cf98a472106e8 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.rs @@ -8,7 +8,7 @@ async fn a((x | s): String) {} //~| ERROR variable `s` is not bound in all patterns async fn b() { - let x | s = String::new(); + let (x | s) = String::new(); //~^ ERROR variable `x` is not bound in all patterns //~| ERROR variable `s` is not bound in all patterns } diff --git a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr index 998577cf4b5e0..d5c77ee39c99c 100644 --- a/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr +++ b/src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr @@ -15,20 +15,20 @@ LL | async fn a((x | s): String) {} | variable not in all patterns error[E0408]: variable `s` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:9 + --> $DIR/mismatched-bindings-async-fn.rs:11:10 | -LL | let x | s = String::new(); - | ^ - variable not in all patterns - | | - | pattern doesn't bind `s` +LL | let (x | s) = String::new(); + | ^ - variable not in all patterns + | | + | pattern doesn't bind `s` error[E0408]: variable `x` is not bound in all patterns - --> $DIR/mismatched-bindings-async-fn.rs:11:13 + --> $DIR/mismatched-bindings-async-fn.rs:11:14 | -LL | let x | s = String::new(); - | - ^ pattern doesn't bind `x` - | | - | variable not in all patterns +LL | let (x | s) = String::new(); + | - ^ pattern doesn't bind `x` + | | + | variable not in all patterns error: aborting due to 4 previous errors diff --git a/src/test/ui/or-patterns/missing-bindings.rs b/src/test/ui/or-patterns/missing-bindings.rs index 67cf52fa8c418..5dd1f16b65580 100644 --- a/src/test/ui/or-patterns/missing-bindings.rs +++ b/src/test/ui/or-patterns/missing-bindings.rs @@ -17,7 +17,7 @@ fn check_handling_of_paths() { } use bar::foo::{alpha, charlie}; - let alpha | beta | charlie = alpha; //~ ERROR variable `beta` is not bound in all patterns + let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns match Some(alpha) { Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns } @@ -31,19 +31,19 @@ fn check_misc_nesting() { // One level: const X: E = B(0); - let A(a, _) | _ = X; //~ ERROR variable `a` is not bound in all patterns - let _ | B(a) = X; //~ ERROR variable `a` is not bound in all patterns - let A(..) | B(a) = X; //~ ERROR variable `a` is not bound in all patterns - let A(a, _) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns - let A(_, a) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns - let A(a, b) | B(a) = X; //~ ERROR variable `b` is not bound in all patterns + let (A(a, _) | _) = X; //~ ERROR variable `a` is not bound in all patterns + let (_ | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(..) | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, _) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(_, a) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns + let (A(a, b) | B(a)) = X; //~ ERROR variable `b` is not bound in all patterns // Two levels: const Y: E> = B(B(0)); - let A(A(..) | B(_), _) | B(a) = Y; //~ ERROR variable `a` is not bound in all patterns - let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; + let (A(A(..) | B(_), _) | B(a)) = Y; //~ ERROR variable `a` is not bound in all patterns + let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; //~^ ERROR variable `a` is not bound in all patterns - let A(A(a, b) | B(c), d) | B(e) = Y; + let (A(A(a, b) | B(c), d) | B(e)) = Y; //~^ ERROR variable `a` is not bound in all patterns //~| ERROR variable `a` is not bound in all patterns //~| ERROR variable `b` is not bound in all patterns diff --git a/src/test/ui/or-patterns/missing-bindings.stderr b/src/test/ui/or-patterns/missing-bindings.stderr index 57270e4412351..4702bc6bbf322 100644 --- a/src/test/ui/or-patterns/missing-bindings.stderr +++ b/src/test/ui/or-patterns/missing-bindings.stderr @@ -1,11 +1,11 @@ error[E0408]: variable `beta` is not bound in all patterns - --> $DIR/missing-bindings.rs:20:9 + --> $DIR/missing-bindings.rs:20:10 | -LL | let alpha | beta | charlie = alpha; - | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` - | | | - | | variable not in all patterns - | pattern doesn't bind `beta` +LL | let (alpha | beta | charlie) = alpha; + | ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta` + | | | + | | variable not in all patterns + | pattern doesn't bind `beta` error[E0408]: variable `beta` is not bound in all patterns --> $DIR/missing-bindings.rs:22:14 @@ -16,132 +16,132 @@ LL | Some(alpha | beta) => {} | pattern doesn't bind `beta` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:34:19 + --> $DIR/missing-bindings.rs:34:20 | -LL | let A(a, _) | _ = X; - | - ^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(a, _) | _) = X; + | - ^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:35:9 + --> $DIR/missing-bindings.rs:35:10 | -LL | let _ | B(a) = X; - | ^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (_ | B(a)) = X; + | ^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:36:9 + --> $DIR/missing-bindings.rs:36:10 | -LL | let A(..) | B(a) = X; - | ^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(..) | B(a)) = X; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:37:19 + --> $DIR/missing-bindings.rs:37:20 | -LL | let A(a, _) | B(_) = X; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(a, _) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:38:19 + --> $DIR/missing-bindings.rs:38:20 | -LL | let A(_, a) | B(_) = X; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(_, a) | B(_)) = X; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:39:19 + --> $DIR/missing-bindings.rs:39:20 | -LL | let A(a, b) | B(a) = X; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(a, b) | B(a)) = X; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:43:9 + --> $DIR/missing-bindings.rs:43:10 | -LL | let A(A(..) | B(_), _) | B(a) = Y; - | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(A(..) | B(_), _) | B(a)) = Y; + | ^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:44:11 + --> $DIR/missing-bindings.rs:44:12 | -LL | let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y; - | ^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `a` +LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y; + | ^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `a` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:21 + --> $DIR/missing-bindings.rs:46:22 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:21 + --> $DIR/missing-bindings.rs:46:22 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:11 + --> $DIR/missing-bindings.rs:46:12 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | ^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `c` +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `c` error[E0408]: variable `a` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `a` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `a` + | | + | variable not in all patterns error[E0408]: variable `b` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `b` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `b` + | | + | variable not in all patterns error[E0408]: variable `c` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `c` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `c` + | | + | variable not in all patterns error[E0408]: variable `d` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:32 + --> $DIR/missing-bindings.rs:46:33 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | - ^^^^ pattern doesn't bind `d` - | | - | variable not in all patterns +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | - ^^^^ pattern doesn't bind `d` + | | + | variable not in all patterns error[E0408]: variable `e` is not bound in all patterns - --> $DIR/missing-bindings.rs:46:9 + --> $DIR/missing-bindings.rs:46:10 | -LL | let A(A(a, b) | B(c), d) | B(e) = Y; - | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns - | | - | pattern doesn't bind `e` +LL | let (A(A(a, b) | B(c), d) | B(e)) = Y; + | ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns + | | + | pattern doesn't bind `e` error[E0408]: variable `a` is not bound in all patterns --> $DIR/missing-bindings.rs:62:29 diff --git a/src/test/ui/or-patterns/nested-undelimited-precedence.rs b/src/test/ui/or-patterns/nested-undelimited-precedence.rs new file mode 100644 index 0000000000000..208662b1c425d --- /dev/null +++ b/src/test/ui/or-patterns/nested-undelimited-precedence.rs @@ -0,0 +1,46 @@ +// This test tests the precedence of `|` (or-patterns) undelimited nested patterns. In particular, +// we want to reserve the syntactic space of a pattern followed by a type annotation for possible +// future type ascription, so we need to make sure that any time a pattern is followed by type +// annotation (for now), the pattern is not a top-level or-pattern. However, there are also a few +// types of patterns that allow undelimited subpatterns that could cause the same ambiguity. +// Currently, those should be impossible due to precedence rule. This test enforces that. + +#![feature(or_patterns)] + +enum E { + A, + B, +} + +fn foo() { + use E::*; + + // ok + let b @ (A | B): E = A; + + let b @ A | B: E = A; //~ERROR `b` is not bound in all patterns + //~^ ERROR top-level or-patterns are not allowed +} + +enum F { + A(usize), + B(usize), +} + +fn bar() { + use F::*; + + // ok + let (A(x) | B(x)): F = A(3); + + let &A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed + let &&mut A(_) | B(_): F = A(3); //~ERROR mismatched types + //~^ ERROR top-level or-patterns are not allowed +} + +fn main() {} diff --git a/src/test/ui/or-patterns/nested-undelimited-precedence.stderr b/src/test/ui/or-patterns/nested-undelimited-precedence.stderr new file mode 100644 index 0000000000000..1d78d5193cb88 --- /dev/null +++ b/src/test/ui/or-patterns/nested-undelimited-precedence.stderr @@ -0,0 +1,86 @@ +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:21:9 + | +LL | let b @ A | B: E = A; + | ^^^^^^^^^ help: wrap the pattern in parentheses: `(b @ A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&mut A(_) | B(_))` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/nested-undelimited-precedence.rs:42:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&mut A(_) | B(_))` + +error[E0408]: variable `b` is not bound in all patterns + --> $DIR/nested-undelimited-precedence.rs:21:17 + | +LL | let b @ A | B: E = A; + | - ^ pattern doesn't bind `b` + | | + | variable not in all patterns + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:36:9 + | +LL | let &A(_) | B(_): F = A(3); + | ^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:38:9 + | +LL | let &&A(_) | B(_): F = A(3); + | ^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:40:9 + | +LL | let &mut A(_) | B(_): F = A(3); + | ^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found `&mut _` + | + = note: expected enum `F` + found mutable reference `&mut _` + +error[E0308]: mismatched types + --> $DIR/nested-undelimited-precedence.rs:42:9 + | +LL | let &&mut A(_) | B(_): F = A(3); + | ^^^^^^^^^^ - expected due to this + | | + | expected enum `F`, found reference + | + = note: expected enum `F` + found reference `&_` + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0308, E0408. +For more information about an error, try `rustc --explain E0308`. diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs index 5ec7dc6962c18..11c8a7b69f948 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs @@ -52,10 +52,10 @@ fn main() { = Some((0u8, Some((1u16, 2u32)))) {} - let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); + let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); //~^ ERROR mismatched types - let (x, y) | (y, x) = (0u8, 1u16); + let ((x, y) | (y, x)) = (0u8, 1u16); //~^ ERROR mismatched types //~| ERROR mismatched types diff --git a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr index 00dba053a59d3..26e14b539dbf2 100644 --- a/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr +++ b/src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr @@ -187,35 +187,35 @@ LL | = Some((0u8, Some((1u16, 2u32)))) = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:55:39 + --> $DIR/or-patterns-binding-type-mismatch.rs:55:40 | -LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2); - | - ^ ---------------- this expression has type `Blah` - | | | - | | expected `usize`, found `isize` - | first introduced with type `usize` here +LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2); + | - ^ ---------------- this expression has type `Blah` + | | | + | | expected `usize`, found `isize` + | first introduced with type `usize` here | = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:19 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:20 | -LL | let (x, y) | (y, x) = (0u8, 1u16); - | - ^ ----------- this expression has type `(u8, u16)` - | | | - | | expected `u16`, found `u8` - | first introduced with type `u16` here +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u16`, found `u8` + | first introduced with type `u16` here | = note: a binding must have the same type in all alternatives error[E0308]: mismatched types - --> $DIR/or-patterns-binding-type-mismatch.rs:58:22 + --> $DIR/or-patterns-binding-type-mismatch.rs:58:23 | -LL | let (x, y) | (y, x) = (0u8, 1u16); - | - ^ ----------- this expression has type `(u8, u16)` - | | | - | | expected `u8`, found `u16` - | first introduced with type `u8` here +LL | let ((x, y) | (y, x)) = (0u8, 1u16); + | - ^ ----------- this expression has type `(u8, u16)` + | | | + | | expected `u8`, found `u16` + | first introduced with type `u8` here | = note: a binding must have the same type in all alternatives diff --git a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs index 3b6047c7be47d..f98b038ae81af 100644 --- a/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs +++ b/src/test/ui/or-patterns/or-patterns-default-binding-modes.rs @@ -37,11 +37,11 @@ fn main() { if let &(Ok(x) | Err(x)) = res { drop::(x); } - let Ok(mut x) | &Err(mut x) = res; + let (Ok(mut x) | &Err(mut x)) = res; drop::(x); let &(Ok(x) | Err(x)) = res; drop::(x); - let Ok(x) | Err(x) = res; + let (Ok(x) | Err(x)) = res; drop::<&u8>(x); for Ok(mut x) | &Err(mut x) in std::iter::once(res) { drop::(x); @@ -119,9 +119,9 @@ fn main() { } let tri = &Tri::A(&Ok(0)); - let Tri::A(Ok(mut x) | Err(mut x)) + let (Tri::A(Ok(mut x) | Err(mut x)) | Tri::B(&Ok(mut x) | Err(mut x)) - | &Tri::C(Ok(mut x) | Err(mut x)) = tri; + | &Tri::C(Ok(mut x) | Err(mut x))) = tri; drop::(x); match tri { diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs index cbc24eb26fa47..27a5374ff1848 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.rs @@ -14,8 +14,19 @@ fn no_top_level_or_patterns() { // -------- 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. - fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1(A | B: E) {} + //~^ ERROR top-level or-patterns are not allowed fn fun2(| A | B: E) {} - //~^ ERROR an or-pattern parameter must be wrapped in parentheses + //~^ ERROR top-level or-patterns are not allowed + + // We don't allow top-level or-patterns before type annotation in let-statements because we + // want to reserve this syntactic space for possible future type ascription. + let A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let | A | B: E = A; + //~^ ERROR top-level or-patterns are not allowed + + let (A | B): E = A; // ok -- wrapped in parens } diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr index db4d827757b03..929b2088f76ce 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr +++ b/src/test/ui/or-patterns/or-patterns-syntactic-fail.stderr @@ -1,15 +1,27 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/or-patterns-syntactic-fail.rs:17:13 | LL | fn fun1(A | B: E) {} | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` -error: an or-pattern parameter must be wrapped in parentheses - --> $DIR/or-patterns-syntactic-fail.rs:19:13 +error: top-level or-patterns are not allowed in function parameters + --> $DIR/or-patterns-syntactic-fail.rs:20:13 | LL | fn fun2(| A | B: E) {} | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:25:9 + | +LL | let A | B: E = A; + | ^^^^^ help: wrap the pattern in parentheses: `(A | B)` + +error: top-level or-patterns are not allowed in `let` bindings + --> $DIR/or-patterns-syntactic-fail.rs:28:9 + | +LL | let | A | B: E = A; + | ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)` + error[E0369]: no implementation for `E | ()` --> $DIR/or-patterns-syntactic-fail.rs:13:22 | @@ -20,6 +32,6 @@ LL | let _ = |A | B: E| (); | = note: an implementation of `std::ops::BitOr` might be missing for `E` -error: aborting due to 3 previous errors +error: aborting due to 5 previous errors For more information about this error, try `rustc --explain E0369`. diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs index 5fe72caf9c1ff..3da238f7b9a45 100644 --- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs +++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs @@ -23,11 +23,11 @@ accept_pat!([p | q]); #[cfg(FALSE)] fn or_patterns() { // Top level of `let`: - let | A | B; - let A | B; - let A | B: u8; - let A | B = 0; - let A | B: u8 = 0; + let (| A | B); + let (A | B); + let (A | B): u8; + let (A | B) = 0; + let (A | B): u8 = 0; // Top level of `for`: for | A | B in 0 {} @@ -69,10 +69,10 @@ fn or_patterns() { let [A | B, .. | ..]; // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`: - let box 0 | 1; // Unstable; we *can* the precedence if we want. - let &0 | 1; - let &mut 0 | 1; - let x @ 0 | 1; - let ref x @ 0 | 1; - let ref mut x @ 0 | 1; + let (box 0 | 1); // Unstable; we *can* change the precedence if we want. + let (&0 | 1); + let (&mut 0 | 1); + let (x @ 0 | 1); + let (ref x @ 0 | 1); + let (ref mut x @ 0 | 1); } diff --git a/src/test/ui/or-patterns/remove-leading-vert.fixed b/src/test/ui/or-patterns/remove-leading-vert.fixed index c8fac4faa2a66..d23858d42d146 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.fixed +++ b/src/test/ui/or-patterns/remove-leading-vert.fixed @@ -9,7 +9,7 @@ fn main() {} #[cfg(FALSE)] fn leading() { - fn fun1( A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter let ( | A): E; let ( | A): (E); //~ ERROR unexpected token `||` in pattern @@ -40,6 +40,9 @@ fn trailing() { //~^ ERROR a trailing `|` is not allowed in an or-pattern } + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/src/test/ui/or-patterns/remove-leading-vert.rs b/src/test/ui/or-patterns/remove-leading-vert.rs index 2cf6b27ab1aac..e753765b3e795 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.rs +++ b/src/test/ui/or-patterns/remove-leading-vert.rs @@ -9,7 +9,7 @@ fn main() {} #[cfg(FALSE)] fn leading() { - fn fun1( | A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses + fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter let ( | A): E; let ( || A): (E); //~ ERROR unexpected token `||` in pattern @@ -40,6 +40,9 @@ fn trailing() { //~^ ERROR a trailing `|` is not allowed in an or-pattern } + // These test trailing-vert in `let` bindings, but they also test that we don't emit a + // duplicate suggestion that would confuse rustfix. + let a | : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a | = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern let a | ; //~ ERROR a trailing `|` is not allowed in an or-pattern diff --git a/src/test/ui/or-patterns/remove-leading-vert.stderr b/src/test/ui/or-patterns/remove-leading-vert.stderr index 5c9efd44a187f..0a2b143288dab 100644 --- a/src/test/ui/or-patterns/remove-leading-vert.stderr +++ b/src/test/ui/or-patterns/remove-leading-vert.stderr @@ -1,8 +1,8 @@ -error: an or-pattern parameter must be wrapped in parentheses +error: top-level or-patterns are not allowed in function parameters --> $DIR/remove-leading-vert.rs:12:14 | LL | fn fun1( | A: E) {} - | ^^^ help: remove the leading `|`: `A` + | ^^^ help: remove the `|`: `A` error: unexpected `||` before function parameter --> $DIR/remove-leading-vert.rs:13:14 @@ -135,7 +135,7 @@ LL | | A | B | => {} | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:43:11 + --> $DIR/remove-leading-vert.rs:46:11 | LL | let a | : u8 = 0; | - ^ help: remove the `|` @@ -143,7 +143,7 @@ LL | let a | : u8 = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:44:11 + --> $DIR/remove-leading-vert.rs:47:11 | LL | let a | = 0; | - ^ help: remove the `|` @@ -151,7 +151,7 @@ LL | let a | = 0; | while parsing this or-pattern starting here error: a trailing `|` is not allowed in an or-pattern - --> $DIR/remove-leading-vert.rs:45:11 + --> $DIR/remove-leading-vert.rs:48:11 | LL | let a | ; | - ^ help: remove the `|` diff --git a/src/tools/clippy/clippy_lints/src/loops.rs b/src/tools/clippy/clippy_lints/src/loops.rs index 1c9373a756c88..a87d5b9d37309 100644 --- a/src/tools/clippy/clippy_lints/src/loops.rs +++ b/src/tools/clippy/clippy_lints/src/loops.rs @@ -885,7 +885,9 @@ struct MinifyingSugg<'a>(Sugg<'a>); impl<'a> MinifyingSugg<'a> { fn as_str(&self) -> &str { - let Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) = &self.0; + let s = match &self.0 { + Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s, + }; s.as_ref() }