Account for missing keyword in fn/struct definition
This commit is contained in:
@@ -6236,7 +6236,58 @@ impl<'a> Parser<'a> {
|
|||||||
return Ok(Some(macro_def));
|
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.
|
/// Parse a foreign item.
|
||||||
|
|||||||
15
src/test/ui/suggestions/pub-ident-fn.rs
Normal file
15
src/test/ui/suggestions/pub-ident-fn.rs
Normal file
@@ -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);
|
||||||
|
}
|
||||||
13
src/test/ui/suggestions/pub-ident-fn.stderr
Normal file
13
src/test/ui/suggestions/pub-ident-fn.stderr
Normal file
@@ -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
|
||||||
|
|
||||||
13
src/test/ui/suggestions/pub-ident-struct.rs
Normal file
13
src/test/ui/suggestions/pub-ident-struct.rs
Normal file
@@ -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() {}
|
||||||
13
src/test/ui/suggestions/pub-ident-struct.stderr
Normal file
13
src/test/ui/suggestions/pub-ident-struct.stderr
Normal file
@@ -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
|
||||||
|
|
||||||
Reference in New Issue
Block a user