From a49368f00b66409ae9fcf42d52e4f8246c73c266 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 10 Nov 2023 12:13:53 -0800 Subject: [PATCH] Correctly handle while-let-chains --- compiler/rustc_parse/src/lexer/tokentrees.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 2 +- tests/ui/parser/brace-in-let-chain.rs | 21 ++++++++++++++ tests/ui/parser/brace-in-let-chain.stderr | 30 ++++++++++++++++++-- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs index e7d2c678824..41f4d0055aa 100644 --- a/compiler/rustc_parse/src/lexer/tokentrees.rs +++ b/compiler/rustc_parse/src/lexer/tokentrees.rs @@ -129,7 +129,7 @@ fn parse_token_tree_open_delim( while parser.token != token::Eof { if let Err(diff_err) = parser.err_diff_marker() { diff_errs.push(diff_err); - } else if parser.token.is_keyword(kw::If) { + } else if parser.is_keyword_ahead(0, &[kw::If, kw::While]) { in_cond = true; } else if matches!( parser.token.kind, diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 1a7ae406911..6eab140117e 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1115,7 +1115,7 @@ pub fn look_ahead(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R } /// Returns whether any of the given keywords are `dist` tokens ahead of the current one. - fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { + pub fn is_keyword_ahead(&self, dist: usize, kws: &[Symbol]) -> bool { self.look_ahead(dist, |t| kws.iter().any(|&kw| t.is_keyword(kw))) } diff --git a/tests/ui/parser/brace-in-let-chain.rs b/tests/ui/parser/brace-in-let-chain.rs index 78060e238d4..1f34c73a2c3 100644 --- a/tests/ui/parser/brace-in-let-chain.rs +++ b/tests/ui/parser/brace-in-let-chain.rs @@ -9,6 +9,27 @@ fn main() { } } +fn quux() { + while let () = () + && let () = () { //~ERROR: found a `{` in the middle of a let-chain + && let () = () + { + } +} + +fn foobar() { + while false {} + { + && let () = () +} + +fn fubar() { + while false { + { + && let () = () + } +} + fn qux() { let foo = false; match foo { diff --git a/tests/ui/parser/brace-in-let-chain.stderr b/tests/ui/parser/brace-in-let-chain.stderr index 8e20cc43421..c43310f4736 100644 --- a/tests/ui/parser/brace-in-let-chain.stderr +++ b/tests/ui/parser/brace-in-let-chain.stderr @@ -1,9 +1,18 @@ error: this file contains an unclosed delimiter - --> $DIR/brace-in-let-chain.rs:37:54 + --> $DIR/brace-in-let-chain.rs:58:54 | LL | fn main() { | - unclosed delimiter ... +LL | fn quux() { + | - unclosed delimiter +... +LL | fn foobar() { + | - unclosed delimiter +... +LL | fn fubar() { + | - unclosed delimiter +... LL | fn qux() { | - unclosed delimiter ... @@ -24,6 +33,23 @@ LL | } LL | } | ^ +error: found a `{` in the middle of a let-chain + --> $DIR/brace-in-let-chain.rs:14:24 + | +LL | && let () = () { + | ^ + | +note: you might have meant to continue the let-chain here + --> $DIR/brace-in-let-chain.rs:15:9 + | +LL | && let () = () + | ^^^^^^ +help: consider removing this brace to parse the `let` as part of the same chain + | +LL - && let () = () { +LL + && let () = () + | + error: found a `{` in the middle of a let-chain --> $DIR/brace-in-let-chain.rs:6:24 | @@ -41,5 +67,5 @@ LL - && let () = () { LL + && let () = () | -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors