diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8d16d44b0a26a..597f40d106926 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1473,8 +1473,8 @@ impl<'a> Parser<'a> { err }, ) - } else if this.check_inline_const(0) { - this.parse_const_block(lo, false) + } else if this.check_keyword(kw::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/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index e08b925f00893..735fa2eed6004 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -733,8 +733,8 @@ impl<'a> Parser<'a> { self.parse_pat_ident(BindingMode(ByRef::Yes(mutbl), Mutability::Not), syntax_loc)? } else if self.eat_keyword(kw::Box) { self.parse_pat_box()? - } else if self.check_inline_const(0) { - // Parse `const pat` + } else if self.check_keyword(kw::Const) { + // Parse `const { pat }` let const_expr = self.parse_const_block(lo.to(self.token.span), true)?; if let Some(re) = self.parse_range_end() { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5fa2e01fc863c..84b9d03f48d39 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -497,15 +497,21 @@ 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::OpenDelim(Delimiter::Brace))) - || do_not_suggest_help => {} + if do_not_suggest_help + || (self.token != token::FatArrow + && self.token != token::Eq + && self.look_ahead(1, |t| { + t == &token::OpenDelim(token::Delimiter::Brace) + })) => {} // 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 2fde37ce6acef..4880c3776e33f 100644 --- a/tests/ui/parser/block-no-opening-brace.rs +++ b/tests/ui/parser/block-no-opening-brace.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(try_blocks)] +#![feature(try_blocks, inline_const_pat)] fn main() {} @@ -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 b65de4eac3f80..75d40eec242b6 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/inline-const-pat-let.rs b/tests/ui/parser/inline-const-pat-let.rs new file mode 100644 index 0000000000000..a813f9646b5ef --- /dev/null +++ b/tests/ui/parser/inline-const-pat-let.rs @@ -0,0 +1,29 @@ +//@ run-pass + +#![feature(inline_const_pat)] + +fn if_let_1() -> i32 { + let x = 2; + const Y: i32 = 3; + + if let const { (Y + 1) / 2 } = x { + x + } else { + 0 + } +} + +fn if_let_2() -> i32 { + let x = 2; + + if let const { 1 + 2 } = x { + const { 1 + 2 } + } else { + 0 + } +} + +fn main() { + assert_eq!(if_let_1(), 2); + assert_eq!(if_let_2(), 0); +} diff --git a/tests/ui/parser/inline-const-without-block.fixed b/tests/ui/parser/inline-const-without-block.fixed new file mode 100644 index 0000000000000..537d1725c4098 --- /dev/null +++ b/tests/ui/parser/inline-const-without-block.fixed @@ -0,0 +1,58 @@ +//@ run-rustfix + +// See issue #78168. + +#![feature(inline_const_pat)] + +const fn one() -> i32 { + 1 +} + +fn foo() -> i32 { + let x = 2; + + match x { + const { 2 } => {} + //~^ ERROR expected `{`, found `2` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + match x { + const { 1 + 2 * 3 / 4 } => {} + //~^ ERROR expected `{`, found `1` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + match x { + const { one() } => {} + //~^ ERROR expected `{`, found `one` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + x +} + +fn bar() -> i32 { + let x = const { 2 }; + //~^ ERROR expected `{`, found `2` + //~| HELP you might have meant to write this as part of a block + + x +} + +fn baz() -> i32 { + let y = const { 1 + 2 * 3 / 4 }; + //~^ ERROR expected `{`, found `1` + //~| HELP you might have meant to write this as part of a block + + y +} + +fn main() { + foo(); + bar(); + baz(); +} diff --git a/tests/ui/parser/inline-const-without-block.rs b/tests/ui/parser/inline-const-without-block.rs new file mode 100644 index 0000000000000..40c74c9e0c1b1 --- /dev/null +++ b/tests/ui/parser/inline-const-without-block.rs @@ -0,0 +1,58 @@ +//@ run-rustfix + +// See issue #78168. + +#![feature(inline_const_pat)] + +const fn one() -> i32 { + 1 +} + +fn foo() -> i32 { + let x = 2; + + match x { + const 2 => {} + //~^ ERROR expected `{`, found `2` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + match x { + const 1 + 2 * 3 / 4 => {} + //~^ ERROR expected `{`, found `1` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + match x { + const one() => {} + //~^ ERROR expected `{`, found `one` + //~| HELP you might have meant to write this as part of a block + _ => {} + } + + x +} + +fn bar() -> i32 { + let x = const 2; + //~^ ERROR expected `{`, found `2` + //~| HELP you might have meant to write this as part of a block + + x +} + +fn baz() -> i32 { + let y = const 1 + 2 * 3 / 4; + //~^ ERROR expected `{`, found `1` + //~| HELP you might have meant to write this as part of a block + + y +} + +fn main() { + foo(); + bar(); + baz(); +} diff --git a/tests/ui/parser/inline-const-without-block.stderr b/tests/ui/parser/inline-const-without-block.stderr new file mode 100644 index 0000000000000..92d4a73f661ce --- /dev/null +++ b/tests/ui/parser/inline-const-without-block.stderr @@ -0,0 +1,57 @@ +error: expected `{`, found `2` + --> $DIR/inline-const-without-block.rs:15:15 + | +LL | const 2 => {} + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | const { 2 } => {} + | + + + +error: expected `{`, found `1` + --> $DIR/inline-const-without-block.rs:22:15 + | +LL | const 1 + 2 * 3 / 4 => {} + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | const { 1 + 2 * 3 / 4 } => {} + | + + + +error: expected `{`, found `one` + --> $DIR/inline-const-without-block.rs:29:15 + | +LL | const one() => {} + | ^^^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | const { one() } => {} + | + + + +error: expected `{`, found `2` + --> $DIR/inline-const-without-block.rs:39:19 + | +LL | let x = const 2; + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | let x = const { 2 }; + | + + + +error: expected `{`, found `1` + --> $DIR/inline-const-without-block.rs:47:19 + | +LL | let y = const 1 + 2 * 3 / 4; + | ^ expected `{` + | +help: you might have meant to write this as part of a block + | +LL | let y = const { 1 + 2 * 3 / 4 }; + | + + + +error: aborting due to 5 previous errors + diff --git a/tests/ui/parser/keyword-const-as-identifier.rs b/tests/ui/parser/keyword-const-as-identifier.rs index 6a2d926bf5796..52f878f36e465 100644 --- a/tests/ui/parser/keyword-const-as-identifier.rs +++ b/tests/ui/parser/keyword-const-as-identifier.rs @@ -1,5 +1,5 @@ -// 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 `=` + //~| ERROR inline-const in pattern position is experimental [E0658] } diff --git a/tests/ui/parser/keyword-const-as-identifier.stderr b/tests/ui/parser/keyword-const-as-identifier.stderr index 61e454174dd78..0d3661f8c7f83 100644 --- a/tests/ui/parser/keyword-const-as-identifier.stderr +++ b/tests/ui/parser/keyword-const-as-identifier.stderr @@ -1,13 +1,19 @@ -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 + | ^ expected `{` + +error[E0658]: inline-const in pattern position is experimental + --> $DIR/keyword-const-as-identifier.rs:2:9 | -help: escape `const` to use it as an identifier +LL | let const = "foo"; + | ^^^^^ | -LL | let r#const = "foo"; - | ++ + = note: see issue #76001 for more information + = help: add `#![feature(inline_const_pat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`.