diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 5571a18b596..1825ee6eab8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1777,7 +1777,26 @@ impl<'a> Parser<'a> { require_name); let pat = self.parse_pat()?; - self.expect(&token::Colon)?; + if let Err(mut err) = self.expect(&token::Colon) { + // If we find a pattern followed by an identifier, it could be an (incorrect) + // C-style parameter declaration. + if self.check_ident() && self.look_ahead(1, |t| { + *t == token::Comma || *t == token::CloseDelim(token::Paren) + }) { + let ident = self.parse_ident().unwrap(); + let span = pat.span.with_hi(ident.span.hi()); + + err.span_suggestion_with_applicability( + span, + "declare the type after the parameter binding", + String::from(": "), + Applicability::HasPlaceholders, + ); + } + + return Err(err); + } + (pat, self.parse_ty()?) } else { debug!("parse_arg_general ident_to_pat"); diff --git a/src/test/ui/parser/inverted-parameters.rs b/src/test/ui/parser/inverted-parameters.rs new file mode 100644 index 00000000000..a100debbf12 --- /dev/null +++ b/src/test/ui/parser/inverted-parameters.rs @@ -0,0 +1,39 @@ +// Copyright 2018 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct S; + +impl S { + fn foo(&self, &str bar) {} + //~^ ERROR expected one of `:` or `@` + //~| HELP declare the type after the parameter binding + //~| SUGGESTION : +} + +fn baz(S quux, xyzzy: i32) {} +//~^ ERROR expected one of `:` or `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn one(i32 a b) {} +//~^ ERROR expected one of `:` or `@` + +fn pattern((i32, i32) (a, b)) {} +//~^ ERROR expected `:` + +fn fizz(i32) {} +//~^ ERROR expected one of `:` or `@` + +fn missing_colon(quux S) {} +//~^ ERROR expected one of `:` or `@` +//~| HELP declare the type after the parameter binding +//~| SUGGESTION : + +fn main() {} diff --git a/src/test/ui/parser/inverted-parameters.stderr b/src/test/ui/parser/inverted-parameters.stderr new file mode 100644 index 00000000000..3f4f0615bc8 --- /dev/null +++ b/src/test/ui/parser/inverted-parameters.stderr @@ -0,0 +1,47 @@ +error: expected one of `:` or `@`, found `bar` + --> $DIR/inverted-parameters.rs:14:24 + | +LL | fn foo(&self, &str bar) {} + | -----^^^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:` or `@`, found `quux` + --> $DIR/inverted-parameters.rs:20:10 + | +LL | fn baz(S quux, xyzzy: i32) {} + | --^^^^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: expected one of `:` or `@`, found `a` + --> $DIR/inverted-parameters.rs:25:12 + | +LL | fn one(i32 a b) {} + | ^ expected one of `:` or `@` here + +error: expected `:`, found `(` + --> $DIR/inverted-parameters.rs:28:23 + | +LL | fn pattern((i32, i32) (a, b)) {} + | ^ expected `:` + +error: expected one of `:` or `@`, found `)` + --> $DIR/inverted-parameters.rs:31:12 + | +LL | fn fizz(i32) {} + | ^ expected one of `:` or `@` here + +error: expected one of `:` or `@`, found `S` + --> $DIR/inverted-parameters.rs:34:23 + | +LL | fn missing_colon(quux S) {} + | -----^ + | | | + | | expected one of `:` or `@` here + | help: declare the type after the parameter binding: `: ` + +error: aborting due to 6 previous errors +