From 72d629caa50fa482dd4165cb43b9fb02ac24c8d8 Mon Sep 17 00:00:00 2001 From: James Miller Date: Tue, 23 Aug 2016 18:23:31 +1200 Subject: [PATCH] Improve error message when failing to parse a block We want to catch this error: ``` if (foo) bar; ``` as it's valid syntax in other languages, and say how to fix it. Unfortunately it didn't care if the suggestion made sense and just highlighted the unexpected token. Now it attempts to parse a statement, and if it succeeds, it shows the help message. Fixes #35907 --- src/libsyntax/parse/parser.rs | 27 ++++++++++++++++++--- src/test/compile-fail/missing-block-hint.rs | 20 +++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/missing-block-hint.rs diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 9443df6321bd..1646246069ea 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4087,9 +4087,30 @@ impl<'a> Parser<'a> { if !self.eat(&token::OpenDelim(token::Brace)) { let sp = self.span; let tok = self.this_token_to_string(); - return Err(self.span_fatal_help(sp, - &format!("expected `{{`, found `{}`", tok), - "place this code inside a block")); + let mut e = self.span_fatal(sp, &format!("expected `{{`, found `{}`", tok)); + + // Check to see if the user has written something like + // + // if (cond) + // bar; + // + // Which is valid in other languages, but not Rust. + match self.parse_stmt_without_recovery(false) { + Ok(Some(stmt)) => { + let mut stmt_span = stmt.span; + // expand the span to include the semicolon, if it exists + if self.eat(&token::Semi) { + stmt_span.hi = self.last_span.hi; + } + e.span_help(stmt_span, "try placing this code inside a block"); + } + Err(mut e) => { + self.recover_stmt_(SemiColonMode::Break); + e.cancel(); + } + _ => () + } + return Err(e); } self.parse_block_tail(lo, BlockCheckMode::Default) diff --git a/src/test/compile-fail/missing-block-hint.rs b/src/test/compile-fail/missing-block-hint.rs new file mode 100644 index 000000000000..1f29ff4e05c0 --- /dev/null +++ b/src/test/compile-fail/missing-block-hint.rs @@ -0,0 +1,20 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + { + if (foo) => {} //~ ERROR expected `{`, found `=>` + } + { + if (foo) + bar; //~ ERROR expected `{`, found `bar` + //^ HELP try placing this code inside a block + } +}