diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2017-11-14 17:49:29 -0800 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2017-11-24 07:34:31 -0800 |
| commit | 547873aa54e787cbb7c266fb6e7337ea4e8a9331 (patch) | |
| tree | 5bcfc4954c7f0a54618959af49ff39ddd516c754 /src | |
| parent | 1737d69c3b6632d56cd66144c9316ad643fb7507 (diff) | |
| download | rust-547873aa54e787cbb7c266fb6e7337ea4e8a9331.tar.gz rust-547873aa54e787cbb7c266fb6e7337ea4e8a9331.zip | |
Account for missing keyword in fn/struct definition
Diffstat (limited to 'src')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 53 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pub-ident-fn.rs | 15 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pub-ident-fn.stderr | 13 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pub-ident-struct.rs | 13 | ||||
| -rw-r--r-- | src/test/ui/suggestions/pub-ident-struct.stderr | 13 |
5 files changed, 106 insertions, 1 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 0b03429ea2e..fbc12872501 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -6236,7 +6236,58 @@ impl<'a> Parser<'a> { return Ok(Some(macro_def)); } - self.parse_macro_use_or_failure(attrs,macros_allowed,attributes_allowed,lo,visibility) + // Verify wether we have encountered a struct or method definition where the user forgot to + // add the `struct` or `fn` keyword after writing `pub`: `pub S {}` + if visibility == Visibility::Public && self.check_ident() { + // Keep the current state of the parser to rollback after an unsuccessful attempt to + // parse an entire method or struct body. + let parser_snapshot = self.clone(); + + // Space between `pub` keyword and the identifier + // + // pub S {} + // ^^^ `sp` points here + let sp = self.prev_span.between(self.span); + if self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace)) { + // possible public struct definition where `struct` was forgotten + let ident = self.parse_ident().unwrap(); + match self.parse_record_struct_body() { + Err(mut err) => { + // couldn't parse a struct body, continue parsing as if it were a macro + err.cancel(); + mem::replace(self, parser_snapshot); + } + Ok(_) => { + let msg = format!("add `struct` here to parse `{}` as a public struct", + ident); + let mut err = self.diagnostic() + .struct_span_err(sp, "missing `struct` for struct definition"); + err.span_suggestion_short(sp, &msg, " struct ".into()); + return Err(err); + } + } + } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) { + // possible public method definition where `fn` was forgotten + let ident = self.parse_ident().unwrap(); + match self.parse_fn_decl(false) + .and_then(|_| self.parse_where_clause()) + .and_then(|_| self.parse_inner_attrs_and_block()) { + Err(mut err) => { + // couldn't parse method arguments or body, continue parsing + err.cancel(); + mem::replace(self, parser_snapshot); + } + Ok(_) => { + let msg = format!("add `fn` here to parse `{}` as a public method", ident); + let mut err = self.diagnostic() + .struct_span_err(sp, "missing `fn` for method definition"); + err.span_suggestion_short(sp, &msg, " fn ".into()); + return Err(err); + } + } + } + } + self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) } /// Parse a foreign item. diff --git a/src/test/ui/suggestions/pub-ident-fn.rs b/src/test/ui/suggestions/pub-ident-fn.rs new file mode 100644 index 00000000000..043cf9328c9 --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn.rs @@ -0,0 +1,15 @@ +// 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. + +pub foo(s: usize) -> bool { true } + +fn main() { + foo(2); +} diff --git a/src/test/ui/suggestions/pub-ident-fn.stderr b/src/test/ui/suggestions/pub-ident-fn.stderr new file mode 100644 index 00000000000..19d3db157c2 --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-fn.stderr @@ -0,0 +1,13 @@ +error: missing `fn` for method definition + --> $DIR/pub-ident-fn.rs:11:4 + | +11 | pub foo(s: usize) -> bool { true } + | ^^^ + | +help: add `fn` here to parse `foo` as a public method + | +11 | pub fn foo(s: usize) -> bool { true } + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/suggestions/pub-ident-struct.rs b/src/test/ui/suggestions/pub-ident-struct.rs new file mode 100644 index 00000000000..3e14a36dbab --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-struct.rs @@ -0,0 +1,13 @@ +// 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. + +pub S { +} +fn main() {} diff --git a/src/test/ui/suggestions/pub-ident-struct.stderr b/src/test/ui/suggestions/pub-ident-struct.stderr new file mode 100644 index 00000000000..bae2f6a4f80 --- /dev/null +++ b/src/test/ui/suggestions/pub-ident-struct.stderr @@ -0,0 +1,13 @@ +error: missing `struct` for struct definition + --> $DIR/pub-ident-struct.rs:11:4 + | +11 | pub S { + | ^ + | +help: add `struct` here to parse `S` as a public struct + | +11 | pub struct S { + | ^^^^^^ + +error: aborting due to previous error + |
