Rollup merge of #107602 - estebank:anon-enum-access, r=compiler-errors

Parse and recover from type ascription in patterns

Reintroduce part of #106960, which was reverted in #107478.

r? `@compiler-errors`
This commit is contained in:
Matthias Krüger 2023-02-03 06:30:24 +01:00 committed by GitHub
commit 743ca67edf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 164 additions and 39 deletions

View file

@ -2405,26 +2405,42 @@ impl<'a> Parser<'a> {
if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..))
|| !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
{ {
let mut snapshot_type = self.create_snapshot_for_diagnostic();
snapshot_type.bump(); // `:`
match snapshot_type.parse_ty() {
Err(inner_err) => {
inner_err.cancel();
}
Ok(ty) => {
let Err(mut err) = self.expected_one_of_not_found(&[], &[]) else {
return first_pat;
};
err.span_label(ty.span, "specifying the type of a pattern isn't supported");
self.restore_snapshot(snapshot_type);
let span = first_pat.span.to(ty.span);
first_pat = self.mk_pat(span, PatKind::Wild);
err.emit();
}
}
return first_pat; return first_pat;
} }
// The pattern looks like it might be a path with a `::` -> `:` typo: // The pattern looks like it might be a path with a `::` -> `:` typo:
// `match foo { bar:baz => {} }` // `match foo { bar:baz => {} }`
let span = self.token.span; let colon_span = self.token.span;
// We only emit "unexpected `:`" error here if we can successfully parse the // We only emit "unexpected `:`" error here if we can successfully parse the
// whole pattern correctly in that case. // whole pattern correctly in that case.
let snapshot = self.create_snapshot_for_diagnostic(); let mut snapshot_pat = self.create_snapshot_for_diagnostic();
let mut snapshot_type = self.create_snapshot_for_diagnostic();
// Create error for "unexpected `:`". // Create error for "unexpected `:`".
match self.expected_one_of_not_found(&[], &[]) { match self.expected_one_of_not_found(&[], &[]) {
Err(mut err) => { Err(mut err) => {
self.bump(); // Skip the `:`. // Skip the `:`.
match self.parse_pat_no_top_alt(expected) { snapshot_pat.bump();
snapshot_type.bump();
match snapshot_pat.parse_pat_no_top_alt(expected) {
Err(inner_err) => { Err(inner_err) => {
// Carry on as if we had not done anything, callers will emit a
// reasonable error.
inner_err.cancel(); inner_err.cancel();
err.cancel();
self.restore_snapshot(snapshot);
} }
Ok(mut pat) => { Ok(mut pat) => {
// We've parsed the rest of the pattern. // We've parsed the rest of the pattern.
@ -2488,8 +2504,8 @@ impl<'a> Parser<'a> {
_ => {} _ => {}
} }
if show_sugg { if show_sugg {
err.span_suggestion( err.span_suggestion_verbose(
span, colon_span.until(self.look_ahead(1, |t| t.span)),
"maybe write a path separator here", "maybe write a path separator here",
"::", "::",
Applicability::MaybeIncorrect, Applicability::MaybeIncorrect,
@ -2497,13 +2513,24 @@ impl<'a> Parser<'a> {
} else { } else {
first_pat = self.mk_pat(new_span, PatKind::Wild); first_pat = self.mk_pat(new_span, PatKind::Wild);
} }
err.emit(); self.restore_snapshot(snapshot_pat);
} }
} }
match snapshot_type.parse_ty() {
Err(inner_err) => {
inner_err.cancel();
}
Ok(ty) => {
err.span_label(ty.span, "specifying the type of a pattern isn't supported");
self.restore_snapshot(snapshot_type);
let new_span = first_pat.span.to(ty.span);
first_pat = self.mk_pat(new_span, PatKind::Wild);
}
}
err.emit();
} }
_ => { _ => {
// Carry on as if we had not done anything. This should be unreachable. // Carry on as if we had not done anything. This should be unreachable.
self.restore_snapshot(snapshot);
} }
}; };
first_pat first_pat

View file

@ -68,7 +68,6 @@ fn main() {
Foo:Bar::Baz => {} Foo:Bar::Baz => {}
//~^ ERROR: expected one of //~^ ERROR: expected one of
//~| HELP: maybe write a path separator here //~| HELP: maybe write a path separator here
//~| ERROR: failed to resolve: `Bar` is a variant, not a module
} }
match myfoo { match myfoo {
Foo::Bar => {} Foo::Bar => {}

View file

@ -2,89 +2,118 @@ error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:17:12 --> $DIR/issue-87086-colon-path-sep.rs:17:12
| |
LL | Foo:Bar => {} LL | Foo:Bar => {}
| ^ | ^--- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | Foo::Bar => {}
| ~~
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:` error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `{`, or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:23:17 --> $DIR/issue-87086-colon-path-sep.rs:23:17
| |
LL | qux::Foo:Bar => {} LL | qux::Foo:Bar => {}
| ^ | ^--- specifying the type of a pattern isn't supported
| | | |
| expected one of 8 possible tokens | expected one of 8 possible tokens
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | qux::Foo::Bar => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:29:12 --> $DIR/issue-87086-colon-path-sep.rs:29:12
| |
LL | qux:Foo::Baz => {} LL | qux:Foo::Baz => {}
| ^ | ^-------- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | qux::Foo::Baz => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:35:12 --> $DIR/issue-87086-colon-path-sep.rs:35:12
| |
LL | qux: Foo::Baz if true => {} LL | qux: Foo::Baz if true => {}
| ^ | ^ -------- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | qux::Foo::Baz if true => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:40:15 --> $DIR/issue-87086-colon-path-sep.rs:40:15
| |
LL | if let Foo:Bar = f() { LL | if let Foo:Bar = f() {
| ^ | ^--- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | if let Foo::Bar = f() {
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:48:16 --> $DIR/issue-87086-colon-path-sep.rs:48:16
| |
LL | ref qux: Foo::Baz => {} LL | ref qux: Foo::Baz => {}
| ^ | ^ -------- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | ref qux::Foo::Baz => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:57:16 --> $DIR/issue-87086-colon-path-sep.rs:57:16
| |
LL | mut qux: Foo::Baz => {} LL | mut qux: Foo::Baz => {}
| ^ | ^ -------- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | mut qux::Foo::Baz => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:68:12 --> $DIR/issue-87086-colon-path-sep.rs:68:12
| |
LL | Foo:Bar::Baz => {} LL | Foo:Bar::Baz => {}
| ^ | ^-------- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::` |
help: maybe write a path separator here
|
LL | Foo::Bar::Baz => {}
| ~~
error: expected one of `@` or `|`, found `:` error: expected one of `@` or `|`, found `:`
--> $DIR/issue-87086-colon-path-sep.rs:75:12 --> $DIR/issue-87086-colon-path-sep.rs:74:12
| |
LL | Foo:Bar => {} LL | Foo:Bar => {}
| ^ | ^--- specifying the type of a pattern isn't supported
| | | |
| expected one of `@` or `|` | expected one of `@` or `|`
| help: maybe write a path separator here: `::`
error[E0433]: failed to resolve: `Bar` is a variant, not a module
--> $DIR/issue-87086-colon-path-sep.rs:68:13
| |
LL | Foo:Bar::Baz => {} help: maybe write a path separator here
| ^^^ `Bar` is a variant, not a module |
LL | Foo::Bar => {}
| ~~
error: aborting due to 10 previous errors error: aborting due to 9 previous errors
For more information about this error, try `rustc --explain E0433`.

View file

@ -0,0 +1,16 @@
fn foo(x: bool) -> i32 {
match x {
x: i32 => x, //~ ERROR expected
//~^ ERROR mismatched types
true => 42.,
false => 0.333,
}
}
fn main() {
match foo(true) {
42: i32 => (), //~ ERROR expected
_: f64 => (), //~ ERROR expected
x: i32 => (), //~ ERROR expected
}
}

View file

@ -0,0 +1,54 @@
error: expected one of `@` or `|`, found `:`
--> $DIR/type-ascription-in-pattern.rs:3:10
|
LL | x: i32 => x,
| ^ --- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
|
help: maybe write a path separator here
|
LL | x::i32 => x,
| ~~
error: expected one of `...`, `..=`, `..`, or `|`, found `:`
--> $DIR/type-ascription-in-pattern.rs:12:11
|
LL | 42: i32 => (),
| ^ --- specifying the type of a pattern isn't supported
| |
| expected one of `...`, `..=`, `..`, or `|`
error: expected `|`, found `:`
--> $DIR/type-ascription-in-pattern.rs:13:10
|
LL | _: f64 => (),
| ^ --- specifying the type of a pattern isn't supported
| |
| expected `|`
error: expected one of `@` or `|`, found `:`
--> $DIR/type-ascription-in-pattern.rs:14:10
|
LL | x: i32 => (),
| ^ --- specifying the type of a pattern isn't supported
| |
| expected one of `@` or `|`
|
help: maybe write a path separator here
|
LL | x::i32 => (),
| ~~
error[E0308]: mismatched types
--> $DIR/type-ascription-in-pattern.rs:3:19
|
LL | fn foo(x: bool) -> i32 {
| --- expected `i32` because of return type
LL | match x {
LL | x: i32 => x,
| ^ expected `i32`, found `bool`
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0308`.