Skip to content

Commit 7e70a63

Browse files
Throw errors when doc comments are added where they're unused
1 parent 0565653 commit 7e70a63

File tree

6 files changed

+111
-7
lines changed

6 files changed

+111
-7
lines changed

src/librustc/hir/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1679,7 +1679,7 @@ pub struct Item {
16791679

16801680
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
16811681
pub enum Item_ {
1682-
/// An`extern crate` item, with optional original crate name,
1682+
/// An `extern crate` item, with optional original crate name,
16831683
///
16841684
/// e.g. `extern crate foo` or `extern crate foo_bar as foo`
16851685
ItemExternCrate(Option<Name>),

src/libsyntax/parse/parser.rs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,14 +2131,14 @@ impl<'a> Parser<'a> {
21312131
} else {
21322132
Ok(self.mk_expr(span, ExprKind::Tup(es), attrs))
21332133
}
2134-
},
2134+
}
21352135
token::OpenDelim(token::Brace) => {
21362136
return self.parse_block_expr(lo, BlockCheckMode::Default, attrs);
2137-
},
2138-
token::BinOp(token::Or) | token::OrOr => {
2137+
}
2138+
token::BinOp(token::Or) | token::OrOr => {
21392139
let lo = self.span;
21402140
return self.parse_lambda_expr(lo, CaptureBy::Ref, attrs);
2141-
},
2141+
}
21422142
token::OpenDelim(token::Bracket) => {
21432143
self.bump();
21442144

@@ -2387,7 +2387,6 @@ impl<'a> Parser<'a> {
23872387
pub fn parse_block_expr(&mut self, lo: Span, blk_mode: BlockCheckMode,
23882388
outer_attrs: ThinVec<Attribute>)
23892389
-> PResult<'a, P<Expr>> {
2390-
23912390
self.expect(&token::OpenDelim(token::Brace))?;
23922391

23932392
let mut attrs = outer_attrs;
@@ -2421,6 +2420,12 @@ impl<'a> Parser<'a> {
24212420
expr.map(|mut expr| {
24222421
attrs.extend::<Vec<_>>(expr.attrs.into());
24232422
expr.attrs = attrs;
2423+
if if let Some(ref doc) = expr.attrs.iter().find(|x| x.is_sugared_doc) {
2424+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
2425+
true
2426+
} else { false } {
2427+
return expr;
2428+
}
24242429
match expr.node {
24252430
ExprKind::If(..) | ExprKind::IfLet(..) => {
24262431
if !expr.attrs.is_empty() {
@@ -3105,6 +3110,9 @@ impl<'a> Parser<'a> {
31053110

31063111
// `else` token already eaten
31073112
pub fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
3113+
if self.prev_token_kind == PrevTokenKind::DocComment {
3114+
return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
3115+
}
31083116
if self.eat_keyword(keywords::If) {
31093117
return self.parse_if_expr(ThinVec::new());
31103118
} else {
@@ -3118,6 +3126,9 @@ impl<'a> Parser<'a> {
31183126
span_lo: Span,
31193127
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
31203128
// Parse: `for <src_pat> in <src_expr> <src_loop_block>`
3129+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3130+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3131+
}
31213132

31223133
let pat = self.parse_pat()?;
31233134
self.expect_keyword(keywords::In)?;
@@ -3133,6 +3144,9 @@ impl<'a> Parser<'a> {
31333144
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
31343145
span_lo: Span,
31353146
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3147+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3148+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3149+
}
31363150
if self.token.is_keyword(keywords::Let) {
31373151
return self.parse_while_let_expr(opt_ident, span_lo, attrs);
31383152
}
@@ -3161,6 +3175,9 @@ impl<'a> Parser<'a> {
31613175
pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::SpannedIdent>,
31623176
span_lo: Span,
31633177
mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3178+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3179+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3180+
}
31643181
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
31653182
attrs.extend(iattrs);
31663183
let span = span_lo.to(body.span);
@@ -3171,13 +3188,19 @@ impl<'a> Parser<'a> {
31713188
pub fn parse_catch_expr(&mut self, span_lo: Span, mut attrs: ThinVec<Attribute>)
31723189
-> PResult<'a, P<Expr>>
31733190
{
3191+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3192+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3193+
}
31743194
let (iattrs, body) = self.parse_inner_attrs_and_block()?;
31753195
attrs.extend(iattrs);
31763196
Ok(self.mk_expr(span_lo.to(body.span), ExprKind::Catch(body), attrs))
31773197
}
31783198

31793199
// `match` token already eaten
31803200
fn parse_match_expr(&mut self, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> {
3201+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3202+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3203+
}
31813204
let match_span = self.prev_span;
31823205
let lo = self.prev_span;
31833206
let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL,
@@ -3215,6 +3238,9 @@ impl<'a> Parser<'a> {
32153238
maybe_whole!(self, NtArm, |x| x);
32163239

32173240
let attrs = self.parse_outer_attributes()?;
3241+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3242+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3243+
}
32183244
let pats = self.parse_pats()?;
32193245
let guard = if self.eat_keyword(keywords::If) {
32203246
Some(self.parse_expr()?)
@@ -3669,6 +3695,9 @@ impl<'a> Parser<'a> {
36693695

36703696
/// Parse a local variable declaration
36713697
fn parse_local(&mut self, attrs: ThinVec<Attribute>) -> PResult<'a, P<Local>> {
3698+
if let Some(doc) = attrs.iter().find(|x| x.is_sugared_doc) {
3699+
self.span_fatal_err(doc.span, Error::UselessDocComment).emit();
3700+
}
36723701
let lo = self.span;
36733702
let pat = self.parse_pat()?;
36743703

@@ -4158,6 +4187,8 @@ impl<'a> Parser<'a> {
41584187
stmts.push(stmt);
41594188
} else if self.token == token::Eof {
41604189
break;
4190+
} else if let token::DocComment(_) = self.token {
4191+
return Err(self.span_fatal_err(self.span, Error::UselessDocComment));
41614192
} else {
41624193
// Found only `;` or `}`.
41634194
continue;

src/test/compile-fail/issue-34222.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,6 @@
1313

1414
#[rustc_error]
1515
fn main() { //~ ERROR compilation successful
16-
/// crash
16+
// crash
1717
let x = 0;
1818
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo3() -> i32 {
12+
let mut x = 12;
13+
/// z //~ ERROR E0585
14+
while x < 1 {
15+
/// x //~ ERROR E0585
16+
//~^ ERROR attributes on non-item statements and expressions are experimental
17+
x += 1;
18+
}
19+
/// d //~ ERROR E0585
20+
return x;
21+
}
22+
23+
fn main() {
24+
/// e //~ ERROR E0585
25+
foo3();
26+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo() {
12+
/// a //~ ERROR E0585
13+
let x = 12;
14+
15+
/// b //~ ERROR E0585
16+
match x {
17+
/// c //~ ERROR E0585
18+
1 => {},
19+
_ => {}
20+
}
21+
}
22+
23+
fn main() {
24+
foo();
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
fn foo() {
12+
let x = 13;
13+
/// x //~ ERROR E0585
14+
if x == 12 {
15+
/// y
16+
println!("hello");
17+
}
18+
}
19+
20+
fn main() {
21+
foo();
22+
}

0 commit comments

Comments
 (0)