From a090bb1dea18af72dce2195fa4de396bcb51061b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Jan 2022 10:47:10 -0800 Subject: [PATCH 1/2] Remove delayed bug when encountering label in bad turbofish --- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 5 +++-- src/test/ui/parser/issues/issue-93282.rs | 5 +++++ src/test/ui/parser/issues/issue-93282.stderr | 19 +++++++++++++++++++ .../require-parens-for-chained-comparison.rs | 2 ++ ...quire-parens-for-chained-comparison.stderr | 18 +++++++++++++++--- 6 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/parser/issues/issue-93282.rs create mode 100644 src/test/ui/parser/issues/issue-93282.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index c41f2d3299bf7..15f29d083dbe1 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -737,7 +737,7 @@ impl<'a> Parser<'a> { "::".to_string(), Applicability::MaybeIncorrect, ); - if self.check(&TokenKind::Semi) { + if matches!(self.token.kind, token::Semi | token::CloseDelim(_)) { turbo_err.emit(); *expr = self.mk_expr_err(expr.span); return Ok(()); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 26284728ff2c6..19ad1b3cec8a3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1448,6 +1448,8 @@ impl<'a> Parser<'a> { let lo = label.ident.span; let label = Some(label); let ate_colon = self.eat(&token::Colon); + let msg = "expected `while`, `for`, `loop` or `{` after a label"; + let expr = if self.eat_keyword(kw::While) { self.parse_while_expr(label, lo, attrs) } else if self.eat_keyword(kw::For) { @@ -1457,13 +1459,12 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) { + self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); // We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the // "must be followed by a colon" error. - self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly"); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { - let msg = "expected `while`, `for`, `loop` or `{` after a label"; self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); // Continue as an expression in an effort to recover on `'label: non_block_expr`. self.parse_expr() diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs new file mode 100644 index 0000000000000..85a1186686708 --- /dev/null +++ b/src/test/ui/parser/issues/issue-93282.rs @@ -0,0 +1,5 @@ +fn main() { + f<'a,> + //~^ ERROR expected + //~| ERROR expected +} diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr new file mode 100644 index 0000000000000..a66beacc81d0e --- /dev/null +++ b/src/test/ui/parser/issues/issue-93282.stderr @@ -0,0 +1,19 @@ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:2:9 + | +LL | f<'a,> + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `{`, `}`, or an operator, found `,` + --> $DIR/issue-93282.rs:2:9 + | +LL | f<'a,> + | ^ expected one of 10 possible tokens + | +help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + | +LL | f::<'a,> + | ++ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index 68636f6b907ef..aaa703f763e14 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -21,10 +21,12 @@ fn main() { let _ = f<'_, i8>(); //~^ ERROR expected one of + //~| ERROR expected //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments f<'_>(); //~^ comparison operators cannot be chained + //~| ERROR expected //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments let _ = f; diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index cde6f8c674f4b..92d700753dc1b 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -53,6 +53,12 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::(); | ++ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:22:17 + | +LL | let _ = f<'_, i8>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,` --> $DIR/require-parens-for-chained-comparison.rs:22:17 | @@ -64,8 +70,14 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::<'_, i8>(); | ++ +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/require-parens-for-chained-comparison.rs:27:9 + | +LL | f<'_>(); + | ^ expected `while`, `for`, `loop` or `{` after a label + error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:26:6 + --> $DIR/require-parens-for-chained-comparison.rs:27:6 | LL | f<'_>(); | ^ ^ @@ -76,7 +88,7 @@ LL | f::<'_>(); | ++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:30:14 + --> $DIR/require-parens-for-chained-comparison.rs:32:14 | LL | let _ = f; | ^ ^ @@ -84,5 +96,5 @@ LL | let _ = f; = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 8 previous errors +error: aborting due to 10 previous errors From 37bed05986db600d6d8028af981632138dd7c7b2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 25 Jan 2022 11:08:37 -0800 Subject: [PATCH 2/2] delay the bug once again, generalize turbofish suggestion --- .../rustc_parse/src/parser/diagnostics.rs | 30 ++++++++----------- compiler/rustc_parse/src/parser/expr.rs | 7 ++--- src/test/ui/parser/issues/issue-93282.rs | 1 - src/test/ui/parser/issues/issue-93282.stderr | 8 +---- .../require-parens-for-chained-comparison.rs | 2 -- ...quire-parens-for-chained-comparison.stderr | 18 ++--------- 6 files changed, 19 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 15f29d083dbe1..17bac362ec81f 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -731,28 +731,22 @@ impl<'a> Parser<'a> { match x { Ok((_, _, false)) => { if self.eat(&token::Gt) { - let turbo_err = e.span_suggestion_verbose( + e.span_suggestion_verbose( binop.span.shrink_to_lo(), TURBOFISH_SUGGESTION_STR, "::".to_string(), Applicability::MaybeIncorrect, - ); - if matches!(self.token.kind, token::Semi | token::CloseDelim(_)) { - turbo_err.emit(); - *expr = self.mk_expr_err(expr.span); - return Ok(()); - } else { - match self.parse_expr() { - Ok(_) => { - turbo_err.emit(); - *expr = self - .mk_expr_err(expr.span.to(self.prev_token.span)); - return Ok(()); - } - Err(mut err) => { - turbo_err.cancel(); - err.cancel(); - } + ) + .emit(); + match self.parse_expr() { + Ok(_) => { + *expr = + self.mk_expr_err(expr.span.to(self.prev_token.span)); + return Ok(()); + } + Err(mut err) => { + *expr = self.mk_expr_err(expr.span); + err.cancel(); } } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 19ad1b3cec8a3..693dd0051dad1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1448,8 +1448,6 @@ impl<'a> Parser<'a> { let lo = label.ident.span; let label = Some(label); let ate_colon = self.eat(&token::Colon); - let msg = "expected `while`, `for`, `loop` or `{` after a label"; - let expr = if self.eat_keyword(kw::While) { self.parse_while_expr(label, lo, attrs) } else if self.eat_keyword(kw::For) { @@ -1459,12 +1457,13 @@ impl<'a> Parser<'a> { } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else if !ate_colon && (self.check(&TokenKind::Comma) || self.check(&TokenKind::Gt)) { - self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); // We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the - // "must be followed by a colon" error. + // "must be followed by a colon" error, and the "expected one of" error. + self.diagnostic().delay_span_bug(lo, "this label wasn't parsed correctly"); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { + let msg = "expected `while`, `for`, `loop` or `{` after a label"; self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); // Continue as an expression in an effort to recover on `'label: non_block_expr`. self.parse_expr() diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs index 85a1186686708..7be8b25363e09 100644 --- a/src/test/ui/parser/issues/issue-93282.rs +++ b/src/test/ui/parser/issues/issue-93282.rs @@ -1,5 +1,4 @@ fn main() { f<'a,> //~^ ERROR expected - //~| ERROR expected } diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr index a66beacc81d0e..20e6c3ed8a8d5 100644 --- a/src/test/ui/parser/issues/issue-93282.stderr +++ b/src/test/ui/parser/issues/issue-93282.stderr @@ -1,9 +1,3 @@ -error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/issue-93282.rs:2:9 - | -LL | f<'a,> - | ^ expected `while`, `for`, `loop` or `{` after a label - error: expected one of `.`, `:`, `;`, `?`, `for`, `loop`, `while`, `{`, `}`, or an operator, found `,` --> $DIR/issue-93282.rs:2:9 | @@ -15,5 +9,5 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | f::<'a,> | ++ -error: aborting due to 2 previous errors +error: aborting due to previous error diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.rs b/src/test/ui/parser/require-parens-for-chained-comparison.rs index aaa703f763e14..68636f6b907ef 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -21,12 +21,10 @@ fn main() { let _ = f<'_, i8>(); //~^ ERROR expected one of - //~| ERROR expected //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments f<'_>(); //~^ comparison operators cannot be chained - //~| ERROR expected //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments let _ = f; diff --git a/src/test/ui/parser/require-parens-for-chained-comparison.stderr b/src/test/ui/parser/require-parens-for-chained-comparison.stderr index 92d700753dc1b..cde6f8c674f4b 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.stderr +++ b/src/test/ui/parser/require-parens-for-chained-comparison.stderr @@ -53,12 +53,6 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::(); | ++ -error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/require-parens-for-chained-comparison.rs:22:17 - | -LL | let _ = f<'_, i8>(); - | ^ expected `while`, `for`, `loop` or `{` after a label - error: expected one of `.`, `:`, `;`, `?`, `else`, `for`, `loop`, `while`, `{`, or an operator, found `,` --> $DIR/require-parens-for-chained-comparison.rs:22:17 | @@ -70,14 +64,8 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | let _ = f::<'_, i8>(); | ++ -error: expected `while`, `for`, `loop` or `{` after a label - --> $DIR/require-parens-for-chained-comparison.rs:27:9 - | -LL | f<'_>(); - | ^ expected `while`, `for`, `loop` or `{` after a label - error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:27:6 + --> $DIR/require-parens-for-chained-comparison.rs:26:6 | LL | f<'_>(); | ^ ^ @@ -88,7 +76,7 @@ LL | f::<'_>(); | ++ error: comparison operators cannot be chained - --> $DIR/require-parens-for-chained-comparison.rs:32:14 + --> $DIR/require-parens-for-chained-comparison.rs:30:14 | LL | let _ = f; | ^ ^ @@ -96,5 +84,5 @@ LL | let _ = f; = help: use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments = help: or use `(...)` if you meant to specify fn arguments -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors