From ed084a93433d214edae3ee739444cbd442baf6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 6 Nov 2023 21:06:20 +0000 Subject: [PATCH] When parsing patterns, bubble all errors except reserved idents that aren't likely to appear in for head or match arm --- compiler/rustc_parse/src/parser/pat.rs | 14 ++++- .../edition-keywords-2018-2015-parsing.stderr | 57 +++++++++++++++++- .../edition-keywords-2018-2018-parsing.stderr | 57 +++++++++++++++++- tests/ui/parser/mut-patterns.rs | 2 +- tests/ui/parser/mut-patterns.stderr | 40 ++++++++++++- tests/ui/self/self_type_keyword.stderr | 58 ++++++++++++++++++- 6 files changed, 221 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index ff36ac952ad..ec7c312d03f 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -141,7 +141,19 @@ impl<'a> Parser<'a> { }; // Parse the first pattern (`p_0`). - let mut first_pat = self.parse_pat_no_top_alt(expected, syntax_loc)?; + let mut first_pat = match self.parse_pat_no_top_alt(expected, syntax_loc) { + Ok(pat) => pat, + Err(mut err) + if self.token.is_reserved_ident() + && !self.token.is_keyword(kw::In) + && !self.token.is_keyword(kw::If) => + { + err.emit(); + self.bump(); + self.mk_pat(self.token.span, PatKind::Wild) + } + Err(err) => return Err(err), + }; if rc == RecoverComma::Yes { self.maybe_recover_unexpected_comma( first_pat.span, diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr index 20a58236855..1a4a94e9733 100644 --- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr @@ -9,5 +9,60 @@ help: escape `async` to use it as an identifier LL | let mut r#async = 1; | ++ -error: aborting due to previous error +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:26:13 + | +LL | module::async(); + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | module::r#async(); + | ++ +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:20:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2018-2015-parsing.rs:21:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/auxiliary/edition-kw-macro-2015.rs:27:23 + | +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` + | + ::: $DIR/edition-keywords-2018-2015-parsing.rs:24:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation + +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr index e904165a5ce..19eb7ac9823 100644 --- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr +++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr @@ -9,5 +9,60 @@ help: escape `async` to use it as an identifier LL | let mut r#async = 1; | ++ -error: aborting due to previous error +error: expected identifier, found keyword `async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:26:13 + | +LL | module::async(); + | ^^^^^ expected identifier, found keyword + | +help: escape `async` to use it as an identifier + | +LL | module::r#async(); + | ++ +error: no rules expected the token `r#async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:20:31 + | +LL | r#async = consumes_async!(r#async); + | ^^^^^^^ no rules expected this token in macro call + | +note: while trying to match `async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:17:6 + | +LL | (async) => (1) + | ^^^^^ + +error: no rules expected the token `async` + --> $DIR/edition-keywords-2018-2018-parsing.rs:21:35 + | +LL | r#async = consumes_async_raw!(async); + | ^^^^^ no rules expected this token in macro call + | +note: while trying to match `r#async` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:22:6 + | +LL | (r#async) => (1) + | ^^^^^^^ + +error: macro expansion ends with an incomplete expression: expected one of `move`, `|`, or `||` + --> $DIR/auxiliary/edition-kw-macro-2018.rs:27:23 + | +LL | ($i: ident) => ($i) + | ^ expected one of `move`, `|`, or `||` + | + ::: $DIR/edition-keywords-2018-2018-parsing.rs:24:8 + | +LL | if passes_ident!(async) == 1 {} + | -------------------- in this macro invocation + +error[E0308]: mismatched types + --> $DIR/edition-keywords-2018-2018-parsing.rs:29:33 + | +LL | let _recovery_witness: () = 0; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/mut-patterns.rs b/tests/ui/parser/mut-patterns.rs index 8b83d6ab2f8..f2d2df0af29 100644 --- a/tests/ui/parser/mut-patterns.rs +++ b/tests/ui/parser/mut-patterns.rs @@ -27,7 +27,7 @@ pub fn main() { struct r#yield(u8, u8); let mut mut yield(become, await) = r#yield(0, 0); //~^ ERROR `mut` on a binding may not be repeated - //~| ERROR `mut` must be attached to each individual binding + //~| ERROR `mut` must be followed by a named binding //~| ERROR expected identifier, found reserved keyword `yield` //~| ERROR expected identifier, found reserved keyword `become` //~| ERROR expected identifier, found keyword `await` diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index d91440d7859..6559cf09cdf 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -72,5 +72,43 @@ help: escape `become` to use it as an identifier LL | let mut mut yield(r#become, await) = r#yield(0, 0); | ++ -error: aborting due to 9 previous errors +error: expected identifier, found keyword `await` + --> $DIR/mut-patterns.rs:28:31 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^ expected identifier, found keyword + | +help: escape `await` to use it as an identifier + | +LL | let mut mut yield(become, r#await) = r#yield(0, 0); + | ++ + +error: `mut` must be followed by a named binding + --> $DIR/mut-patterns.rs:28:9 + | +LL | let mut mut yield(become, await) = r#yield(0, 0); + | ^^^^^^^^ help: remove the `mut` prefix + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: `mut` must be attached to each individual binding + --> $DIR/mut-patterns.rs:37:9 + | +LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f })))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))` + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found `x` + --> $DIR/mut-patterns.rs:44:21 + | +LL | let mut $p = 0; + | ^^ expected identifier +... +LL | foo!(x); + | ------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 13 previous errors diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index cdafae381ac..fed853a7e1f 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -10,6 +10,26 @@ error: expected identifier, found keyword `Self` LL | ref Self => (), | ^^^^ expected identifier, found keyword +error: `mut` must be followed by a named binding + --> $DIR/self_type_keyword.rs:16:9 + | +LL | mut Self => (), + | ^^^^ help: remove the `mut` prefix + | + = note: `mut` may be followed by `variable` and `variable @ pattern` + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:19:17 + | +LL | ref mut Self => (), + | ^^^^ expected identifier, found keyword + +error: expected identifier, found keyword `Self` + --> $DIR/self_type_keyword.rs:23:15 + | +LL | Foo { Self } => (), + | ^^^^ expected identifier, found keyword + error: expected identifier, found keyword `Self` --> $DIR/self_type_keyword.rs:31:26 | @@ -34,6 +54,24 @@ error: lifetimes cannot use keyword names LL | struct Bar<'Self>; | ^^^^^ +error: cannot find macro `Self` in this scope + --> $DIR/self_type_keyword.rs:21:9 + | +LL | Self!() => (), + | ^^^^ + +error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope + --> $DIR/self_type_keyword.rs:16:13 + | +LL | mut Self => (), + | ^^^^ not found in this scope + | +note: unit struct `foo::Self` exists but is inaccessible + --> $DIR/self_type_keyword.rs:2:3 + | +LL | struct Self; + | ^^^^^^^^^^^^ not accessible + error[E0392]: parameter `'Self` is never used --> $DIR/self_type_keyword.rs:6:12 | @@ -42,6 +80,22 @@ LL | struct Bar<'Self>; | = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData` -error: aborting due to 7 previous errors +error[E0308]: mismatched types + --> $DIR/self_type_keyword.rs:23:9 + | +LL | match 15 { + | -- this expression has type `{integer}` +... +LL | Foo { Self } => (), + | ^^^^^^^^^^^^ expected integer, found `Foo` -For more information about this error, try `rustc --explain E0392`. +error[E0026]: struct `Foo` does not have a field named `Self` + --> $DIR/self_type_keyword.rs:23:15 + | +LL | Foo { Self } => (), + | ^^^^ struct `Foo` does not have this field + +error: aborting due to 14 previous errors + +Some errors have detailed explanations: E0026, E0308, E0392, E0531. +For more information about an error, try `rustc --explain E0026`.