Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions compiler/rustc_parse/src/parser/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2929,12 +2929,26 @@ impl<'a> Parser<'a> {
// parentheses in what should have been a tuple pattern; return a
// suggestion-enhanced error here rather than choking on the comma later.
let comma_span = self.token.span;
// `EitherTupleOrPipe` is only ever used for the pattern of a `match` arm, which has to be
// followed by either a `=>` or an `if` guard. Take a snapshot so that we can rewind to the
// comma if neither of those follows the comma-separated list.
let snapshot = (rt == CommaRecoveryMode::EitherTupleOrPipe)
.then(|| self.create_snapshot_for_diagnostic());
self.bump();
if let Err(err) = self.skip_pat_list() {
// We didn't expect this to work anyway; we just wanted to advance to the
// end of the comma-sequence so we know the span to suggest parenthesizing.
err.cancel();
}
if let Some(snapshot) = snapshot
&& self.token != token::FatArrow
&& !self.token.is_keyword(kw::If)
{
// Neither parenthesising the patterns nor joining them with `|` would give the arm a
// body, so the comma is far more likely to stand in for a missing `=> <body>`.
self.restore_snapshot(snapshot);
return Ok(());
}
let seq_span = lo.to(self.prev_token.span);
let mut err = self.dcx().struct_span_err(comma_span, "unexpected `,` in pattern");
err.multipart_suggestion(
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_parse/src/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub enum RecoverColon {
#[derive(PartialEq, Copy, Clone)]
pub enum CommaRecoveryMode {
LikelyTuple,
/// Only used for the pattern of a `match` arm, which the recovery relies on: it gives up when
/// the comma-separated list is not followed by the `=>` or the guard of an arm.
EitherTupleOrPipe,
}

Expand Down
3 changes: 2 additions & 1 deletion tests/ui/feature-gates/feature-gate-never_patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ fn main() {
match Some(0) {
None => {}
Some(_),
//~^ ERROR unexpected `,` in pattern
//~^ ERROR `match` arm with no body
}
match Some(0) {
None => {}
Expand Down Expand Up @@ -59,6 +59,7 @@ fn main() {

// Check that the gate operates even behind `cfg`.
match Some(0) {
//~^ ERROR non-exhaustive patterns: `Some(_)` not covered
None => {}
#[cfg(false)]
Some(_)
Expand Down
54 changes: 34 additions & 20 deletions tests/ui/feature-gates/feature-gate-never_patterns.stderr
Original file line number Diff line number Diff line change
@@ -1,19 +1,3 @@
error: unexpected `,` in pattern
--> $DIR/feature-gate-never_patterns.rs:33:16
|
LL | Some(_),
| ^
|
help: try adding parentheses to match on a tuple...
|
LL | (Some(_),)
| + +
help: ...or a vertical bar to match on alternatives
|
LL - Some(_),
LL + Some(_) |
|

error[E0658]: `!` patterns are experimental
--> $DIR/feature-gate-never_patterns.rs:8:24
|
Expand Down Expand Up @@ -54,6 +38,17 @@ LL | ! => {}
= help: add `#![feature(never_patterns)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:33:9
|
LL | Some(_),
| ^^^^^^^
|
help: add a body after the pattern
|
LL | Some(_) => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:38:9
|
Expand Down Expand Up @@ -108,7 +103,7 @@ LL | Err(!) if false,
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:64:9
--> $DIR/feature-gate-never_patterns.rs:65:9
|
LL | Some(_)
| ^^^^^^^
Expand All @@ -119,7 +114,7 @@ LL | Some(_) => { todo!() }
| ++++++++++++++

error: `match` arm with no body
--> $DIR/feature-gate-never_patterns.rs:70:9
--> $DIR/feature-gate-never_patterns.rs:71:9
|
LL | Some(_) if false
| ^^^^^^^^^^^^^^^^
Expand All @@ -135,6 +130,25 @@ error: a guard on a never pattern will never be run
LL | Err(!) if false,
| ^^^^^ help: remove this guard

error: aborting due to 13 previous errors
error[E0004]: non-exhaustive patterns: `Some(_)` not covered
--> $DIR/feature-gate-never_patterns.rs:61:11
|
LL | match Some(0) {
| ^^^^^^^ pattern `Some(_)` not covered
|
note: `Option<i32>` defined here
--> $SRC_DIR/core/src/option.rs:LL:COL
::: $SRC_DIR/core/src/option.rs:LL:COL
|
= note: not covered
= note: the matched value is of type `Option<i32>`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
|
LL ~ None => {},
LL + Some(_) => todo!()
|

error: aborting due to 14 previous errors

For more information about this error, try `rustc --explain E0658`.
Some errors have detailed explanations: E0004, E0658.
For more information about an error, try `rustc --explain E0004`.
10 changes: 9 additions & 1 deletion tests/ui/parser/match-arm-without-body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@ fn main() {
_ => {}
//~^ ERROR expected one of
}
match Some(false) {
Some(_),
//~^ ERROR `match` arm with no body
//~| HELP add a body after the pattern
}
// The comma is only taken for a missing body when parenthesising the patterns (or joining
// them with `|`) wouldn't give the arm a body either.
match Some(false) {
Some(_),
//~^ ERROR unexpected `,` in pattern
//~| HELP try adding parentheses to match on a tuple
//~| HELP or a vertical bar to match on alternative
_ => {}
}
match Some(false) {
Some(_),
//~^ ERROR unexpected `,` in pattern
//~| HELP try adding parentheses to match on a tuple
//~| HELP or a vertical bar to match on alternative
_ => {}
None if true => {}
}
match Some(false) {
Some(_) if true
Expand Down
45 changes: 30 additions & 15 deletions tests/ui/parser/match-arm-without-body.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,27 @@ LL | _ => {}
| ^ unexpected token

error: unexpected `,` in pattern
--> $DIR/match-arm-without-body.rs:17:16
--> $DIR/match-arm-without-body.rs:24:16
|
LL | Some(_),
| ^
|
help: try adding parentheses to match on a tuple...
|
LL | (Some(_),)
| + +
LL ~ (Some(_),
LL |
LL |
LL |
LL ~ _) => {}
|
help: ...or a vertical bar to match on alternatives
|
LL - Some(_),
LL + Some(_) |
|

error: unexpected `,` in pattern
--> $DIR/match-arm-without-body.rs:23:16
--> $DIR/match-arm-without-body.rs:31:16
|
LL | Some(_),
| ^
Expand All @@ -34,7 +38,7 @@ LL ~ (Some(_),
LL |
LL |
LL |
LL ~ _) => {}
LL ~ None) if true => {}
|
help: ...or a vertical bar to match on alternatives
|
Expand All @@ -43,15 +47,15 @@ LL + Some(_) |
|

error: expected one of `.`, `=>`, `?`, or an operator, found reserved identifier `_`
--> $DIR/match-arm-without-body.rs:36:9
--> $DIR/match-arm-without-body.rs:44:9
|
LL | Some(_) if true
| - expected one of `.`, `=>`, `?`, or an operator
LL | _ => {}
| ^ unexpected token

error: expected `,` following `match` arm
--> $DIR/match-arm-without-body.rs:66:15
--> $DIR/match-arm-without-body.rs:74:15
|
LL | pat!()
| ^
Expand All @@ -73,7 +77,18 @@ LL | Some(_) => { todo!() }
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:30:9
--> $DIR/match-arm-without-body.rs:17:9
|
LL | Some(_),
| ^^^^^^^
|
help: add a body after the pattern
|
LL | Some(_) => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:38:9
|
LL | Some(_) if true
| ^^^^^^^^^^^^^^^
Expand All @@ -84,7 +99,7 @@ LL | Some(_) if true => { todo!() }
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:40:9
--> $DIR/match-arm-without-body.rs:48:9
|
LL | Some(_) if true,
| ^^^^^^^^^^^^^^^
Expand All @@ -95,7 +110,7 @@ LL | Some(_) if true => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:45:9
--> $DIR/match-arm-without-body.rs:53:9
|
LL | Some(_) if true,
| ^^^^^^^^^^^^^^^
Expand All @@ -106,7 +121,7 @@ LL | Some(_) if true => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:51:9
--> $DIR/match-arm-without-body.rs:59:9
|
LL | pat!()
| ^^^^^^
Expand All @@ -117,7 +132,7 @@ LL | pat!() => { todo!() }
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:56:9
--> $DIR/match-arm-without-body.rs:64:9
|
LL | pat!(),
| ^^^^^^
Expand All @@ -128,7 +143,7 @@ LL | pat!() => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:61:9
--> $DIR/match-arm-without-body.rs:69:9
|
LL | pat!() if true,
| ^^^^^^^^^^^^^^
Expand All @@ -139,7 +154,7 @@ LL | pat!() if true => { todo!() },
| ++++++++++++++

error: `match` arm with no body
--> $DIR/match-arm-without-body.rs:72:9
--> $DIR/match-arm-without-body.rs:80:9
|
LL | pat!(),
| ^^^^^^
Expand All @@ -149,5 +164,5 @@ help: add a body after the pattern
LL | pat!() => { todo!() },
| ++++++++++++++

error: aborting due to 13 previous errors
error: aborting due to 14 previous errors

Loading