about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-08-14 22:56:18 +0200
committerGitHub <noreply@github.com>2019-08-14 22:56:18 +0200
commit7178cf5f970a4f32afd260dda4f87223d8a9ba96 (patch)
tree1663a71b9c9cf82ff994b7ce35eaf1d52d170c27 /src/libsyntax/parse
parentc43d03a19f326f4a323569328cc501e86eb6d22e (diff)
parent76a134524295a04ed5f336265239ef5f39d089de (diff)
downloadrust-7178cf5f970a4f32afd260dda4f87223d8a9ba96.tar.gz
rust-7178cf5f970a4f32afd260dda4f87223d8a9ba96.zip
Rollup merge of #62984 - nathanwhit:extra_semi_lint, r=varkor
Add lint for excess trailing semicolons

Closes #60876.
A caveat (not necessarily a negative, but something to consider) with this implementation is that excess semicolons after return/continue/break now also cause an 'unreachable statement' warning.

For the following example:
```
fn main() {
    extra_semis();
}
fn extra_semis() -> i32 {
    let mut sum = 0;;;
    for i in 0..10 {
        if i == 5 {
            continue;;
        } else if i == 9 {
            break;;
        } else {
            sum += i;;
        }
    }
    return sum;;
}
```
The output is:
```
warning: unnecessary trailing semicolons
 --> src/main.rs:5:21
  |
5 |     let mut sum = 0;;;
  |                     ^^ help: remove these semicolons
  |
  = note: `#[warn(redundant_semicolon)]` on by default

warning: unnecessary trailing semicolon
 --> src/main.rs:8:22
  |
8 |             continue;;
  |                      ^ help: remove this semicolon

warning: unnecessary trailing semicolon
  --> src/main.rs:10:19
   |
10 |             break;;
   |                   ^ help: remove this semicolon

warning: unnecessary trailing semicolon
  --> src/main.rs:12:22
   |
12 |             sum += i;;
   |                      ^ help: remove this semicolon

warning: unnecessary trailing semicolon
  --> src/main.rs:15:16
   |
15 |     return sum;;
   |                ^ help: remove this semicolon

warning: unreachable statement
 --> src/main.rs:8:22
  |
8 |             continue;;
  |                      ^
  |
  = note: `#[warn(unreachable_code)]` on by default

warning: unreachable statement
  --> src/main.rs:10:19
   |
10 |             break;;
   |                   ^

warning: unreachable statement
  --> src/main.rs:15:16
   |
15 |     return sum;;
   |                ^

```
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/parser/stmt.rs17
1 files changed, 16 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser/stmt.rs b/src/libsyntax/parse/parser/stmt.rs
index f182edcbff4..750d8fbbddc 100644
--- a/src/libsyntax/parse/parser/stmt.rs
+++ b/src/libsyntax/parse/parser/stmt.rs
@@ -167,7 +167,22 @@ impl<'a> Parser<'a> {
                     if self.token == token::Semi {
                         unused_attrs(&attrs, self);
                         self.bump();
-                        return Ok(None);
+                        let mut last_semi = lo;
+                        while self.token == token::Semi {
+                            last_semi = self.token.span;
+                            self.bump();
+                        }
+                        // We are encoding a string of semicolons as an
+                        // an empty tuple that spans the excess semicolons
+                        // to preserve this info until the lint stage
+                        return Ok(Some(Stmt {
+                            id: ast::DUMMY_NODE_ID,
+                            span: lo.to(last_semi),
+                            node: StmtKind::Semi(self.mk_expr(lo.to(last_semi),
+                                ExprKind::Tup(Vec::new()),
+                                ThinVec::new()
+                            )),
+                        }));
                     }
 
                     if self.token == token::CloseDelim(token::Brace) {