mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-26 00:34:06 +00:00
Account for missing keyword in fn/struct definition
This commit is contained in:
parent
1737d69c3b
commit
547873aa54
@ -6236,6 +6236,57 @@ impl<'a> Parser<'a> {
|
||||
return Ok(Some(macro_def));
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
|
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
|
||||
|
Loading…
Reference in New Issue
Block a user