From 327641e35c10624e7c728fce269885c6e4f6a602 Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Tue, 3 Dec 2019 13:35:05 +0100 Subject: [PATCH] recover on 'do catch { .. }' --- src/librustc_parse/parser/expr.rs | 44 ++++++++++++------- src/test/ui/parser/do-catch-suggests-try.rs | 7 ++- .../ui/parser/do-catch-suggests-try.stderr | 17 +++++-- 3 files changed, 47 insertions(+), 21 deletions(-) diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index b4d828ff849..292d277a678 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -876,14 +876,11 @@ macro_rules! parse_lit { return self.parse_labeled_expr(label, attrs); } if self.eat_keyword(kw::Loop) { - let lo = self.prev_span; - return self.parse_loop_expr(None, lo, attrs); + return self.parse_loop_expr(None, self.prev_span, attrs); } if self.eat_keyword(kw::Continue) { - let label = self.eat_label(); - let ex = ExprKind::Continue(label); - let hi = self.prev_span; - return Ok(self.mk_expr(lo.to(hi), ex, attrs)); + let kind = ExprKind::Continue(self.eat_label()); + return Ok(self.mk_expr(lo.to(self.prev_span), kind, attrs)); } if self.eat_keyword(kw::Match) { let match_sp = self.prev_span; @@ -893,20 +890,14 @@ macro_rules! parse_lit { }); } if self.eat_keyword(kw::Unsafe) { - return self.parse_block_expr( - None, - lo, - BlockCheckMode::Unsafe(ast::UserProvided), - attrs); + let mode = BlockCheckMode::Unsafe(ast::UserProvided); + return self.parse_block_expr(None, lo, mode, attrs); } if self.is_do_catch_block() { - let mut db = self.fatal("found removed `do catch` syntax"); - db.help("following RFC #2388, the new non-placeholder syntax is `try`"); - return Err(db); + return self.recover_do_catch(attrs); } if self.is_try_block() { - let lo = self.token.span; - assert!(self.eat_keyword(kw::Try)); + self.expect_keyword(kw::Try)?; return self.parse_try_block(lo, attrs); } @@ -1104,6 +1095,27 @@ fn parse_labeled_expr( self.parse_expr() } + /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead. + fn recover_do_catch(&mut self, attrs: ThinVec) -> PResult<'a, P> { + let lo = self.token.span; + + self.bump(); // `do` + self.bump(); // `catch` + + let span_dc = lo.to(self.prev_span); + self.struct_span_err(span_dc, "found removed `do catch` syntax") + .span_suggestion( + span_dc, + "replace with the new syntax", + "try".to_string(), + Applicability::MachineApplicable, + ) + .note("following RFC #2388, the new non-placeholder syntax is `try`") + .emit(); + + self.parse_try_block(lo, attrs) + } + /// Returns a string literal if the next token is a string literal. /// In case of error returns `Some(lit)` if the next token is a literal with a wrong kind, /// and returns `None` if the next token is not literal at all. diff --git a/src/test/ui/parser/do-catch-suggests-try.rs b/src/test/ui/parser/do-catch-suggests-try.rs index d805ab75882..f64568d06e9 100644 --- a/src/test/ui/parser/do-catch-suggests-try.rs +++ b/src/test/ui/parser/do-catch-suggests-try.rs @@ -1,5 +1,10 @@ +#![feature(try_blocks)] + fn main() { let _: Option<()> = do catch {}; //~^ ERROR found removed `do catch` syntax - //~^^ HELP following RFC #2388, the new non-placeholder syntax is `try` + //~| replace with the new syntax + //~| following RFC #2388, the new non-placeholder syntax is `try` + + let _recovery_witness: () = 1; //~ ERROR mismatched types } diff --git a/src/test/ui/parser/do-catch-suggests-try.stderr b/src/test/ui/parser/do-catch-suggests-try.stderr index e151d4cf8a6..cd8907b7eac 100644 --- a/src/test/ui/parser/do-catch-suggests-try.stderr +++ b/src/test/ui/parser/do-catch-suggests-try.stderr @@ -1,10 +1,19 @@ error: found removed `do catch` syntax - --> $DIR/do-catch-suggests-try.rs:2:25 + --> $DIR/do-catch-suggests-try.rs:4:25 | LL | let _: Option<()> = do catch {}; - | ^^ + | ^^^^^^^^ help: replace with the new syntax: `try` | - = help: following RFC #2388, the new non-placeholder syntax is `try` + = note: following RFC #2388, the new non-placeholder syntax is `try` -error: aborting due to previous error +error[E0308]: mismatched types + --> $DIR/do-catch-suggests-try.rs:9:33 + | +LL | let _recovery_witness: () = 1; + | -- ^ expected `()`, found integer + | | + | expected due to this + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0308`. -- 2.44.0