Skip to content

Commit 0d97f9b

Browse files
authoredMar 9, 2021
Rollup merge of #82048 - mark-i-m:or-pat-type-ascription, r=petrochenkov
or-patterns: disallow in `let` bindings ~~Blocked on #81869 Disallows top-level or-patterns before type ascription. We want to reserve this syntactic space for possible future generalized type ascription. r? ``@petrochenkov``
·
1.90.01.52.0
2 parents 0083e6c + 402a00a commit 0d97f9b

37 files changed

+591
-344
lines changed
 

‎compiler/rustc_lint/src/unused.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -872,7 +872,7 @@ impl EarlyLintPass for UnusedParens {
872872

873873
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
874874
if let StmtKind::Local(ref local) = s.kind {
875-
self.check_unused_parens_pat(cx, &local.pat, false, false);
875+
self.check_unused_parens_pat(cx, &local.pat, true, false);
876876
}
877877

878878
<Self as UnusedDelimLint>::check_stmt(self, cx, s)

‎compiler/rustc_parse/src/parser/item.rs‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1757,8 +1757,9 @@ impl<'a> Parser<'a> {
17571757
let (pat, ty) = if is_name_required || this.is_named_param() {
17581758
debug!("parse_param_general parse_pat (is_name_required:{})", is_name_required);
17591759

1760-
let pat = this.parse_fn_param_pat()?;
1761-
if let Err(mut err) = this.expect(&token::Colon) {
1760+
let (pat, colon) = this.parse_fn_param_pat_colon()?;
1761+
if !colon {
1762+
let mut err = this.unexpected::<()>().unwrap_err();
17621763
return if let Some(ident) =
17631764
this.parameter_without_type(&mut err, pat, is_name_required, first_param)
17641765
{

‎compiler/rustc_parse/src/parser/pat.rs‎

Lines changed: 122 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,18 @@ pub enum RecoverComma {
3131
No,
3232
}
3333

34+
/// The result of `eat_or_separator`. We want to distinguish which case we are in to avoid
35+
/// emitting duplicate diagnostics.
36+
#[derive(Debug, Clone, Copy)]
37+
enum EatOrResult {
38+
/// We recovered from a trailing vert.
39+
TrailingVert,
40+
/// We ate an `|` (or `||` and recovered).
41+
AteOr,
42+
/// We did not eat anything (i.e. the current token is not `|` or `||`).
43+
None,
44+
}
45+
3446
impl<'a> Parser<'a> {
3547
/// Parses a pattern.
3648
///
@@ -55,9 +67,26 @@ impl<'a> Parser<'a> {
5567
gate_or: GateOr,
5668
rc: RecoverComma,
5769
) -> PResult<'a, P<Pat>> {
70+
self.parse_pat_allow_top_alt_inner(expected, gate_or, rc).map(|(pat, _)| pat)
71+
}
72+
73+
/// Returns the pattern and a bool indicating whether we recovered from a trailing vert (true =
74+
/// recovered).
75+
fn parse_pat_allow_top_alt_inner(
76+
&mut self,
77+
expected: Expected,
78+
gate_or: GateOr,
79+
rc: RecoverComma,
80+
) -> PResult<'a, (P<Pat>, bool)> {
81+
// Keep track of whether we recovered from a trailing vert so that we can avoid duplicated
82+
// suggestions (which bothers rustfix).
83+
//
5884
// Allow a '|' before the pats (RFCs 1925, 2530, and 2535).
59-
let leading_vert_span =
60-
if self.eat_or_separator(None) { Some(self.prev_token.span) } else { None };
85+
let (leading_vert_span, mut trailing_vert) = match self.eat_or_separator(None) {
86+
EatOrResult::AteOr => (Some(self.prev_token.span), false),
87+
EatOrResult::TrailingVert => (None, true),
88+
EatOrResult::None => (None, false),
89+
};
6190

6291
// Parse the first pattern (`p_0`).
6392
let first_pat = self.parse_pat_no_top_alt(expected)?;
@@ -77,16 +106,24 @@ impl<'a> Parser<'a> {
77106
// If there was a leading vert, treat this as an or-pattern. This improves
78107
// diagnostics.
79108
let span = leading_vert_span.to(self.prev_token.span);
80-
return Ok(self.mk_pat(span, PatKind::Or(vec![first_pat])));
109+
return Ok((self.mk_pat(span, PatKind::Or(vec![first_pat])), trailing_vert));
81110
}
82111

83-
return Ok(first_pat);
112+
return Ok((first_pat, trailing_vert));
84113
}
85114

86115
// Parse the patterns `p_1 | ... | p_n` where `n > 0`.
87116
let lo = leading_vert_span.unwrap_or(first_pat.span);
88117
let mut pats = vec![first_pat];
89-
while self.eat_or_separator(Some(lo)) {
118+
loop {
119+
match self.eat_or_separator(Some(lo)) {
120+
EatOrResult::AteOr => {}
121+
EatOrResult::None => break,
122+
EatOrResult::TrailingVert => {
123+
trailing_vert = true;
124+
break;
125+
}
126+
}
90127
let pat = self.parse_pat_no_top_alt(expected).map_err(|mut err| {
91128
err.span_label(lo, WHILE_PARSING_OR_MSG);
92129
err
@@ -101,15 +138,63 @@ impl<'a> Parser<'a> {
101138
self.sess.gated_spans.gate(sym::or_patterns, or_pattern_span);
102139
}
103140

104-
Ok(self.mk_pat(or_pattern_span, PatKind::Or(pats)))
141+
Ok((self.mk_pat(or_pattern_span, PatKind::Or(pats)), trailing_vert))
105142
}
106143

107-
/// Parse the pattern for a function or function pointer parameter.
108-
pub(super) fn parse_fn_param_pat(&mut self) -> PResult<'a, P<Pat>> {
109-
// We actually do _not_ allow top-level or-patterns in function params, but we use
110-
// `parse_pat_allow_top_alt` anyway so that we can detect when a user tries to use it. This
111-
// allows us to print a better error message.
112-
//
144+
/// Parse a pattern and (maybe) a `Colon` in positions where a pattern may be followed by a
145+
/// type annotation (e.g. for `let` bindings or `fn` params).
146+
///
147+
/// Generally, this corresponds to `pat_no_top_alt` followed by an optional `Colon`. It will
148+
/// eat the `Colon` token if one is present.
149+
///
150+
/// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
151+
/// otherwise).
152+
pub(super) fn parse_pat_before_ty(
153+
&mut self,
154+
expected: Expected,
155+
gate_or: GateOr,
156+
rc: RecoverComma,
157+
syntax_loc: &str,
158+
) -> PResult<'a, (P<Pat>, bool)> {
159+
// We use `parse_pat_allow_top_alt` regardless of whether we actually want top-level
160+
// or-patterns so that we can detect when a user tries to use it. This allows us to print a
161+
// better error message.
162+
let (pat, trailing_vert) = self.parse_pat_allow_top_alt_inner(expected, gate_or, rc)?;
163+
let colon = self.eat(&token::Colon);
164+
165+
if let PatKind::Or(pats) = &pat.kind {
166+
let msg = format!("top-level or-patterns are not allowed in {}", syntax_loc);
167+
let (help, fix) = if pats.len() == 1 {
168+
// If all we have is a leading vert, then print a special message. This is the case
169+
// if `parse_pat_allow_top_alt` returns an or-pattern with one variant.
170+
let msg = "remove the `|`";
171+
let fix = pprust::pat_to_string(&pat);
172+
(msg, fix)
173+
} else {
174+
let msg = "wrap the pattern in parentheses";
175+
let fix = format!("({})", pprust::pat_to_string(&pat));
176+
(msg, fix)
177+
};
178+
179+
if trailing_vert {
180+
// We already emitted an error and suggestion to remove the trailing vert. Don't
181+
// emit again.
182+
self.sess.span_diagnostic.delay_span_bug(pat.span, &msg);
183+
} else {
184+
self.struct_span_err(pat.span, &msg)
185+
.span_suggestion(pat.span, help, fix, Applicability::MachineApplicable)
186+
.emit();
187+
}
188+
}
189+
190+
Ok((pat, colon))
191+
}
192+
193+
/// Parse the pattern for a function or function pointer parameter, followed by a colon.
194+
///
195+
/// The return value represents the parsed pattern and `true` if a `Colon` was parsed (`false`
196+
/// otherwise).
197+
pub(super) fn parse_fn_param_pat_colon(&mut self) -> PResult<'a, (P<Pat>, bool)> {
113198
// In order to get good UX, we first recover in the case of a leading vert for an illegal
114199
// top-level or-pat. Normally, this means recovering both `|` and `||`, but in this case,
115200
// a leading `||` probably doesn't indicate an or-pattern attempt, so we handle that
@@ -128,53 +213,28 @@ impl<'a> Parser<'a> {
128213
self.bump();
129214
}
130215

131-
let pat = self.parse_pat_allow_top_alt(PARAM_EXPECTED, GateOr::No, RecoverComma::No)?;
132-
133-
if let PatKind::Or(..) = &pat.kind {
134-
self.ban_illegal_fn_param_or_pat(&pat);
135-
}
136-
137-
Ok(pat)
138-
}
139-
140-
/// Ban `A | B` immediately in a parameter pattern and suggest wrapping in parens.
141-
fn ban_illegal_fn_param_or_pat(&self, pat: &Pat) {
142-
// If all we have a leading vert, then print a special message. This is the case if
143-
// `parse_pat_allow_top_alt` returns an or-pattern with one variant.
144-
let (msg, fix) = match &pat.kind {
145-
PatKind::Or(pats) if pats.len() == 1 => {
146-
let msg = "remove the leading `|`";
147-
let fix = pprust::pat_to_string(pat);
148-
(msg, fix)
149-
}
150-
151-
_ => {
152-
let msg = "wrap the pattern in parentheses";
153-
let fix = format!("({})", pprust::pat_to_string(pat));
154-
(msg, fix)
155-
}
156-
};
157-
158-
self.struct_span_err(pat.span, "an or-pattern parameter must be wrapped in parentheses")
159-
.span_suggestion(pat.span, msg, fix, Applicability::MachineApplicable)
160-
.emit();
216+
self.parse_pat_before_ty(
217+
PARAM_EXPECTED,
218+
GateOr::No,
219+
RecoverComma::No,
220+
"function parameters",
221+
)
161222
}
162223

163224
/// Eat the or-pattern `|` separator.
164225
/// If instead a `||` token is encountered, recover and pretend we parsed `|`.
165-
fn eat_or_separator(&mut self, lo: Option<Span>) -> bool {
226+
fn eat_or_separator(&mut self, lo: Option<Span>) -> EatOrResult {
166227
if self.recover_trailing_vert(lo) {
167-
return false;
168-
}
169-
170-
match self.token.kind {
171-
token::OrOr => {
172-
// Found `||`; Recover and pretend we parsed `|`.
173-
self.ban_unexpected_or_or(lo);
174-
self.bump();
175-
true
176-
}
177-
_ => self.eat(&token::BinOp(token::Or)),
228+
EatOrResult::TrailingVert
229+
} else if matches!(self.token.kind, token::OrOr) {
230+
// Found `||`; Recover and pretend we parsed `|`.
231+
self.ban_unexpected_or_or(lo);
232+
self.bump();
233+
EatOrResult::AteOr
234+
} else if self.eat(&token::BinOp(token::Or)) {
235+
EatOrResult::AteOr
236+
} else {
237+
EatOrResult::None
178238
}
179239
}
180240

@@ -190,14 +250,14 @@ impl<'a> Parser<'a> {
190250
matches!(
191251
&token.uninterpolate().kind,
192252
token::FatArrow // e.g. `a | => 0,`.
193-
| token::Ident(kw::If, false) // e.g. `a | if expr`.
194-
| token::Eq // e.g. `let a | = 0`.
195-
| token::Semi // e.g. `let a |;`.
196-
| token::Colon // e.g. `let a | :`.
197-
| token::Comma // e.g. `let (a |,)`.
198-
| token::CloseDelim(token::Bracket) // e.g. `let [a | ]`.
199-
| token::CloseDelim(token::Paren) // e.g. `let (a | )`.
200-
| token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`.
253+
| token::Ident(kw::If, false) // e.g. `a | if expr`.
254+
| token::Eq // e.g. `let a | = 0`.
255+
| token::Semi // e.g. `let a |;`.
256+
| token::Colon // e.g. `let a | :`.
257+
| token::Comma // e.g. `let (a |,)`.
258+
| token::CloseDelim(token::Bracket) // e.g. `let [a | ]`.
259+
| token::CloseDelim(token::Paren) // e.g. `let (a | )`.
260+
| token::CloseDelim(token::Brace) // e.g. `let A { f: a | }`.
201261
)
202262
});
203263
match (is_end_ahead, &self.token.kind) {

‎compiler/rustc_parse/src/parser/stmt.rs‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use rustc_ast::token::{self, TokenKind};
1313
use rustc_ast::util::classify;
1414
use rustc_ast::AstLike;
1515
use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle};
16-
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt, StmtKind, DUMMY_NODE_ID};
16+
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
17+
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
1718
use rustc_errors::{Applicability, PResult};
1819
use rustc_span::source_map::{BytePos, Span};
1920
use rustc_span::symbol::{kw, sym};
@@ -220,9 +221,10 @@ impl<'a> Parser<'a> {
220221
/// Parses a local variable declaration.
221222
fn parse_local(&mut self, attrs: AttrVec) -> PResult<'a, P<Local>> {
222223
let lo = self.prev_token.span;
223-
let pat = self.parse_pat_allow_top_alt(None, GateOr::Yes, RecoverComma::Yes)?;
224+
let (pat, colon) =
225+
self.parse_pat_before_ty(None, GateOr::Yes, RecoverComma::Yes, "`let` bindings")?;
224226

225-
let (err, ty) = if self.eat(&token::Colon) {
227+
let (err, ty) = if colon {
226228
// Save the state of the parser before parsing type normally, in case there is a `:`
227229
// instead of an `=` typo.
228230
let parser_snapshot_before_type = self.clone();

‎src/test/ui/or-patterns/already-bound-name.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,28 @@ fn main() {
1818
let (A(a, _) | B(a), a) = (A(0, 1), 2);
1919
//~^ ERROR identifier `a` is bound more than once in the same pattern
2020

21-
let A(a, a) | B(a) = A(0, 1);
21+
let (A(a, a) | B(a)) = A(0, 1);
2222
//~^ ERROR identifier `a` is bound more than once in the same pattern
2323

24-
let B(a) | A(a, a) = A(0, 1);
24+
let (B(a) | A(a, a)) = A(0, 1);
2525
//~^ ERROR identifier `a` is bound more than once in the same pattern
2626

2727
match A(0, 1) {
2828
B(a) | A(a, a) => {} // Let's ensure `match` has no funny business.
2929
//~^ ERROR identifier `a` is bound more than once in the same pattern
3030
}
3131

32-
let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
32+
let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
3333
//~^ ERROR identifier `a` is bound more than once in the same pattern
3434
//~| ERROR identifier `a` is bound more than once in the same pattern
3535
//~| ERROR mismatched types
3636

37-
let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
37+
let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
3838
//~^ ERROR identifier `a` is bound more than once in the same pattern
3939
//~| ERROR identifier `a` is bound more than once in the same pattern
4040
//~| ERROR variable `a` is not bound in all patterns
4141

42-
let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
42+
let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
4343
//~^ ERROR identifier `a` is bound more than once in the same pattern
4444
//~| ERROR identifier `a` is bound more than once in the same pattern
4545
}

‎src/test/ui/or-patterns/already-bound-name.stderr‎

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,16 @@ LL | let (A(a, _) | B(a), a) = (A(0, 1), 2);
2323
| ^ used in a pattern more than once
2424

2525
error[E0416]: identifier `a` is bound more than once in the same pattern
26-
--> $DIR/already-bound-name.rs:21:14
26+
--> $DIR/already-bound-name.rs:21:15
2727
|
28-
LL | let A(a, a) | B(a) = A(0, 1);
29-
| ^ used in a pattern more than once
28+
LL | let (A(a, a) | B(a)) = A(0, 1);
29+
| ^ used in a pattern more than once
3030

3131
error[E0416]: identifier `a` is bound more than once in the same pattern
32-
--> $DIR/already-bound-name.rs:24:21
32+
--> $DIR/already-bound-name.rs:24:22
3333
|
34-
LL | let B(a) | A(a, a) = A(0, 1);
35-
| ^ used in a pattern more than once
34+
LL | let (B(a) | A(a, a)) = A(0, 1);
35+
| ^ used in a pattern more than once
3636

3737
error[E0416]: identifier `a` is bound more than once in the same pattern
3838
--> $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.
4141
| ^ used in a pattern more than once
4242

4343
error[E0416]: identifier `a` is bound more than once in the same pattern
44-
--> $DIR/already-bound-name.rs:32:36
44+
--> $DIR/already-bound-name.rs:32:37
4545
|
46-
LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
47-
| ^ used in a pattern more than once
46+
LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
47+
| ^ used in a pattern more than once
4848

4949
error[E0416]: identifier `a` is bound more than once in the same pattern
50-
--> $DIR/already-bound-name.rs:32:46
50+
--> $DIR/already-bound-name.rs:32:47
5151
|
52-
LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
53-
| ^ used in a pattern more than once
52+
LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
53+
| ^ used in a pattern more than once
5454

5555
error[E0416]: identifier `a` is bound more than once in the same pattern
56-
--> $DIR/already-bound-name.rs:37:36
56+
--> $DIR/already-bound-name.rs:37:37
5757
|
58-
LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
59-
| ^ used in a pattern more than once
58+
LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
59+
| ^ used in a pattern more than once
6060

6161
error[E0416]: identifier `a` is bound more than once in the same pattern
62-
--> $DIR/already-bound-name.rs:37:46
62+
--> $DIR/already-bound-name.rs:37:47
6363
|
64-
LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
65-
| ^ used in a pattern more than once
64+
LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
65+
| ^ used in a pattern more than once
6666

6767
error[E0408]: variable `a` is not bound in all patterns
68-
--> $DIR/already-bound-name.rs:37:9
68+
--> $DIR/already-bound-name.rs:37:10
6969
|
70-
LL | let B(_) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
71-
| ^^^^ pattern doesn't bind `a` - variable not in all patterns
70+
LL | let (B(_) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
71+
| ^^^^ pattern doesn't bind `a` - variable not in all patterns
7272

7373
error[E0416]: identifier `a` is bound more than once in the same pattern
74-
--> $DIR/already-bound-name.rs:42:49
74+
--> $DIR/already-bound-name.rs:42:50
7575
|
76-
LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
77-
| ^ used in a pattern more than once
76+
LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
77+
| ^ used in a pattern more than once
7878

7979
error[E0416]: identifier `a` is bound more than once in the same pattern
80-
--> $DIR/already-bound-name.rs:42:59
80+
--> $DIR/already-bound-name.rs:42:60
8181
|
82-
LL | let B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a)) = B(B(1));
83-
| ^ used in a pattern more than once
82+
LL | let (B(A(a, _) | B(a)) | A(A(a, _) | B(a), A(a, _) | B(a))) = B(B(1));
83+
| ^ used in a pattern more than once
8484

8585
error[E0308]: mismatched types
86-
--> $DIR/already-bound-name.rs:32:31
86+
--> $DIR/already-bound-name.rs:32:32
8787
|
88-
LL | let B(A(a, _) | B(a)) | A(a, A(a, _) | B(a)) = B(B(1));
89-
| - ^ ------- this expression has type `E<E<{integer}>>`
90-
| | |
91-
| | expected integer, found enum `E`
92-
| first introduced with type `{integer}` here
88+
LL | let (B(A(a, _) | B(a)) | A(a, A(a, _) | B(a))) = B(B(1));
89+
| - ^ ------- this expression has type `E<E<{integer}>>`
90+
| | |
91+
| | expected integer, found enum `E`
92+
| first introduced with type `{integer}` here
9393
|
9494
= note: expected type `{integer}`
9595
found type `E<{integer}>`

‎src/test/ui/or-patterns/consistent-bindings.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88

99
fn main() {
1010
// One level:
11-
let Ok(a) | Err(a) = Ok(0);
12-
let Ok(ref a) | Err(ref a) = Ok(0);
13-
let Ok(ref mut a) | Err(ref mut a) = Ok(0);
11+
let (Ok(a) | Err(a)) = Ok(0);
12+
let (Ok(ref a) | Err(ref a)) = Ok(0);
13+
let (Ok(ref mut a) | Err(ref mut a)) = Ok(0);
1414

1515
// Two levels:
1616
enum Tri<S, T, U> {
@@ -20,10 +20,10 @@ fn main() {
2020
}
2121
use Tri::*;
2222

23-
let Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b))): Result<_, Result<_, _>> =
23+
let (Ok((V1(a) | V2(a) | V3(a), b)) | Err(Ok((a, b)) | Err((a, b)))): Result<_, Result<_, _>> =
2424
Ok((V1(1), 1));
2525

26-
let Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b))): Result<
26+
let (Ok((V1(a) | V2(a) | V3(a), ref b)) | Err(Ok((a, ref b)) | Err((a, ref b)))): Result<
2727
_,
2828
Result<_, _>,
2929
> = Ok((V1(1), 1));

‎src/test/ui/or-patterns/const-fn.rs‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,28 +3,28 @@
33

44
const fn foo((Ok(a) | Err(a)): Result<i32, i32>) {
55
let x = Ok(3);
6-
let Ok(y) | Err(y) = x;
6+
let (Ok(y) | Err(y)) = x;
77
}
88

99
const X: () = {
1010
let x = Ok(3);
11-
let Ok(y) | Err(y) = x;
11+
let (Ok(y) | Err(y)) = x;
1212
};
1313

1414
static Y: () = {
1515
let x = Ok(3);
16-
let Ok(y) | Err(y) = x;
16+
let (Ok(y) | Err(y)) = x;
1717
};
1818

1919
static mut Z: () = {
2020
let x = Ok(3);
21-
let Ok(y) | Err(y) = x;
21+
let (Ok(y) | Err(y)) = x;
2222
};
2323

2424
fn main() {
2525
let _: [(); {
2626
let x = Ok(3);
27-
let Ok(y) | Err(y) = x;
27+
let (Ok(y) | Err(y)) = x;
2828
2
2929
}];
3030
}

‎src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ fn main() {}
55
#[cfg(FALSE)]
66
fn gated_leading_vert_in_let() {
77
let | A; //~ ERROR or-patterns syntax is experimental
8+
//~^ ERROR top-level or-patterns are not allowed
89
}

‎src/test/ui/or-patterns/feature-gate-or_patterns-leading-let.stderr‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
error: top-level or-patterns are not allowed in `let` bindings
2+
--> $DIR/feature-gate-or_patterns-leading-let.rs:7:9
3+
|
4+
LL | let | A;
5+
| ^^^ help: remove the `|`: `A`
6+
17
error[E0658]: or-patterns syntax is experimental
28
--> $DIR/feature-gate-or_patterns-leading-let.rs:7:9
39
|
@@ -7,6 +13,6 @@ LL | let | A;
713
= note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
814
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
915

10-
error: aborting due to previous error
16+
error: aborting due to 2 previous errors
1117

1218
For more information about this error, try `rustc --explain E0658`.

‎src/test/ui/or-patterns/feature-gate-or_patterns.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ fn or_patterns() {
2626
// Gated:
2727

2828
let | A | B; //~ ERROR or-patterns syntax is experimental
29+
//~^ ERROR top-level or-patterns are not allowed
2930
let A | B; //~ ERROR or-patterns syntax is experimental
31+
//~^ ERROR top-level or-patterns are not allowed
3032
for | A | B in 0 {} //~ ERROR or-patterns syntax is experimental
3133
for A | B in 0 {} //~ ERROR or-patterns syntax is experimental
3234
fn fun((A | B): _) {} //~ ERROR or-patterns syntax is experimental

‎src/test/ui/or-patterns/feature-gate-or_patterns.stderr‎

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: top-level or-patterns are not allowed in `let` bindings
2+
--> $DIR/feature-gate-or_patterns.rs:28:9
3+
|
4+
LL | let | A | B;
5+
| ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)`
6+
7+
error: top-level or-patterns are not allowed in `let` bindings
8+
--> $DIR/feature-gate-or_patterns.rs:30:9
9+
|
10+
LL | let A | B;
11+
| ^^^^^ help: wrap the pattern in parentheses: `(A | B)`
12+
113
error[E0658]: or-patterns syntax is experimental
214
--> $DIR/feature-gate-or_patterns.rs:5:14
315
|
@@ -17,7 +29,7 @@ LL | let | A | B;
1729
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
1830

1931
error[E0658]: or-patterns syntax is experimental
20-
--> $DIR/feature-gate-or_patterns.rs:29:9
32+
--> $DIR/feature-gate-or_patterns.rs:30:9
2133
|
2234
LL | let A | B;
2335
| ^^^^^
@@ -26,7 +38,7 @@ LL | let A | B;
2638
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
2739

2840
error[E0658]: or-patterns syntax is experimental
29-
--> $DIR/feature-gate-or_patterns.rs:30:9
41+
--> $DIR/feature-gate-or_patterns.rs:32:9
3042
|
3143
LL | for | A | B in 0 {}
3244
| ^^^^^^^
@@ -35,7 +47,7 @@ LL | for | A | B in 0 {}
3547
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
3648

3749
error[E0658]: or-patterns syntax is experimental
38-
--> $DIR/feature-gate-or_patterns.rs:31:9
50+
--> $DIR/feature-gate-or_patterns.rs:33:9
3951
|
4052
LL | for A | B in 0 {}
4153
| ^^^^^
@@ -44,7 +56,7 @@ LL | for A | B in 0 {}
4456
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
4557

4658
error[E0658]: or-patterns syntax is experimental
47-
--> $DIR/feature-gate-or_patterns.rs:32:13
59+
--> $DIR/feature-gate-or_patterns.rs:34:13
4860
|
4961
LL | fn fun((A | B): _) {}
5062
| ^^^^^
@@ -53,7 +65,7 @@ LL | fn fun((A | B): _) {}
5365
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
5466

5567
error[E0658]: or-patterns syntax is experimental
56-
--> $DIR/feature-gate-or_patterns.rs:33:15
68+
--> $DIR/feature-gate-or_patterns.rs:35:15
5769
|
5870
LL | let _ = |(A | B): u8| ();
5971
| ^^^^^
@@ -62,7 +74,7 @@ LL | let _ = |(A | B): u8| ();
6274
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
6375

6476
error[E0658]: or-patterns syntax is experimental
65-
--> $DIR/feature-gate-or_patterns.rs:34:10
77+
--> $DIR/feature-gate-or_patterns.rs:36:10
6678
|
6779
LL | let (A | B);
6880
| ^^^^^
@@ -71,7 +83,7 @@ LL | let (A | B);
7183
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
7284

7385
error[E0658]: or-patterns syntax is experimental
74-
--> $DIR/feature-gate-or_patterns.rs:35:10
86+
--> $DIR/feature-gate-or_patterns.rs:37:10
7587
|
7688
LL | let (A | B,);
7789
| ^^^^^
@@ -80,7 +92,7 @@ LL | let (A | B,);
8092
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
8193

8294
error[E0658]: or-patterns syntax is experimental
83-
--> $DIR/feature-gate-or_patterns.rs:36:11
95+
--> $DIR/feature-gate-or_patterns.rs:38:11
8496
|
8597
LL | let A(B | C);
8698
| ^^^^^
@@ -89,7 +101,7 @@ LL | let A(B | C);
89101
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
90102

91103
error[E0658]: or-patterns syntax is experimental
92-
--> $DIR/feature-gate-or_patterns.rs:37:14
104+
--> $DIR/feature-gate-or_patterns.rs:39:14
93105
|
94106
LL | let E::V(B | C);
95107
| ^^^^^
@@ -98,7 +110,7 @@ LL | let E::V(B | C);
98110
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
99111

100112
error[E0658]: or-patterns syntax is experimental
101-
--> $DIR/feature-gate-or_patterns.rs:38:17
113+
--> $DIR/feature-gate-or_patterns.rs:40:17
102114
|
103115
LL | let S { f1: B | C, f2 };
104116
| ^^^^^
@@ -107,7 +119,7 @@ LL | let S { f1: B | C, f2 };
107119
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
108120

109121
error[E0658]: or-patterns syntax is experimental
110-
--> $DIR/feature-gate-or_patterns.rs:39:20
122+
--> $DIR/feature-gate-or_patterns.rs:41:20
111123
|
112124
LL | let E::V { f1: B | C, f2 };
113125
| ^^^^^
@@ -116,7 +128,7 @@ LL | let E::V { f1: B | C, f2 };
116128
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
117129

118130
error[E0658]: or-patterns syntax is experimental
119-
--> $DIR/feature-gate-or_patterns.rs:40:10
131+
--> $DIR/feature-gate-or_patterns.rs:42:10
120132
|
121133
LL | let [A | B];
122134
| ^^^^^
@@ -169,6 +181,6 @@ LL | accept_pat!([p | q]);
169181
= note: see issue #54883 <https://github.com/rust-lang/rust/issues/54883> for more information
170182
= help: add `#![feature(or_patterns)]` to the crate attributes to enable
171183

172-
error: aborting due to 19 previous errors
184+
error: aborting due to 21 previous errors
173185

174186
For more information about this error, try `rustc --explain E0658`.

‎src/test/ui/or-patterns/fn-param-wrap-parens.fixed‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ enum E { A, B }
1111
use E::*;
1212

1313
#[cfg(FALSE)]
14-
fn fun1((A | B): E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
14+
fn fun1((A | B): E) {} //~ ERROR top-level or-patterns are not allowed

‎src/test/ui/or-patterns/fn-param-wrap-parens.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ enum E { A, B }
1111
use E::*;
1212

1313
#[cfg(FALSE)]
14-
fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
14+
fn fun1(A | B: E) {} //~ ERROR top-level or-patterns are not allowed

‎src/test/ui/or-patterns/fn-param-wrap-parens.stderr‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: an or-pattern parameter must be wrapped in parentheses
1+
error: top-level or-patterns are not allowed in function parameters
22
--> $DIR/fn-param-wrap-parens.rs:14:9
33
|
44
LL | fn fun1(A | B: E) {}

‎src/test/ui/or-patterns/inconsistent-modes.rs‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,23 @@
44
#![allow(non_camel_case_types)]
55
fn main() {
66
// One level:
7-
let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
7+
let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0);
88
//~^ ERROR variable `a` is bound inconsistently
9-
let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
9+
let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = Ok(0);
1010
//~^ ERROR variable `a` is bound inconsistently
11-
let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
11+
let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0);
1212
//~^ ERROR variable `a` is bound inconsistently
1313
//~| ERROR mismatched types
14-
let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
14+
let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0));
1515
//~^ ERROR variable `a` is bound inconsistently
1616
//~| ERROR variable `b` is bound inconsistently
1717
//~| ERROR mismatched types
1818

1919
// Two levels:
20-
let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
20+
let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0);
2121
//~^ ERROR variable `a` is bound inconsistently
2222

2323
// Three levels:
24-
let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1);
24+
let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1);
2525
//~^ ERROR variable `a` is bound inconsistently
2626
}

‎src/test/ui/or-patterns/inconsistent-modes.stderr‎

Lines changed: 41 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,74 @@
11
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
2-
--> $DIR/inconsistent-modes.rs:7:25
2+
--> $DIR/inconsistent-modes.rs:7:26
33
|
4-
LL | let Ok(a) | Err(ref a): Result<&u8, u8> = Ok(&0);
5-
| - ^ bound in different ways
6-
| |
7-
| first binding
4+
LL | let (Ok(a) | Err(ref a)): Result<&u8, u8> = Ok(&0);
5+
| - ^ bound in different ways
6+
| |
7+
| first binding
88

99
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
10-
--> $DIR/inconsistent-modes.rs:9:29
10+
--> $DIR/inconsistent-modes.rs:9:30
1111
|
12-
LL | let Ok(ref mut a) | Err(a): Result<u8, &mut u8> = Ok(0);
13-
| - ^ bound in different ways
14-
| |
15-
| first binding
12+
LL | let (Ok(ref mut a) | Err(a)): Result<u8, &mut u8> = Ok(0);
13+
| - ^ bound in different ways
14+
| |
15+
| first binding
1616

1717
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
18-
--> $DIR/inconsistent-modes.rs:11:33
18+
--> $DIR/inconsistent-modes.rs:11:34
1919
|
20-
LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
21-
| - first binding ^ bound in different ways
20+
LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0);
21+
| - first binding ^ bound in different ways
2222

2323
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
24-
--> $DIR/inconsistent-modes.rs:14:39
24+
--> $DIR/inconsistent-modes.rs:14:40
2525
|
26-
LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
27-
| - first binding ^ bound in different ways
26+
LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0));
27+
| - first binding ^ bound in different ways
2828

