diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 589b3e30fcfb..3056d1c545cc 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1789,6 +1789,35 @@ impl<'a> Parser<'a> { self.look_ahead(offset + 1, |t| t == &token::Colon) } + /// Skip unexpected attributes and doc comments in this position and emit an appropriate error. + fn eat_incorrect_doc_comment(&mut self, applied_to: &str) { + if let token::DocComment(_) = self.token { + let mut err = self.diagnostic().struct_span_err( + self.span, + &format!("documentation comments cannot be applied to {}", applied_to), + ); + err.span_label(self.span, "doc comments are not allowed here"); + err.emit(); + self.bump(); + } else if self.token == token::Pound && self.look_ahead(1, |t| { + *t == token::OpenDelim(token::Bracket) + }) { + let lo = self.span; + // Skip every token until next possible arg. + while self.token != token::CloseDelim(token::Bracket) { + self.bump(); + } + let sp = lo.to(self.span); + self.bump(); + let mut err = self.diagnostic().struct_span_err( + sp, + &format!("attributes cannot be applied to {}", applied_to), + ); + err.span_label(sp, "attributes are not allowed here"); + err.emit(); + } + } + /// This version of parse arg doesn't necessarily require /// identifier names. fn parse_arg_general(&mut self, require_name: bool) -> PResult<'a, Arg> { @@ -1797,7 +1826,11 @@ impl<'a> Parser<'a> { let (pat, ty) = if require_name || self.is_named_argument() { debug!("parse_arg_general parse_pat (require_name:{})", require_name); - let pat = self.parse_pat()?; + self.eat_incorrect_doc_comment("method arguments"); + let pat = self.parse_pat().map_err(|mut err| { + err.span_label(self.span, "expected argument name"); + err + })?; if let Err(mut err) = self.expect(&token::Colon) { // If we find a pattern followed by an identifier, it could be an (incorrect) @@ -1819,10 +1852,12 @@ impl<'a> Parser<'a> { return Err(err); } + self.eat_incorrect_doc_comment("a method argument's type"); (pat, self.parse_ty()?) } else { debug!("parse_arg_general ident_to_pat"); let parser_snapshot_before_ty = self.clone(); + self.eat_incorrect_doc_comment("a method argument's type"); let mut ty = self.parse_ty(); if ty.is_ok() && self.token == token::Colon { // This wasn't actually a type, but a pattern looking like a type, diff --git a/src/test/ui/parser/fn-arg-doc-comment.rs b/src/test/ui/parser/fn-arg-doc-comment.rs new file mode 100644 index 000000000000..22af94b62845 --- /dev/null +++ b/src/test/ui/parser/fn-arg-doc-comment.rs @@ -0,0 +1,37 @@ +pub fn f( + /// Comment + //~^ ERROR documentation comments cannot be applied to method arguments + //~| NOTE doc comments are not allowed here + id: u8, + /// Other + //~^ ERROR documentation comments cannot be applied to method arguments + //~| NOTE doc comments are not allowed here + a: u8, +) {} + +fn foo(#[allow(dead_code)] id: i32) {} +//~^ ERROR attributes cannot be applied to method arguments +//~| NOTE attributes are not allowed here + +fn bar(id: #[allow(dead_code)] i32) {} +//~^ ERROR attributes cannot be applied to a method argument's type +//~| NOTE attributes are not allowed here + +fn main() { + // verify that the parser recovered and properly typechecked the args + f("", ""); + //~^ ERROR mismatched types + //~| NOTE expected u8, found reference + //~| NOTE expected + //~| ERROR mismatched types + //~| NOTE expected u8, found reference + //~| NOTE expected + foo(""); + //~^ ERROR mismatched types + //~| NOTE expected i32, found reference + //~| NOTE expected + bar(""); + //~^ ERROR mismatched types + //~| NOTE expected i32, found reference + //~| NOTE expected +} diff --git a/src/test/ui/parser/fn-arg-doc-comment.stderr b/src/test/ui/parser/fn-arg-doc-comment.stderr new file mode 100644 index 000000000000..73a24eebb3f1 --- /dev/null +++ b/src/test/ui/parser/fn-arg-doc-comment.stderr @@ -0,0 +1,63 @@ +error: documentation comments cannot be applied to method arguments + --> $DIR/fn-arg-doc-comment.rs:2:5 + | +LL | /// Comment + | ^^^^^^^^^^^ doc comments are not allowed here + +error: documentation comments cannot be applied to method arguments + --> $DIR/fn-arg-doc-comment.rs:6:5 + | +LL | /// Other + | ^^^^^^^^^ doc comments are not allowed here + +error: attributes cannot be applied to method arguments + --> $DIR/fn-arg-doc-comment.rs:12:8 + | +LL | fn foo(#[allow(dead_code)] id: i32) {} + | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here + +error: attributes cannot be applied to a method argument's type + --> $DIR/fn-arg-doc-comment.rs:16:12 + | +LL | fn bar(id: #[allow(dead_code)] i32) {} + | ^^^^^^^^^^^^^^^^^^^ attributes are not allowed here + +error[E0308]: mismatched types + --> $DIR/fn-arg-doc-comment.rs:22:7 + | +LL | f("", ""); + | ^^ expected u8, found reference + | + = note: expected type `u8` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/fn-arg-doc-comment.rs:22:11 + | +LL | f("", ""); + | ^^ expected u8, found reference + | + = note: expected type `u8` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/fn-arg-doc-comment.rs:29:9 + | +LL | foo(""); + | ^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error[E0308]: mismatched types + --> $DIR/fn-arg-doc-comment.rs:33:9 + | +LL | bar(""); + | ^^ expected i32, found reference + | + = note: expected type `i32` + found type `&'static str` + +error: aborting due to 8 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/parser/issue-33413.stderr b/src/test/ui/parser/issue-33413.stderr index 189ace74b9c6..4cdd14a3e27e 100644 --- a/src/test/ui/parser/issue-33413.stderr +++ b/src/test/ui/parser/issue-33413.stderr @@ -2,7 +2,10 @@ error: expected pattern, found `*` --> $DIR/issue-33413.rs:14:10 | LL | fn f(*, a: u8) -> u8 {} //~ ERROR expected pattern, found `*` - | ^ expected pattern + | ^ + | | + | expected pattern + | expected argument name error: aborting due to previous error diff --git a/src/test/ui/parser/lifetime-in-pattern.stderr b/src/test/ui/parser/lifetime-in-pattern.stderr index 86cc3c5b0cbe..83ca1b0ba266 100644 --- a/src/test/ui/parser/lifetime-in-pattern.stderr +++ b/src/test/ui/parser/lifetime-in-pattern.stderr @@ -2,7 +2,10 @@ error: unexpected lifetime `'a` in pattern --> $DIR/lifetime-in-pattern.rs:13:10 | LL | fn test(&'a str) { - | ^^ unexpected lifetime + | ^^ + | | + | unexpected lifetime + | expected argument name error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-mode.stderr b/src/test/ui/parser/removed-syntax-mode.stderr index 7a274553d576..c5bc92e37b51 100644 --- a/src/test/ui/parser/removed-syntax-mode.stderr +++ b/src/test/ui/parser/removed-syntax-mode.stderr @@ -2,7 +2,10 @@ error: expected pattern, found `+` --> $DIR/removed-syntax-mode.rs:13:6 | LL | fn f(+x: isize) {} //~ ERROR expected pattern, found `+` - | ^ expected pattern + | ^ + | | + | expected pattern + | expected argument name error: aborting due to previous error diff --git a/src/test/ui/self/self-vs-path-ambiguity.stderr b/src/test/ui/self/self-vs-path-ambiguity.stderr index 765174331706..4cad8401f239 100644 --- a/src/test/ui/self/self-vs-path-ambiguity.stderr +++ b/src/test/ui/self/self-vs-path-ambiguity.stderr @@ -2,7 +2,10 @@ error: unexpected lifetime `'a` in pattern --> $DIR/self-vs-path-ambiguity.rs:19:11 | LL | fn i(&'a self::S: &S) {} //~ ERROR unexpected lifetime `'a` in pattern - | ^^ unexpected lifetime + | ^^ + | | + | unexpected lifetime + | expected argument name error: aborting due to previous error