From 70ee7a685ef6f2d16109ae1573cb048f8f8ea088 Mon Sep 17 00:00:00 2001 From: Camelid Date: Tue, 20 Oct 2020 16:48:04 -0700 Subject: [PATCH 1/2] Suggest adding missing braces in `const` block pattern Previously it would only suggest wrapping the code in braces in regular expressions; now it does it in patterns too. This is a squashed rebase of #78173 --- compiler/rustc_parse/src/parser/expr.rs | 4 +-- compiler/rustc_parse/src/parser/mod.rs | 3 +-- compiler/rustc_parse/src/parser/pat.rs | 10 ++++--- compiler/rustc_parse/src/parser/stmt.rs | 10 ++++--- tests/ui/parser/bad-if-statements.stderr | 4 --- tests/ui/parser/block-no-opening-brace.rs | 5 ++-- tests/ui/parser/block-no-opening-brace.stderr | 26 +++++++++++-------- .../ui/parser/keyword-const-as-identifier.rs | 5 ++-- .../parser/keyword-const-as-identifier.stderr | 11 +++----- 9 files changed, 38 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 93c76c47f060b..02985b2def6a1 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1495,8 +1495,8 @@ impl<'a> Parser<'a> { err }, ) - } else if this.check_inline_const(0) { - this.parse_const_block(lo, false) + } else if this.eat_keyword(exp!(Const)) { + this.parse_const_block(lo.to(this.prev_token.span), false) } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b2e902513672d..526fab0705a96 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1281,9 +1281,8 @@ impl<'a> Parser<'a> { } } - /// Parses inline const expressions. + /// Parses inline const expressions. The `const` keyword was already eaten. fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { - self.expect_keyword(exp!(Const))?; let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { id: DUMMY_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 64653ee2a04c9..e87de901ecbc3 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -779,9 +779,9 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? } else if self.eat_keyword(exp!(Box)) { self.parse_pat_box()? - } else if self.check_inline_const(0) { - // Parse `const pat` - let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; + } else if self.eat_keyword(exp!(Const)) { + // Parse `const { pat }` + let const_expr = self.parse_const_block(lo.to(self.prev_token.span), true)?; if let Some(re) = self.parse_range_end() { self.parse_pat_range_begin_with(const_expr, re)? @@ -1268,7 +1268,9 @@ impl<'a> Parser<'a> { .then_some(self.prev_token.span); let bound = if self.check_inline_const(0) { - self.parse_const_block(self.token.span, true) + let _eaten = self.eat_keyword(exp!(Const)); + debug_assert!(_eaten); + self.parse_const_block(self.prev_token.span, true) } else if self.check_path() { let lo = self.token.span; let (qself, path) = if self.eat_lt() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index c37cb0881c3f1..666acfd051e1a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -538,15 +538,19 @@ impl<'a> Parser<'a> { // // the place-inside-a-block suggestion would be more likely wrong than right. // + // But we don't want to trigger this if we just parsed a pattern, + // so this only triggers if the current token is neither `=>` nor `=`. + // // FIXME(compiler-errors): this should probably parse an arbitrary expr and not // just lookahead one token, so we can see if there's a brace after _that_, // since we want to protect against: // `if 1 1 + 1 {` being suggested as `if { 1 } 1 + 1 {` // + + Ok(Some(_)) - if (!self.token.is_keyword(kw::Else) - && self.look_ahead(1, |t| t == &token::OpenBrace)) - || do_not_suggest_help => {} + if do_not_suggest_help + || (self.token != token::FatArrow + && self.token != token::Eq + && self.look_ahead(1, |t| t == &token::OpenBrace)) => {} // Do not suggest `if foo println!("") {;}` (as would be seen in test for #46836). Ok(Some(Stmt { kind: StmtKind::Empty, .. })) => {} Ok(Some(stmt)) => { diff --git a/tests/ui/parser/bad-if-statements.stderr b/tests/ui/parser/bad-if-statements.stderr index 320b1176993d8..c2a4122064f3e 100644 --- a/tests/ui/parser/bad-if-statements.stderr +++ b/tests/ui/parser/bad-if-statements.stderr @@ -65,10 +65,6 @@ note: the `if` expression is missing a block after this condition | LL | if true x else {} | ^^^^ -help: you might have meant to write this as part of a block - | -LL | if true { x } else {} - | + + error: this `if` expression is missing a block after the condition --> $DIR/bad-if-statements.rs:34:5 diff --git a/tests/ui/parser/block-no-opening-brace.rs b/tests/ui/parser/block-no-opening-brace.rs index ea5a98ff6fc1e..d1fbce01e42bd 100644 --- a/tests/ui/parser/block-no-opening-brace.rs +++ b/tests/ui/parser/block-no-opening-brace.rs @@ -35,7 +35,7 @@ fn in_async() { // FIXME(#78168) fn in_const() { - let x = const 2; //~ ERROR expected expression, found keyword `const` + let x = const 2; //~ ERROR expected `{`, found `2` } // FIXME(#78168) @@ -43,7 +43,6 @@ fn in_const_in_match() { let x = 2; match x { const 2 => {} - //~^ ERROR expected identifier, found keyword `const` - //~| ERROR expected one of `=>`, `if`, or `|`, found `2` + //~^ ERROR expected `{`, found `2` } } diff --git a/tests/ui/parser/block-no-opening-brace.stderr b/tests/ui/parser/block-no-opening-brace.stderr index cf9eeba573dc8..ee12f77f9a0cb 100644 --- a/tests/ui/parser/block-no-opening-brace.stderr +++ b/tests/ui/parser/block-no-opening-brace.stderr @@ -51,23 +51,27 @@ LL | async LL | let x = 0; | ^^^ unexpected token -error: expected expression, found keyword `const` - --> $DIR/block-no-opening-brace.rs:38:13 +error: expected `{`, found `2` + --> $DIR/block-no-opening-brace.rs:38:19 | LL | let x = const 2; - | ^^^^^ expected expression - -error: expected identifier, found keyword `const` - --> $DIR/block-no-opening-brace.rs:45:9 + | ^ expected `{` | -LL | const 2 => {} - | ^^^^^ expected identifier, found keyword +help: you might have meant to write this as part of a block + | +LL | let x = const { 2 }; + | + + -error: expected one of `=>`, `if`, or `|`, found `2` +error: expected `{`, found `2` --> $DIR/block-no-opening-brace.rs:45:15 | LL | const 2 => {} - | ^ expected one of `=>`, `if`, or `|` + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | const { 2 } => {} + | + + -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/parser/keyword-const-as-identifier.rs b/tests/ui/parser/keyword-const-as-identifier.rs index 6a2d926bf5796..220fc3ca06cdf 100644 --- a/tests/ui/parser/keyword-const-as-identifier.rs +++ b/tests/ui/parser/keyword-const-as-identifier.rs @@ -1,5 +1,4 @@ -// This file was auto-generated using 'src/etc/generate-keyword-tests.py const' - fn main() { - let const = "foo"; //~ error: expected identifier, found keyword `const` + let const = "foo"; + //~^ ERROR expected `{`, found `=` } diff --git a/tests/ui/parser/keyword-const-as-identifier.stderr b/tests/ui/parser/keyword-const-as-identifier.stderr index 61e454174dd78..875740d8d4e0c 100644 --- a/tests/ui/parser/keyword-const-as-identifier.stderr +++ b/tests/ui/parser/keyword-const-as-identifier.stderr @@ -1,13 +1,8 @@ -error: expected identifier, found keyword `const` - --> $DIR/keyword-const-as-identifier.rs:4:9 +error: expected `{`, found `=` + --> $DIR/keyword-const-as-identifier.rs:2:15 | LL | let const = "foo"; - | ^^^^^ expected identifier, found keyword - | -help: escape `const` to use it as an identifier - | -LL | let r#const = "foo"; - | ++ + | ^ expected `{` error: aborting due to 1 previous error From 2d862accf619a9e4f1737ed215f2667bbfdeb409 Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Mon, 23 Sep 2024 16:24:33 +0300 Subject: [PATCH 2/2] Move eating `const` back into `parse_const_block` --- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- compiler/rustc_parse/src/parser/mod.rs | 3 ++- compiler/rustc_parse/src/parser/pat.rs | 8 +++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 02985b2def6a1..4961a93623e84 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1495,8 +1495,8 @@ impl<'a> Parser<'a> { err }, ) - } else if this.eat_keyword(exp!(Const)) { - this.parse_const_block(lo.to(this.prev_token.span), false) + } else if this.check_keyword(exp!(Const)) { + this.parse_const_block(lo.to(this.token.span), false) } else if this.may_recover() && this.is_do_catch_block() { this.recover_do_catch() } else if this.is_try_block() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 526fab0705a96..b2e902513672d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1281,8 +1281,9 @@ impl<'a> Parser<'a> { } } - /// Parses inline const expressions. The `const` keyword was already eaten. + /// Parses inline const expressions. fn parse_const_block(&mut self, span: Span, pat: bool) -> PResult<'a, P> { + self.expect_keyword(exp!(Const))?; let (attrs, blk) = self.parse_inner_attrs_and_block(None)?; let anon_const = AnonConst { id: DUMMY_NODE_ID, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e87de901ecbc3..2e56f30f4c22e 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -779,9 +779,9 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? } else if self.eat_keyword(exp!(Box)) { self.parse_pat_box()? - } else if self.eat_keyword(exp!(Const)) { + } else if self.check_keyword(exp!(Const)) { // Parse `const { pat }` - let const_expr = self.parse_const_block(lo.to(self.prev_token.span), true)?; + let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; if let Some(re) = self.parse_range_end() { self.parse_pat_range_begin_with(const_expr, re)? @@ -1268,9 +1268,7 @@ impl<'a> Parser<'a> { .then_some(self.prev_token.span); let bound = if self.check_inline_const(0) { - let _eaten = self.eat_keyword(exp!(Const)); - debug_assert!(_eaten); - self.parse_const_block(self.prev_token.span, true) + self.parse_const_block(self.token.span, true) } else if self.check_path() { let lo = self.token.span; let (qself, path) = if self.eat_lt() {