2929
error[E0409]: variable `b` is bound inconsistently across alternatives separated by `|`
30-
--> $DIR/inconsistent-modes.rs:14:46
30+
--> $DIR/inconsistent-modes.rs:14:47
3131
|
32-
LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
33-
| - first binding ^ bound in different ways
32+
LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0));
33+
| - first binding ^ bound in different ways
3434

3535
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
36-
--> $DIR/inconsistent-modes.rs:20:38
36+
--> $DIR/inconsistent-modes.rs:20:39
3737
|
38-
LL | let Ok(Ok(a) | Err(a)) | Err(ref a) = Err(0);
39-
| - ^ bound in different ways
40-
| |
41-
| first binding
38+
LL | let (Ok(Ok(a) | Err(a)) | Err(ref a)) = Err(0);
39+
| - ^ bound in different ways
40+
| |
41+
| first binding
4242

4343
error[E0409]: variable `a` is bound inconsistently across alternatives separated by `|`
44-
--> $DIR/inconsistent-modes.rs:24:33
44+
--> $DIR/inconsistent-modes.rs:24:34
4545
|
46-
LL | let Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a) = Err(&1);
47-
| - ^ bound in different ways
48-
| |
49-
| first binding
46+
LL | let (Ok([Ok((Ok(ref a) | Err(a),)) | Err(a)]) | Err(a)) = Err(&1);
47+
| - ^ bound in different ways
48+
| |
49+
| first binding
5050

5151
error[E0308]: mismatched types
52-
--> $DIR/inconsistent-modes.rs:11:25
52+
--> $DIR/inconsistent-modes.rs:11:26
5353
|
54-
LL | let Ok(ref a) | Err(ref mut a): Result<&u8, &mut u8> = Ok(&0);
55-
| ----- ^^^^^^^^^ -------------------- expected due to this
56-
| | |
57-
| | types differ in mutability
58-
| first introduced with type `&&u8` here
54+
LL | let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0);
55+
| ----- ^^^^^^^^^ -------------------- expected due to this
56+
| | |
57+
| | types differ in mutability
58+
| first introduced with type `&&u8` here
5959
|
6060
= note: expected type `&&u8`
6161
found type `&mut &mut u8`
6262
= note: a binding must have the same type in all alternatives
6363

6464
error[E0308]: mismatched types
65-
--> $DIR/inconsistent-modes.rs:14:31
65+
--> $DIR/inconsistent-modes.rs:14:32
6666
|
67-
LL | let Ok((ref a, b)) | Err((ref mut a, ref b)) = Ok((0, &0));
68-
| ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>`
69-
| | |
70-
| | types differ in mutability
71-
| first introduced with type `&{integer}` here
67+
LL | let (Ok((ref a, b)) | Err((ref mut a, ref b))) = Ok((0, &0));
68+
| ----- ^^^^^^^^^ ----------- this expression has type `Result<({integer}, &{integer}), (_, _)>`
69+
| | |
70+
| | types differ in mutability
71+
| first introduced with type `&{integer}` here
7272
|
7373
= note: expected type `&{integer}`
7474
found type `&mut _`

‎src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#![feature(or_patterns)]
22

33
fn main() {
4-
let 0 | (1 | 2) = 0; //~ ERROR refutable pattern in local binding
4+
let (0 | (1 | 2)) = 0; //~ ERROR refutable pattern in local binding
55
match 0 {
66
//~^ ERROR non-exhaustive patterns
77
0 | (1 | 2) => {}

‎src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
error[E0005]: refutable pattern in local binding: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
2-
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:9
2+
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:4:10
33
|
4-
LL | let 0 | (1 | 2) = 0;
5-
| ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
4+
LL | let (0 | (1 | 2)) = 0;
5+
| ^^^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
66
|
77
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
88
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
99
= note: the matched value is of type `i32`
1010
help: you might want to use `if let` to ignore the variant that isn't matched
1111
|
12-
LL | if let 0 | (1 | 2) = 0 { /* */ }
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
LL | if let (0 | (1 | 2)) = 0 { /* */ }
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

1515
error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
1616
--> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:5:11

‎src/test/ui/or-patterns/issue-69875-should-have-been-expanded-earlier.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#![feature(or_patterns)]
44

55
fn main() {
6-
let 0 | (1 | _) = 0;
6+
let (0 | (1 | _)) = 0;
77
if let 0 | (1 | 2) = 0 {}
88
if let x @ 0 | x @ (1 | 2) = 0 {}
99
}

‎src/test/ui/or-patterns/let-pattern.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// run-pass
44

55
fn or_pat_let(x: Result<u32, u32>) -> u32 {
6-
let Ok(y) | Err(y) = x;
6+
let (Ok(y) | Err(y)) = x;
77
y
88
}
99

‎src/test/ui/or-patterns/mismatched-bindings-async-fn.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ async fn a((x | s): String) {}
88
//~| ERROR variable `s` is not bound in all patterns
99

1010
async fn b() {
11-
let x | s = String::new();
11+
let (x | s) = String::new();
1212
//~^ ERROR variable `x` is not bound in all patterns
1313
//~| ERROR variable `s` is not bound in all patterns
1414
}

‎src/test/ui/or-patterns/mismatched-bindings-async-fn.stderr‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,20 @@ LL | async fn a((x | s): String) {}
1515
| variable not in all patterns
1616

1717
error[E0408]: variable `s` is not bound in all patterns
18-
--> $DIR/mismatched-bindings-async-fn.rs:11:9
18+
--> $DIR/mismatched-bindings-async-fn.rs:11:10
1919
|
20-
LL | let x | s = String::new();
21-
| ^ - variable not in all patterns
22-
| |
23-
| pattern doesn't bind `s`
20+
LL | let (x | s) = String::new();
21+
| ^ - variable not in all patterns
22+
| |
23+
| pattern doesn't bind `s`
2424

2525
error[E0408]: variable `x` is not bound in all patterns
26-
--> $DIR/mismatched-bindings-async-fn.rs:11:13
26+
--> $DIR/mismatched-bindings-async-fn.rs:11:14
2727
|
28-
LL | let x | s = String::new();
29-
| - ^ pattern doesn't bind `x`
30-
| |
31-
| variable not in all patterns
28+
LL | let (x | s) = String::new();
29+
| - ^ pattern doesn't bind `x`
30+
| |
31+
| variable not in all patterns
3232

3333
error: aborting due to 4 previous errors
3434

‎src/test/ui/or-patterns/missing-bindings.rs‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ fn check_handling_of_paths() {
1717
}
1818

1919
use bar::foo::{alpha, charlie};
20-
let alpha | beta | charlie = alpha; //~ ERROR variable `beta` is not bound in all patterns
20+
let (alpha | beta | charlie) = alpha; //~ ERROR variable `beta` is not bound in all patterns
2121
match Some(alpha) {
2222
Some(alpha | beta) => {} //~ ERROR variable `beta` is not bound in all patterns
2323
}
@@ -31,19 +31,19 @@ fn check_misc_nesting() {
3131

3232
// One level:
3333
const X: E<u8> = B(0);
34-
let A(a, _) | _ = X; //~ ERROR variable `a` is not bound in all patterns
35-
let _ | B(a) = X; //~ ERROR variable `a` is not bound in all patterns
36-
let A(..) | B(a) = X; //~ ERROR variable `a` is not bound in all patterns
37-
let A(a, _) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns
38-
let A(_, a) | B(_) = X; //~ ERROR variable `a` is not bound in all patterns
39-
let A(a, b) | B(a) = X; //~ ERROR variable `b` is not bound in all patterns
34+
let (A(a, _) | _) = X; //~ ERROR variable `a` is not bound in all patterns
35+
let (_ | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns
36+
let (A(..) | B(a)) = X; //~ ERROR variable `a` is not bound in all patterns
37+
let (A(a, _) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns
38+
let (A(_, a) | B(_)) = X; //~ ERROR variable `a` is not bound in all patterns
39+
let (A(a, b) | B(a)) = X; //~ ERROR variable `b` is not bound in all patterns
4040

4141
// Two levels:
4242
const Y: E<E<u8>> = B(B(0));
43-
let A(A(..) | B(_), _) | B(a) = Y; //~ ERROR variable `a` is not bound in all patterns
44-
let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y;
43+
let (A(A(..) | B(_), _) | B(a)) = Y; //~ ERROR variable `a` is not bound in all patterns
44+
let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
4545
//~^ ERROR variable `a` is not bound in all patterns
46-
let A(A(a, b) | B(c), d) | B(e) = Y;
46+
let (A(A(a, b) | B(c), d) | B(e)) = Y;
4747
//~^ ERROR variable `a` is not bound in all patterns
4848
//~| ERROR variable `a` is not bound in all patterns
4949
//~| ERROR variable `b` is not bound in all patterns

‎src/test/ui/or-patterns/missing-bindings.stderr‎

Lines changed: 86 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
error[E0408]: variable `beta` is not bound in all patterns
2-
--> $DIR/missing-bindings.rs:20:9
2+
--> $DIR/missing-bindings.rs:20:10
33
|
4-
LL | let alpha | beta | charlie = alpha;
5-
| ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta`
6-
| | |
7-
| | variable not in all patterns
8-
| pattern doesn't bind `beta`
4+
LL | let (alpha | beta | charlie) = alpha;
5+
| ^^^^^ ---- ^^^^^^^ pattern doesn't bind `beta`
6+
| | |
7+
| | variable not in all patterns
8+
| pattern doesn't bind `beta`
99

