From b79fc92db3f0264136c3bc3c70b80e8b7b443fc3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 2 Feb 2022 10:33:13 -0800 Subject: [PATCH 1/2] fix ICE when parsing lifetime as function argument --- compiler/rustc_parse/src/parser/expr.rs | 6 ++--- compiler/rustc_typeck/src/check/expr.rs | 24 ++++++++++++------- src/test/ui/parser/issues/issue-93282.rs | 11 +++++++++ src/test/ui/parser/issues/issue-93282.stderr | 14 ++++++++++- .../require-parens-for-chained-comparison.rs | 2 ++ ...quire-parens-for-chained-comparison.stderr | 18 +++++++++++--- 6 files changed, 60 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 0115d498a7fb8..0a9452a83a5e4 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1457,9 +1457,9 @@ 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)) { - // We're probably inside of a `Path<'a>` that needs a turbofish, so suppress the - // "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"); + // We're probably inside of a `Path<'a>` that needs a turbofish + 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(); consume_colon = false; Ok(self.mk_expr_err(lo)) } else { diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 0e1dbc53806ff..82cda5a2f2e73 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -865,14 +865,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), .. }) => { - // We have a situation like `while Some(0) = value.get(0) {`, where `while let` - // was more likely intended. - err.span_suggestion_verbose( - expr.span.shrink_to_lo(), - "you might have meant to use pattern destructuring", - "let ".to_string(), - Applicability::MachineApplicable, - ); + // Check if our lhs is a child of the condition of a while loop + let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| { + self.tcx.hir().find_parent_node(*id) + }) + .take_while(|id| *id != parent) + .any(|id| id == expr.hir_id); + // if it is, then we have a situation like `while Some(0) = value.get(0) {`, + // where `while let` was more likely intended. + if expr_is_ancestor { + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); + } break; } hir::Node::Item(_) diff --git a/src/test/ui/parser/issues/issue-93282.rs b/src/test/ui/parser/issues/issue-93282.rs index 7be8b25363e09..261fcb5f9183e 100644 --- a/src/test/ui/parser/issues/issue-93282.rs +++ b/src/test/ui/parser/issues/issue-93282.rs @@ -1,4 +1,15 @@ fn main() { f<'a,> //~^ ERROR expected + //~| ERROR expected +} + +fn bar(a: usize, b: usize) -> usize { + a + b +} + +fn foo() { + let x = 1; + bar('y, x); + //~^ ERROR expected } diff --git a/src/test/ui/parser/issues/issue-93282.stderr b/src/test/ui/parser/issues/issue-93282.stderr index 20e6c3ed8a8d5..900f21a7ccef4 100644 --- a/src/test/ui/parser/issues/issue-93282.stderr +++ b/src/test/ui/parser/issues/issue-93282.stderr @@ -1,3 +1,9 @@ +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 | @@ -9,5 +15,11 @@ help: use `::<...>` instead of `<...>` to specify lifetime, type, or const argum LL | f::<'a,> | ++ -error: aborting due to previous error +error: expected `while`, `for`, `loop` or `{` after a label + --> $DIR/issue-93282.rs:13:11 + | +LL | bar('y, x); + | ^ expected `while`, `for`, `loop` or `{` after a label + +error: aborting due to 3 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..f29fd7a5472d4 100644 --- a/src/test/ui/parser/require-parens-for-chained-comparison.rs +++ b/src/test/ui/parser/require-parens-for-chained-comparison.rs @@ -22,10 +22,12 @@ fn main() { let _ = f<'_, i8>(); //~^ ERROR expected one of //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected f<'_>(); //~^ comparison operators cannot be chained //~| HELP use `::<...>` instead of `<...>` to specify lifetime, type, or const arguments + //~| ERROR expected let _ = f; //~^ ERROR comparison operators cannot be chained 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 5be9e79ae02d9e61542f12c18c1da70aa1d2d5ff Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 11 Feb 2022 17:48:06 -0800 Subject: [PATCH 2/2] Update expr.rs Revert spurious changes included in PR --- compiler/rustc_typeck/src/check/expr.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_typeck/src/check/expr.rs b/compiler/rustc_typeck/src/check/expr.rs index 82cda5a2f2e73..0e1dbc53806ff 100644 --- a/compiler/rustc_typeck/src/check/expr.rs +++ b/compiler/rustc_typeck/src/check/expr.rs @@ -865,22 +865,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), .. }) => { - // Check if our lhs is a child of the condition of a while loop - let expr_is_ancestor = std::iter::successors(Some(lhs.hir_id), |id| { - self.tcx.hir().find_parent_node(*id) - }) - .take_while(|id| *id != parent) - .any(|id| id == expr.hir_id); - // if it is, then we have a situation like `while Some(0) = value.get(0) {`, - // where `while let` was more likely intended. - if expr_is_ancestor { - err.span_suggestion_verbose( - expr.span.shrink_to_lo(), - "you might have meant to use pattern destructuring", - "let ".to_string(), - Applicability::MachineApplicable, - ); - } + // We have a situation like `while Some(0) = value.get(0) {`, where `while let` + // was more likely intended. + err.span_suggestion_verbose( + expr.span.shrink_to_lo(), + "you might have meant to use pattern destructuring", + "let ".to_string(), + Applicability::MachineApplicable, + ); break; } hir::Node::Item(_)