about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2017-07-02 01:37:47 +0200
committerGuillaume Gomez <guillaume1.gomez@gmail.com>2017-07-27 20:38:32 +0200
commit7e70a63e615d399072c8b8c2054d8d61844240d6 (patch)
tree76a4b583f95a93d982f11f668e08b8cccf837fd4
parent0565653eecd7d667dbb28bb5d3008e783950892a (diff)
downloadrust-7e70a63e615d399072c8b8c2054d8d61844240d6.tar.gz
rust-7e70a63e615d399072c8b8c2054d8d61844240d6.zip
Throw errors when doc comments are added where they're unused
-rw-r--r--src/librustc/hir/mod.rs2
-rw-r--r--src/libsyntax/parse/parser.rs41
-rw-r--r--src/test/compile-fail/issue-34222.rs2
-rw-r--r--src/test/compile-fail/useless_comment.rs26
-rw-r--r--src/test/compile-fail/useless_comment2.rs25
-rw-r--r--src/test/compile-fail/useless_comment3.rs22
6 files changed, 111 insertions, 7 deletions
diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs
index fd79ec3b6b9..1b14caad3c8 100644
--- a/src/librustc/hir/mod.rs
+++ b/src/librustc/hir/mod.rs
@@ -1679,7 +1679,7 @@ pub struct Item {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Item_ {
-    /// An`extern crate` item, with optional original crate name,
+    /// An `extern crate` item, with optional original crate name,
     ///
     /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
     ItemExternCrate(Option<Name>),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index af9a198b983..047f4b979d9 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2131,14 +2131,14 @@ impl<'a> Parser<'a> {
                 } else {
                     Ok(self.mk_expr(span, ExprKind::Tup(es), attrs))
                 }
-            },
+            }
             token::OpenDelim(token::Brace) => {
                 return self.parse_block_expr(lo, BlockCheckMode::Default, attrs);
-            },
-            token::BinOp(token::Or) |  token::OrOr => {
+            }
+            token::BinOp(token::Or) | token::OrOr => {
                 let lo = self.span;
                 return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs);
-            },
+            }
             token::OpenDelim(token::Bracket) => {
                 self.bump();
 
@@ -2387,7 +2387,6 @@ impl<'a> Parser<'a> {
     pub fn parse_block_expr(&mut self, lo: Span, blk_mode: BlockCheckMode,
                             outer_attrs: ThinVec<Attribute>)
                             -> PResult<'a, P<Expr>> {
-
         self.expect(&token::OpenDelim(token::Brace))?;
 
         let mut attrs = outer_attrs;
@@ -2421,6 +2420,12 @@ impl<'a> Parser<'a> {
             expr.map(|mut expr| {
                 attrs.extend::<Vec<_>>(expr.attrs.into());
                 expr.attrs = attrs;
+                if if let Some(ref doc) = expr.attrs.iter().find(|x| x.is_sugared_doc) {
+                    self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+                    true
+                } else { false } {
+                    return expr;
+                }
                 match expr.node {
                     ExprKind::If(..) | ExprKind::IfLet(..) => {
                         if !expr.attrs.is_empty() {
@@ -3105,6 +3110,9 @@ impl<'a> Parser<'a> {
 
     // `else` token already eaten
     pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
+        if self.prev_token_kind == PrevTokenKind::DocComment {
+            return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
+        }
         if self.eat_keyword(keywords::If) {
             return self.parse_if_expr(ThinVec::new());
         } else {
@@ -3118,6 +3126,9 @@ impl<'a> Parser<'a> {
                           span_lo: Span,
                           mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
         // Parse: `for <src_pat> in <src_expr> <src_loop_block>`
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
 
         let pat = self.parse_pat()?;
         self.expect_keyword(keywords::In)?;
@@ -3133,6 +3144,9 @@ impl<'a> Parser<'a> {
     pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                             span_lo: Span,
                             mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         if self.token.is_keyword(keywords::Let) {
             return self.parse_while_let_expr(opt_ident, span_lo, attrs);
         }
@@ -3161,6 +3175,9 @@ impl<'a> Parser<'a> {
     pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
                            span_lo: Span,
                            mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         let span = span_lo.to(body.span);
@@ -3171,6 +3188,9 @@ impl<'a> Parser<'a> {
     pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
         -> PResult<'a, P<Expr>>
     {
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         let (iattrs, body) = self.parse_inner_attrs_and_block()?;
         attrs.extend(iattrs);
         Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
@@ -3178,6 +3198,9 @@ impl<'a> Parser<'a> {
 
     // `match` token already eaten
     fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         let match_span = self.prev_span;
         let lo = self.prev_span;
         let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL,
@@ -3215,6 +3238,9 @@ impl<'a> Parser<'a> {
         maybe_whole!(self, NtArm, |x| x);
 
         let attrs = self.parse_outer_attributes()?;
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         let pats = self.parse_pats()?;
         let guard = if self.eat_keyword(keywords::If) {
             Some(self.parse_expr()?)
@@ -3669,6 +3695,9 @@ impl<'a> Parser<'a> {
 
     /// Parse a local variable declaration
     fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
+        if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
+            self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
+        }
         let lo = self.span;
         let pat = self.parse_pat()?;
 
@@ -4158,6 +4187,8 @@ impl<'a> Parser<'a> {
                 stmts.push(stmt);
             } else if self.token == token::Eof {
                 break;
+            } else if let token::DocComment(_) = self.token {
+                return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
             } else {
                 // Found only `;` or `}`.
                 continue;
diff --git a/src/test/compile-fail/issue-34222.rs b/src/test/compile-fail/issue-34222.rs
index 4609c0ccb1c..d406f59d0a2 100644
--- a/src/test/compile-fail/issue-34222.rs
+++ b/src/test/compile-fail/issue-34222.rs
@@ -13,6 +13,6 @@
 
 #[rustc_error]
 fn main() { //~ ERROR compilation successful
-    /// crash
+    // crash
     let x = 0;
 }
diff --git a/src/test/compile-fail/useless_comment.rs b/src/test/compile-fail/useless_comment.rs
new file mode 100644
index 00000000000..a32988aff12
--- /dev/null
+++ b/src/test/compile-fail/useless_comment.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo3() -> i32 {
+    let mut x = 12;
+    /// z //~ ERROR E0585
+    while x < 1 {
+        /// x //~ ERROR E0585
+        //~^ ERROR attributes on non-item statements and expressions are experimental
+        x += 1;
+    }
+    /// d //~ ERROR E0585
+    return x;
+}
+
+fn main() {
+    /// e //~ ERROR E0585
+    foo3();
+}
diff --git a/src/test/compile-fail/useless_comment2.rs b/src/test/compile-fail/useless_comment2.rs
new file mode 100644
index 00000000000..52ac7b6a769
--- /dev/null
+++ b/src/test/compile-fail/useless_comment2.rs
@@ -0,0 +1,25 @@
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() {
+    /// a //~ ERROR E0585
+    let x = 12;
+
+    /// b //~ ERROR E0585
+    match x {
+        /// c //~ ERROR E0585
+        1 => {},
+        _ => {}
+    }
+}
+
+fn main() {
+    foo();
+}
\ No newline at end of file
diff --git a/src/test/compile-fail/useless_comment3.rs b/src/test/compile-fail/useless_comment3.rs
new file mode 100644
index 00000000000..c26031b5eb6
--- /dev/null
+++ b/src/test/compile-fail/useless_comment3.rs
@@ -0,0 +1,22 @@
+// Copyright 2017 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() {
+    let x = 13;
+    /// x //~ ERROR E0585
+    if x == 12 {
+        /// y
+        println!("hello");
+    }
+}
+
+fn main() {
+    foo();
+}