1010
error[E0408]: variable `beta` is not bound in all patterns
1111
--> $DIR/missing-bindings.rs:22:14
@@ -16,132 +16,132 @@ LL | Some(alpha | beta) => {}
1616
| pattern doesn't bind `beta`
1717

1818
error[E0408]: variable `a` is not bound in all patterns
19-
--> $DIR/missing-bindings.rs:34:19
19+
--> $DIR/missing-bindings.rs:34:20
2020
|
21-
LL | let A(a, _) | _ = X;
22-
| - ^ pattern doesn't bind `a`
23-
| |
24-
| variable not in all patterns
21+
LL | let (A(a, _) | _) = X;
22+
| - ^ pattern doesn't bind `a`
23+
| |
24+
| variable not in all patterns
2525

2626
error[E0408]: variable `a` is not bound in all patterns
27-
--> $DIR/missing-bindings.rs:35:9
27+
--> $DIR/missing-bindings.rs:35:10
2828
|
29-
LL | let _ | B(a) = X;
30-
| ^ - variable not in all patterns
31-
| |
32-
| pattern doesn't bind `a`
29+
LL | let (_ | B(a)) = X;
30+
| ^ - variable not in all patterns
31+
| |
32+
| pattern doesn't bind `a`
3333

3434
error[E0408]: variable `a` is not bound in all patterns
35-
--> $DIR/missing-bindings.rs:36:9
35+
--> $DIR/missing-bindings.rs:36:10
3636
|
37-
LL | let A(..) | B(a) = X;
38-
| ^^^^^ - variable not in all patterns
39-
| |
40-
| pattern doesn't bind `a`
37+
LL | let (A(..) | B(a)) = X;
38+
| ^^^^^ - variable not in all patterns
39+
| |
40+
| pattern doesn't bind `a`
4141

4242
error[E0408]: variable `a` is not bound in all patterns
43-
--> $DIR/missing-bindings.rs:37:19
43+
--> $DIR/missing-bindings.rs:37:20
4444
|
45-
LL | let A(a, _) | B(_) = X;
46-
| - ^^^^ pattern doesn't bind `a`
47-
| |
48-
| variable not in all patterns
45+
LL | let (A(a, _) | B(_)) = X;
46+
| - ^^^^ pattern doesn't bind `a`
47+
| |
48+
| variable not in all patterns
4949

5050
error[E0408]: variable `a` is not bound in all patterns
51-
--> $DIR/missing-bindings.rs:38:19
51+
--> $DIR/missing-bindings.rs:38:20
5252
|
53-
LL | let A(_, a) | B(_) = X;
54-
| - ^^^^ pattern doesn't bind `a`
55-
| |
56-
| variable not in all patterns
53+
LL | let (A(_, a) | B(_)) = X;
54+
| - ^^^^ pattern doesn't bind `a`
55+
| |
56+
| variable not in all patterns
5757

5858
error[E0408]: variable `b` is not bound in all patterns
59-
--> $DIR/missing-bindings.rs:39:19
59+
--> $DIR/missing-bindings.rs:39:20
6060
|
61-
LL | let A(a, b) | B(a) = X;
62-
| - ^^^^ pattern doesn't bind `b`
63-
| |
64-
| variable not in all patterns
61+
LL | let (A(a, b) | B(a)) = X;
62+
| - ^^^^ pattern doesn't bind `b`
63+
| |
64+
| variable not in all patterns
6565

6666
error[E0408]: variable `a` is not bound in all patterns
67-
--> $DIR/missing-bindings.rs:43:9
67+
--> $DIR/missing-bindings.rs:43:10
6868
|
69-
LL | let A(A(..) | B(_), _) | B(a) = Y;
70-
| ^^^^^^^^^^^^^^^^^^ - variable not in all patterns
71-
| |
72-
| pattern doesn't bind `a`
69+
LL | let (A(A(..) | B(_), _) | B(a)) = Y;
70+
| ^^^^^^^^^^^^^^^^^^ - variable not in all patterns
71+
| |
72+
| pattern doesn't bind `a`
7373

7474
error[E0408]: variable `a` is not bound in all patterns
75-
--> $DIR/missing-bindings.rs:44:11
75+
--> $DIR/missing-bindings.rs:44:12
7676
|
77-
LL | let A(A(..) | B(a), _) | B(A(a, _) | B(a)) = Y;
78-
| ^^^^^ - variable not in all patterns
79-
| |
80-
| pattern doesn't bind `a`
77+
LL | let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
78+
| ^^^^^ - variable not in all patterns
79+
| |
80+
| pattern doesn't bind `a`
8181

8282
error[E0408]: variable `a` is not bound in all patterns
83-
--> $DIR/missing-bindings.rs:46:21
83+
--> $DIR/missing-bindings.rs:46:22
8484
|
85-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
86-
| - ^^^^ pattern doesn't bind `a`
87-
| |
88-
| variable not in all patterns
85+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
86+
| - ^^^^ pattern doesn't bind `a`
87+
| |
88+
| variable not in all patterns
8989

9090
error[E0408]: variable `b` is not bound in all patterns
91-
--> $DIR/missing-bindings.rs:46:21
91+
--> $DIR/missing-bindings.rs:46:22
9292
|
93-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
94-
| - ^^^^ pattern doesn't bind `b`
95-
| |
96-
| variable not in all patterns
93+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
94+
| - ^^^^ pattern doesn't bind `b`
95+
| |
96+
| variable not in all patterns
9797

9898
error[E0408]: variable `c` is not bound in all patterns
99-
--> $DIR/missing-bindings.rs:46:11
99+
--> $DIR/missing-bindings.rs:46:12
100100
|
101-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
102-
| ^^^^^^^ - variable not in all patterns
103-
| |
104-
| pattern doesn't bind `c`
101+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
102+
| ^^^^^^^ - variable not in all patterns
103+
| |
104+
| pattern doesn't bind `c`
105105

106106
error[E0408]: variable `a` is not bound in all patterns
107-
--> $DIR/missing-bindings.rs:46:32
107+
--> $DIR/missing-bindings.rs:46:33
108108
|
109-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
110-
| - ^^^^ pattern doesn't bind `a`
111-
| |
112-
| variable not in all patterns
109+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
110+
| - ^^^^ pattern doesn't bind `a`
111+
| |
112+
| variable not in all patterns
113113

114114
error[E0408]: variable `b` is not bound in all patterns
115-
--> $DIR/missing-bindings.rs:46:32
115+
--> $DIR/missing-bindings.rs:46:33
116116
|
117-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
118-
| - ^^^^ pattern doesn't bind `b`
119-
| |
120-
| variable not in all patterns
117+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
118+
| - ^^^^ pattern doesn't bind `b`
119+
| |
120+
| variable not in all patterns
121121

122122
error[E0408]: variable `c` is not bound in all patterns
123-
--> $DIR/missing-bindings.rs:46:32
123+
--> $DIR/missing-bindings.rs:46:33
124124
|
125-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
126-
| - ^^^^ pattern doesn't bind `c`
127-
| |
128-
| variable not in all patterns
125+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
126+
| - ^^^^ pattern doesn't bind `c`
127+
| |
128+
| variable not in all patterns
129129

130130
error[E0408]: variable `d` is not bound in all patterns
131-
--> $DIR/missing-bindings.rs:46:32
131+
--> $DIR/missing-bindings.rs:46:33
132132
|
133-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
134-
| - ^^^^ pattern doesn't bind `d`
135-
| |
136-
| variable not in all patterns
133+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
134+
| - ^^^^ pattern doesn't bind `d`
135+
| |
136+
| variable not in all patterns
137137

138138
error[E0408]: variable `e` is not bound in all patterns
139-
--> $DIR/missing-bindings.rs:46:9
139+
--> $DIR/missing-bindings.rs:46:10
140140
|
141-
LL | let A(A(a, b) | B(c), d) | B(e) = Y;
142-
| ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns
143-
| |
144-
| pattern doesn't bind `e`
141+
LL | let (A(A(a, b) | B(c), d) | B(e)) = Y;
142+
| ^^^^^^^^^^^^^^^^^^^^ - variable not in all patterns
143+
| |
144+
| pattern doesn't bind `e`
145145

146146
error[E0408]: variable `a` is not bound in all patterns
147147
--> $DIR/missing-bindings.rs:62:29
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// This test tests the precedence of `|` (or-patterns) undelimited nested patterns. In particular,
2+
// we want to reserve the syntactic space of a pattern followed by a type annotation for possible
3+
// future type ascription, so we need to make sure that any time a pattern is followed by type
4+
// annotation (for now), the pattern is not a top-level or-pattern. However, there are also a few
5+
// types of patterns that allow undelimited subpatterns that could cause the same ambiguity.
6+
// Currently, those should be impossible due to precedence rule. This test enforces that.
7+
8+
#![feature(or_patterns)]
9+
10+
enum E {
11+
A,
12+
B,
13+
}
14+
15+
fn foo() {
16+
use E::*;
17+
18+
// ok
19+
let b @ (A | B): E = A;
20+
21+
let b @ A | B: E = A; //~ERROR `b` is not bound in all patterns
22+
//~^ ERROR top-level or-patterns are not allowed
23+
}
24+
25+
enum F {
26+
A(usize),
27+
B(usize),
28+
}
29+
30+
fn bar() {
31+
use F::*;
32+
33+
// ok
34+
let (A(x) | B(x)): F = A(3);
35+
36+
let &A(_) | B(_): F = A(3); //~ERROR mismatched types
37+
//~^ ERROR top-level or-patterns are not allowed
38+
let &&A(_) | B(_): F = A(3); //~ERROR mismatched types
39+
//~^ ERROR top-level or-patterns are not allowed
40+
let &mut A(_) | B(_): F = A(3); //~ERROR mismatched types
41+
//~^ ERROR top-level or-patterns are not allowed
42+
let &&mut A(_) | B(_): F = A(3); //~ERROR mismatched types
43+
//~^ ERROR top-level or-patterns are not allowed
44+
}
45+
46+
fn main() {}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
error: top-level or-patterns are not allowed in `let` bindings
2+
--> $DIR/nested-undelimited-precedence.rs:21:9
3+
|
4+
LL | let b @ A | B: E = A;
5+
| ^^^^^^^^^ help: wrap the pattern in parentheses: `(b @ A | B)`
6+
7+
error: top-level or-patterns are not allowed in `let` bindings
8+
--> $DIR/nested-undelimited-precedence.rs:36:9
9+
|
10+
LL | let &A(_) | B(_): F = A(3);
11+
| ^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&A(_) | B(_))`
12+
13+
error: top-level or-patterns are not allowed in `let` bindings
14+
--> $DIR/nested-undelimited-precedence.rs:38:9
15+
|
16+
LL | let &&A(_) | B(_): F = A(3);
17+
| ^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&A(_) | B(_))`
18+
19+
error: top-level or-patterns are not allowed in `let` bindings
20+
--> $DIR/nested-undelimited-precedence.rs:40:9
21+
|
22+
LL | let &mut A(_) | B(_): F = A(3);
23+
| ^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&mut A(_) | B(_))`
24+
25+
error: top-level or-patterns are not allowed in `let` bindings
26+
--> $DIR/nested-undelimited-precedence.rs:42:9
27+
|
28+
LL | let &&mut A(_) | B(_): F = A(3);
29+
| ^^^^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(&&mut A(_) | B(_))`
30+
31+
error[E0408]: variable `b` is not bound in all patterns
32+
--> $DIR/nested-undelimited-precedence.rs:21:17
33+
|
34+
LL | let b @ A | B: E = A;
35+
| - ^ pattern doesn't bind `b`
36+
| |
37+
| variable not in all patterns
38+
39+
error[E0308]: mismatched types
40+
--> $DIR/nested-undelimited-precedence.rs:36:9
41+
|
42+
LL | let &A(_) | B(_): F = A(3);
43+
| ^^^^^ - expected due to this
44+
| |
45+
| expected enum `F`, found reference
46+
|
47+
= note: expected enum `F`
48+
found reference `&_`
49+
50+
error[E0308]: mismatched types
51+
--> $DIR/nested-undelimited-precedence.rs:38:9
52+
|
53+
LL | let &&A(_) | B(_): F = A(3);
54+
| ^^^^^^ - expected due to this
55+
| |
56+
| expected enum `F`, found reference
57+
|
58+
= note: expected enum `F`
59+
found reference `&_`
60+
61+
error[E0308]: mismatched types
62+
--> $DIR/nested-undelimited-precedence.rs:40:9
63+
|
64+
LL | let &mut A(_) | B(_): F = A(3);
65+
| ^^^^^^^^^ - expected due to this
66+
| |
67+
| expected enum `F`, found `&mut _`
68+
|
69+
= note: expected enum `F`
70+
found mutable reference `&mut _`
71+
72+
error[E0308]: mismatched types
73+
--> $DIR/nested-undelimited-precedence.rs:42:9
74+
|
75+
LL | let &&mut A(_) | B(_): F = A(3);
76+
| ^^^^^^^^^^ - expected due to this
77+
| |
78+
| expected enum `F`, found reference
79+
|
80+
= note: expected enum `F`
81+
found reference `&_`
82+
83+
error: aborting due to 10 previous errors
84+
85+
Some errors have detailed explanations: E0308, E0408.
86+
For more information about an error, try `rustc --explain E0308`.

‎src/test/ui/or-patterns/or-patterns-binding-type-mismatch.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ fn main() {
5252
= Some((0u8, Some((1u16, 2u32))))
5353
{}
5454

55-
let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2);
55+
let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2);
5656
//~^ ERROR mismatched types
5757

58-
let (x, y) | (y, x) = (0u8, 1u16);
58+
let ((x, y) | (y, x)) = (0u8, 1u16);
5959
//~^ ERROR mismatched types
6060
//~| ERROR mismatched types
6161

‎src/test/ui/or-patterns/or-patterns-binding-type-mismatch.stderr‎

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -187,35 +187,35 @@ LL | = Some((0u8, Some((1u16, 2u32))))
187187
= note: a binding must have the same type in all alternatives
188188

189189
error[E0308]: mismatched types
190-
--> $DIR/or-patterns-binding-type-mismatch.rs:55:39
190+
--> $DIR/or-patterns-binding-type-mismatch.rs:55:40
191191
|
192-
LL | let Blah::A(_, x, y) | Blah::B(x, y) = Blah::A(1, 1, 2);
193-
| - ^ ---------------- this expression has type `Blah`
194-
| | |
195-
| | expected `usize`, found `isize`
196-
| first introduced with type `usize` here
192+
LL | let (Blah::A(_, x, y) | Blah::B(x, y)) = Blah::A(1, 1, 2);
193+
| - ^ ---------------- this expression has type `Blah`
194+
| | |
195+
| | expected `usize`, found `isize`
196+
| first introduced with type `usize` here
197197
|
198198
= note: a binding must have the same type in all alternatives
199199

200200
error[E0308]: mismatched types
201-
--> $DIR/or-patterns-binding-type-mismatch.rs:58:19
201+
--> $DIR/or-patterns-binding-type-mismatch.rs:58:20
202202
|
203-
LL | let (x, y) | (y, x) = (0u8, 1u16);
204-
| - ^ ----------- this expression has type `(u8, u16)`
205-
| | |
206-
| | expected `u16`, found `u8`
207-
| first introduced with type `u16` here
203+
LL | let ((x, y) | (y, x)) = (0u8, 1u16);
204+
| - ^ ----------- this expression has type `(u8, u16)`
205+
| | |
206+
| | expected `u16`, found `u8`
207+
| first introduced with type `u16` here
208208
|
209209
= note: a binding must have the same type in all alternatives
210210

211211
error[E0308]: mismatched types
212-
--> $DIR/or-patterns-binding-type-mismatch.rs:58:22
212+
--> $DIR/or-patterns-binding-type-mismatch.rs:58:23
213213
|
214-
LL | let (x, y) | (y, x) = (0u8, 1u16);
215-
| - ^ ----------- this expression has type `(u8, u16)`
216-
| | |
217-
| | expected `u8`, found `u16`
218-
| first introduced with type `u8` here
214+
LL | let ((x, y) | (y, x)) = (0u8, 1u16);
215+
| - ^ ----------- this expression has type `(u8, u16)`
216+
| | |
217+
| | expected `u8`, found `u16`
218+
| first introduced with type `u8` here
219219
|
220220
= note: a binding must have the same type in all alternatives
221221

‎src/test/ui/or-patterns/or-patterns-default-binding-modes.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,11 @@ fn main() {
3737
if let &(Ok(x) | Err(x)) = res {
3838
drop::<u8>(x);
3939
}
40-
let Ok(mut x) | &Err(mut x) = res;
40+
let (Ok(mut x) | &Err(mut x)) = res;
4141
drop::<u8>(x);
4242
let &(Ok(x) | Err(x)) = res;
4343
drop::<u8>(x);
44-
let Ok(x) | Err(x) = res;
44+
let (Ok(x) | Err(x)) = res;
4545
drop::<&u8>(x);
4646
for Ok(mut x) | &Err(mut x) in std::iter::once(res) {
4747
drop::<u8>(x);
@@ -119,9 +119,9 @@ fn main() {
119119
}
120120

121121
let tri = &Tri::A(&Ok(0));
122-
let Tri::A(Ok(mut x) | Err(mut x))
122+
let (Tri::A(Ok(mut x) | Err(mut x))
123123
| Tri::B(&Ok(mut x) | Err(mut x))
124-
| &Tri::C(Ok(mut x) | Err(mut x)) = tri;
124+
| &Tri::C(Ok(mut x) | Err(mut x))) = tri;
125125
drop::<u8>(x);
126126

127127
match tri {

‎src/test/ui/or-patterns/or-patterns-syntactic-fail.rs‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,19 @@ fn no_top_level_or_patterns() {
1414
// -------- This looks like an or-pattern but is in fact `|A| (B: E | ())`.
1515

1616
// ...and for now neither do we allow or-patterns at the top level of functions.
17-
fn fun1(A | B: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
17+
fn fun1(A | B: E) {}
18+
//~^ ERROR top-level or-patterns are not allowed
1819

1920
fn fun2(| A | B: E) {}
20-
//~^ ERROR an or-pattern parameter must be wrapped in parentheses
21+
//~^ ERROR top-level or-patterns are not allowed
22+
23+
// We don't allow top-level or-patterns before type annotation in let-statements because we
24+
// want to reserve this syntactic space for possible future type ascription.
25+
let A | B: E = A;
26+
//~^ ERROR top-level or-patterns are not allowed
27+
28+
let | A | B: E = A;
29+
//~^ ERROR top-level or-patterns are not allowed
30+
31+
let (A | B): E = A; // ok -- wrapped in parens
2132
}
Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,27 @@
1-
error: an or-pattern parameter must be wrapped in parentheses
1+
error: top-level or-patterns are not allowed in function parameters
22
--> $DIR/or-patterns-syntactic-fail.rs:17:13
33
|
44
LL | fn fun1(A | B: E) {}
55
| ^^^^^ help: wrap the pattern in parentheses: `(A | B)`
66

7-
error: an or-pattern parameter must be wrapped in parentheses
8-
--> $DIR/or-patterns-syntactic-fail.rs:19:13
7+
error: top-level or-patterns are not allowed in function parameters
8+
--> $DIR/or-patterns-syntactic-fail.rs:20:13
99
|
1010
LL | fn fun2(| A | B: E) {}
1111
| ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)`
1212

13+
error: top-level or-patterns are not allowed in `let` bindings
14+
--> $DIR/or-patterns-syntactic-fail.rs:25:9
15+
|
16+
LL | let A | B: E = A;
17+
| ^^^^^ help: wrap the pattern in parentheses: `(A | B)`
18+
19+
error: top-level or-patterns are not allowed in `let` bindings
20+
--> $DIR/or-patterns-syntactic-fail.rs:28:9
21+
|
22+
LL | let | A | B: E = A;
23+
| ^^^^^^^ help: wrap the pattern in parentheses: `(A | B)`
24+
1325
error[E0369]: no implementation for `E | ()`
1426
--> $DIR/or-patterns-syntactic-fail.rs:13:22
1527
|
@@ -20,6 +32,6 @@ LL | let _ = |A | B: E| ();
2032
|
2133
= note: an implementation of `std::ops::BitOr` might be missing for `E`
2234

23-
error: aborting due to 3 previous errors
35+
error: aborting due to 5 previous errors
2436

2537
For more information about this error, try `rustc --explain E0369`.

‎src/test/ui/or-patterns/or-patterns-syntactic-pass.rs‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ accept_pat!([p | q]);
2323
#[cfg(FALSE)]
2424
fn or_patterns() {
2525
// Top level of `let`:
26-
let | A | B;
27-
let A | B;
28-
let A | B: u8;
29-
let A | B = 0;
30-
let A | B: u8 = 0;
26+
let (| A | B);
27+
let (A | B);
28+
let (A | B): u8;
29+
let (A | B) = 0;
30+
let (A | B): u8 = 0;
3131

3232
// Top level of `for`:
3333
for | A | B in 0 {}
@@ -69,10 +69,10 @@ fn or_patterns() {
6969
let [A | B, .. | ..];
7070

7171
// These bind as `(prefix p) | q` as opposed to `prefix (p | q)`:
72-
let box 0 | 1; // Unstable; we *can* the precedence if we want.
73-
let &0 | 1;
74-
let &mut 0 | 1;
75-
let x @ 0 | 1;
76-
let ref x @ 0 | 1;
77-
let ref mut x @ 0 | 1;
72+
let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
73+
let (&0 | 1);
74+
let (&mut 0 | 1);
75+
let (x @ 0 | 1);
76+
let (ref x @ 0 | 1);
77+
let (ref mut x @ 0 | 1);
7878
}

‎src/test/ui/or-patterns/remove-leading-vert.fixed‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn main() {}
99

1010
#[cfg(FALSE)]
1111
fn leading() {
12-
fn fun1( A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
12+
fn fun1( A: E) {} //~ ERROR top-level or-patterns are not allowed
1313
fn fun2( A: E) {} //~ ERROR unexpected `||` before function parameter
1414
let ( | A): E;
1515
let ( | A): (E); //~ ERROR unexpected token `||` in pattern
@@ -40,6 +40,9 @@ fn trailing() {
4040
//~^ ERROR a trailing `|` is not allowed in an or-pattern
4141
}
4242

43+
// These test trailing-vert in `let` bindings, but they also test that we don't emit a
44+
// duplicate suggestion that would confuse rustfix.
45+
4346
let a : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
4447
let a = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
4548
let a ; //~ ERROR a trailing `|` is not allowed in an or-pattern

‎src/test/ui/or-patterns/remove-leading-vert.rs‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fn main() {}
99

1010
#[cfg(FALSE)]
1111
fn leading() {
12-
fn fun1( | A: E) {} //~ ERROR an or-pattern parameter must be wrapped in parentheses
12+
fn fun1( | A: E) {} //~ ERROR top-level or-patterns are not allowed
1313
fn fun2( || A: E) {} //~ ERROR unexpected `||` before function parameter
1414
let ( | A): E;
1515
let ( || A): (E); //~ ERROR unexpected token `||` in pattern
@@ -40,6 +40,9 @@ fn trailing() {
4040
//~^ ERROR a trailing `|` is not allowed in an or-pattern
4141
}
4242

43+
// These test trailing-vert in `let` bindings, but they also test that we don't emit a
44+
// duplicate suggestion that would confuse rustfix.
45+
4346
let a | : u8 = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
4447
let a | = 0; //~ ERROR a trailing `|` is not allowed in an or-pattern
4548
let a | ; //~ ERROR a trailing `|` is not allowed in an or-pattern

‎src/test/ui/or-patterns/remove-leading-vert.stderr‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error: an or-pattern parameter must be wrapped in parentheses
1+
error: top-level or-patterns are not allowed in function parameters
22
--> $DIR/remove-leading-vert.rs:12:14
33
|
44
LL | fn fun1( | A: E) {}
5-
| ^^^ help: remove the leading `|`: `A`
5+
| ^^^ help: remove the `|`: `A`
66

77
error: unexpected `||` before function parameter
88
--> $DIR/remove-leading-vert.rs:13:14
@@ -135,23 +135,23 @@ LL | | A | B | => {}
135135
| while parsing this or-pattern starting here
136136

137137
error: a trailing `|` is not allowed in an or-pattern
138-
--> $DIR/remove-leading-vert.rs:43:11
138+
--> $DIR/remove-leading-vert.rs:46:11
139139
|
140140
LL | let a | : u8 = 0;
141141
| - ^ help: remove the `|`
142142
| |
143143
| while parsing this or-pattern starting here
144144

145145
error: a trailing `|` is not allowed in an or-pattern
146-
--> $DIR/remove-leading-vert.rs:44:11
146+
--> $DIR/remove-leading-vert.rs:47:11
147147
|
148148
LL | let a | = 0;
149149
| - ^ help: remove the `|`
150150
| |
151151
| while parsing this or-pattern starting here
152152

153153
error: a trailing `|` is not allowed in an or-pattern
154-
--> $DIR/remove-leading-vert.rs:45:11
154+
--> $DIR/remove-leading-vert.rs:48:11
155155
|
156156
LL | let a | ;
157157
| - ^ help: remove the `|`

‎src/tools/clippy/clippy_lints/src/loops.rs‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -885,7 +885,9 @@ struct MinifyingSugg<'a>(Sugg<'a>);
885885

886886
impl<'a> MinifyingSugg<'a> {
887887
fn as_str(&self) -> &str {
888-
let Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) = &self.0;
888+
let s = match &self.0 {
889+
Sugg::NonParen(s) | Sugg::MaybeParen(s) | Sugg::BinOp(_, s) => s,
890+
};
889891
s.as_ref()
890892
}
891893

0 commit comments

Comments
 (0)
Please sign in to comment.