Skip to content

Commit

Permalink
Rollup merge of rust-lang#59866 - estebank:recover-missing-semi, r=pe…
Browse files Browse the repository at this point in the history
…trochenkov

Recover from missing semicolon based on the found token

When encountering one of a few keywords when a semicolon was
expected, suggest the semicolon and recover:

```
error: expected one of `.`, `;`, `?`, or an operator, found `let`
  --> $DIR/recover-missing-semi.rs:4:5
   |
LL |     let _: usize = ()
   |                      - help: missing semicolon here
LL |
LL |     let _ = 3;
   |     ^^^

error[E0308]: mismatched types
  --> $DIR/recover-missing-semi.rs:2:20
   |
LL |     let _: usize = ()
   |                    ^^ expected usize, found ()
   |
   = note: expected type `usize`
              found type `()`
```
  • Loading branch information
Centril authored Apr 12, 2019
2 parents ca9f04e + 9b6b3d6 commit af4acd0
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
26 changes: 26 additions & 0 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,34 @@ impl<'a> Parser<'a> {
}
}

let is_semi_suggestable = expected.iter().any(|t| match t {
TokenType::Token(token::Semi) => true, // we expect a `;` here
_ => false,
}) && ( // a `;` would be expected before the current keyword
self.token.is_keyword(keywords::Break) ||
self.token.is_keyword(keywords::Continue) ||
self.token.is_keyword(keywords::For) ||
self.token.is_keyword(keywords::If) ||
self.token.is_keyword(keywords::Let) ||
self.token.is_keyword(keywords::Loop) ||
self.token.is_keyword(keywords::Match) ||
self.token.is_keyword(keywords::Return) ||
self.token.is_keyword(keywords::While)
);
let cm = self.sess.source_map();
match (cm.lookup_line(self.span.lo()), cm.lookup_line(sp.lo())) {
(Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => {
// The spans are in different lines, expected `;` and found `let` or `return`.
// High likelihood that it is only a missing `;`.
err.span_suggestion_short(
label_sp,
"a semicolon may be missing here",
";".to_string(),
Applicability::MaybeIncorrect,
);
err.emit();
return Ok(true);
}
(Ok(ref a), Ok(ref b)) if a.line == b.line => {
// When the spans are in the same line, it means that the only content between
// them is whitespace, point at the found token in that case:
Expand Down
13 changes: 13 additions & 0 deletions src/test/ui/parser/recover-missing-semi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fn main() {
let _: usize = ()
//~^ ERROR mismatched types
let _ = 3;
//~^ ERROR expected one of
}

fn foo() -> usize {
let _: usize = ()
//~^ ERROR mismatched types
return 3;
//~^ ERROR expected one of
}
39 changes: 39 additions & 0 deletions src/test/ui/parser/recover-missing-semi.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
error: expected one of `.`, `;`, `?`, or an operator, found `let`
--> $DIR/recover-missing-semi.rs:4:5
|
LL | let _: usize = ()
| - help: a semicolon may be missing here
LL |
LL | let _ = 3;
| ^^^

error: expected one of `.`, `;`, `?`, or an operator, found `return`
--> $DIR/recover-missing-semi.rs:11:5
|
LL | let _: usize = ()
| - help: a semicolon may be missing here
LL |
LL | return 3;
| ^^^^^^

error[E0308]: mismatched types
--> $DIR/recover-missing-semi.rs:2:20
|
LL | let _: usize = ()
| ^^ expected usize, found ()
|
= note: expected type `usize`
found type `()`

error[E0308]: mismatched types
--> $DIR/recover-missing-semi.rs:9:20
|
LL | let _: usize = ()
| ^^ expected usize, found ()
|
= note: expected type `usize`
found type `()`

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.

0 comments on commit af4acd0

Please sign in to comment.