From 9596dc2a47861d73996a550cba7caf55b2737c17 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 01:47:15 +0100 Subject: [PATCH 01/19] parse_labeled_expr: simplify --- src/librustc_parse/parser/expr.rs | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 16ea2773b2009..e0e6fd5eed6b7 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1069,24 +1069,22 @@ impl<'a> Parser<'a> { fn parse_labeled_expr(&mut self, label: Label, attrs: AttrVec) -> PResult<'a, P> { let lo = label.ident.span; + let label = Some(label); self.expect(&token::Colon)?; if self.eat_keyword(kw::While) { - return self.parse_while_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::For) { - return self.parse_for_expr(Some(label), lo, attrs); - } - if self.eat_keyword(kw::Loop) { - return self.parse_loop_expr(Some(label), lo, attrs); - } - if self.token == token::OpenDelim(token::Brace) { - return self.parse_block_expr(Some(label), lo, BlockCheckMode::Default, attrs); + self.parse_while_expr(label, lo, attrs) + } else if self.eat_keyword(kw::For) { + self.parse_for_expr(label, lo, attrs) + } else if self.eat_keyword(kw::Loop) { + self.parse_loop_expr(label, lo, attrs) + } else if self.check(&token::OpenDelim(token::Brace)) { + self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) + } 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() } - - 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() } /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. From c303c4463cd3530c634dac8614feac7723ab0c58 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 02:46:13 +0100 Subject: [PATCH 02/19] use error_block_no_opening_brace more --- src/librustc_parse/parser/stmt.rs | 6 ++- src/test/ui/parser/block-no-opening-brace.rs | 30 +++++++++++ .../ui/parser/block-no-opening-brace.stderr | 53 +++++++++++++++++++ 3 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/parser/block-no-opening-brace.rs create mode 100644 src/test/ui/parser/block-no-opening-brace.stderr diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 3864ec3aaa163..511d4bfccd2cf 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -304,7 +304,11 @@ impl<'a> Parser<'a> { maybe_whole!(self, NtBlock, |x| (Vec::new(), x)); let lo = self.token.span; - self.expect(&token::OpenDelim(token::Brace))?; + + if !self.eat(&token::OpenDelim(token::Brace)) { + return self.error_block_no_opening_brace(); + } + Ok((self.parse_inner_attributes()?, self.parse_block_tail(lo, BlockCheckMode::Default)?)) } diff --git a/src/test/ui/parser/block-no-opening-brace.rs b/src/test/ui/parser/block-no-opening-brace.rs new file mode 100644 index 0000000000000..169625bf8973b --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.rs @@ -0,0 +1,30 @@ +// edition:2018 + +#![feature(try_blocks)] + +fn main() {} + +fn f1() { + loop + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f2() { + while true + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f3() { + for x in 0..1 + let x = 0; //~ ERROR expected `{`, found keyword `let` + } + +fn f4() { + try //~ ERROR expected expression, found reserved keyword `try` + let x = 0; + } + +fn f5() { + async //~ ERROR async closures are unstable + let x = 0; //~ ERROR expected one of `move`, `|`, or `||`, found keyword `let` + } diff --git a/src/test/ui/parser/block-no-opening-brace.stderr b/src/test/ui/parser/block-no-opening-brace.stderr new file mode 100644 index 0000000000000..56db1147360de --- /dev/null +++ b/src/test/ui/parser/block-no-opening-brace.stderr @@ -0,0 +1,53 @@ +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:9:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:14:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected `{`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:19:6 + | +LL | let x = 0; + | ^^^------- + | | + | expected `{` + | help: try placing this code inside a block: `{ let x = 0; }` + +error: expected expression, found reserved keyword `try` + --> $DIR/block-no-opening-brace.rs:23:4 + | +LL | try + | ^^^ expected expression + +error: expected one of `move`, `|`, or `||`, found keyword `let` + --> $DIR/block-no-opening-brace.rs:29:6 + | +LL | async + | - expected one of `move`, `|`, or `||` +LL | let x = 0; + | ^^^ unexpected token + +error[E0658]: async closures are unstable + --> $DIR/block-no-opening-brace.rs:28:4 + | +LL | async + | ^^^^^ + | + = note: see issue #62290 for more information + = help: add `#![feature(async_closure)]` to the crate attributes to enable + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0658`. From 883e90dd81b207cc5d9e85c02f628432b7f8d65d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 03:24:58 +0100 Subject: [PATCH 03/19] simplify parse_inner_attributes --- src/librustc_parse/parser/attr.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/librustc_parse/parser/attr.rs b/src/librustc_parse/parser/attr.rs index bdd78e671a8b3..1e7f5b662f3d2 100644 --- a/src/librustc_parse/parser/attr.rs +++ b/src/librustc_parse/parser/attr.rs @@ -201,12 +201,8 @@ impl<'a> Parser<'a> { let mut attrs: Vec = vec![]; loop { match self.token.kind { - token::Pound => { - // Don't even try to parse if it's not an inner attribute. - if !self.look_ahead(1, |t| t == &token::Not) { - break; - } - + // Only try to parse if it is an inner attribute (has `!`). + token::Pound if self.look_ahead(1, |t| t == &token::Not) => { let attr = self.parse_attribute(true)?; assert_eq!(attr.style, ast::AttrStyle::Inner); attrs.push(attr); From 8ee220c447911c519ebbd118e1415d961317b18d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Thu, 5 Mar 2020 05:49:30 +0100 Subject: [PATCH 04/19] more reuse in block parsing & improve diagnostics. --- src/librustc_ast/token.rs | 10 +++++ src/librustc_parse/parser/expr.rs | 16 ++++---- src/librustc_parse/parser/stmt.rs | 17 +++++--- .../label_break_value_illegal_uses.stderr | 5 ++- src/test/ui/parser/bad-interpolated-block.rs | 15 +++++++ .../ui/parser/bad-interpolated-block.stderr | 39 +++++++++++++++++++ src/test/ui/parser/closure-return-syntax.rs | 2 +- .../ui/parser/closure-return-syntax.stderr | 7 +++- .../unsafe/unsafe-block-without-braces.stderr | 7 ++-- 9 files changed, 98 insertions(+), 20 deletions(-) create mode 100644 src/test/ui/parser/bad-interpolated-block.rs create mode 100644 src/test/ui/parser/bad-interpolated-block.stderr diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs index b67b7d346f756..3fc6444168e24 100644 --- a/src/librustc_ast/token.rs +++ b/src/librustc_ast/token.rs @@ -535,6 +535,16 @@ impl Token { false } + // Is the token an interpolated block (`$b:block`)? + pub fn is_whole_block(&self) -> bool { + if let Interpolated(ref nt) = self.kind { + if let NtBlock(..) = **nt { + return true; + } + } + false + } + /// Returns `true` if the token is either the `mut` or `const` keyword. pub fn is_mutability(&self) -> bool { self.is_keyword(kw::Mut) || self.is_keyword(kw::Const) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index e0e6fd5eed6b7..b1c5eaf8973ab 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1077,7 +1077,7 @@ impl<'a> Parser<'a> { self.parse_for_expr(label, lo, attrs) } else if self.eat_keyword(kw::Loop) { self.parse_loop_expr(label, lo, attrs) - } else if self.check(&token::OpenDelim(token::Brace)) { + } else if self.check(&token::OpenDelim(token::Brace)) || self.token.is_whole_block() { self.parse_block_expr(label, lo, BlockCheckMode::Default, attrs) } else { let msg = "expected `while`, `for`, `loop` or `{` after a label"; @@ -1361,18 +1361,20 @@ impl<'a> Parser<'a> { opt_label: Option