diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index 8afc86c704d..fb85f54b136 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -259,16 +259,14 @@ impl<'a> Parser<'a> { // // which is valid in other languages, but not Rust. match self.parse_stmt_without_recovery() { - Ok(Some(stmt)) => { + // If the next token is an open brace (e.g., `if a b {`), the place- + // inside-a-block suggestion would be more likely wrong than right. + Ok(Some(_)) if self.look_ahead(1, |t| t == &token::OpenDelim(token::Brace)) - || do_not_suggest_help - { - // If the next token is an open brace (e.g., `if a b {`), the place- - // inside-a-block suggestion would be more likely wrong than right. - e.span_label(sp, "expected `{`"); - return Err(e); - } - let stmt_span = if self.eat(&token::Semi) { + || do_not_suggest_help => {} + Ok(Some(stmt)) => { + let stmt_own_line = self.sess.source_map().is_line_before_span_empty(sp); + let stmt_span = if stmt_own_line && self.eat(&token::Semi) { // Expand the span to include the semicolon. stmt.span.with_hi(self.prev_token.span.hi()) } else { diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index cd2d2c4c3d7..5170f69e059 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -517,6 +517,13 @@ impl SourceMap { Ok((lo, hi)) } + pub fn is_line_before_span_empty(&self, sp: Span) -> bool { + match self.span_to_prev_source(sp) { + Ok(s) => s.split('\n').last().map(|l| l.trim_start().is_empty()).unwrap_or(false), + Err(_) => false, + } + } + pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { debug!("span_to_lines(sp={:?})", sp); let (lo, hi) = self.is_valid_span(sp)?; diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr index 4dcba27cb68..af490150913 100644 --- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr +++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr @@ -140,7 +140,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:41:37 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; } - | -- ^ --- help: try placing this code inside a block: `{ {}; }` + | -- ^ -- help: try placing this code inside a block: `{ {} }` | | | | | expected `{` | this `if` expression has a condition, but no block @@ -163,7 +163,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:47:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] {}; } - | ^ --- help: try placing this code inside a block: `{ {}; }` + | ^ -- help: try placing this code inside a block: `{ {} }` | | | expected `{` @@ -179,7 +179,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:51:45 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else #[attr] if 0 {}; } - | ^ -------- help: try placing this code inside a block: `{ if 0 {}; }` + | ^ ------- help: try placing this code inside a block: `{ if 0 {} }` | | | expected `{` @@ -187,7 +187,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:53:50 | LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; } - | -- ^ --- help: try placing this code inside a block: `{ {}; }` + | -- ^ -- help: try placing this code inside a block: `{ {} }` | | | | | expected `{` | this `if` expression has a condition, but no block @@ -204,7 +204,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:57:45 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; } - | -- ^ --- help: try placing this code inside a block: `{ {}; }` + | -- ^ -- help: try placing this code inside a block: `{ {} }` | | | | | expected `{` | this `if` expression has a condition, but no block @@ -227,7 +227,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:63:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] {}; } - | ^ --- help: try placing this code inside a block: `{ {}; }` + | ^ -- help: try placing this code inside a block: `{ {} }` | | | expected `{` @@ -243,7 +243,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:67:53 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else #[attr] if let _ = 0 {}; } - | ^ ---------------- help: try placing this code inside a block: `{ if let _ = 0 {}; }` + | ^ --------------- help: try placing this code inside a block: `{ if let _ = 0 {} }` | | | expected `{` @@ -251,7 +251,7 @@ error: expected `{`, found `#` --> $DIR/attr-stmt-expr-attr-bad.rs:69:66 | LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}; } - | -- ^ --- help: try placing this code inside a block: `{ {}; }` + | -- ^ -- help: try placing this code inside a block: `{ {} }` | | | | | expected `{` | this `if` expression has a condition, but no block diff --git a/src/test/ui/parser/closure-return-syntax.stderr b/src/test/ui/parser/closure-return-syntax.stderr index 7bf6202a72a..1ccdd977305 100644 --- a/src/test/ui/parser/closure-return-syntax.stderr +++ b/src/test/ui/parser/closure-return-syntax.stderr @@ -2,10 +2,10 @@ error: expected `{`, found `22` --> $DIR/closure-return-syntax.rs:5:23 | LL | let x = || -> i32 22; - | ^^- + | ^^ | | | expected `{` - | help: try placing this code inside a block: `{ 22; }` + | help: try placing this code inside a block: `{ 22 }` error: aborting due to previous error