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:
commit
743ca67edf
5 changed files with 164 additions and 39 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
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();
|
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
|
||||||
|
|
|
@ -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 => {}
|
||||||
|
|
|
@ -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`.
|
|
||||||
|
|
16
tests/ui/parser/type-ascription-in-pattern.rs
Normal file
16
tests/ui/parser/type-ascription-in-pattern.rs
Normal 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
|
||||||
|
}
|
||||||
|
}
|
54
tests/ui/parser/type-ascription-in-pattern.stderr
Normal file
54
tests/ui/parser/type-ascription-in-pattern.stderr
Normal 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`.
|
Loading…
Add table
Add a link
Reference in a new issue