diff options
| author | Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> | 2017-04-05 23:01:06 +0000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-04-05 23:01:06 +0000 |
| commit | cee05080219bde70125882ef32c0a882544b9f50 (patch) | |
| tree | f918f3255ceb45636d37a3d4ebb850773449aa78 /src/libsyntax/parse | |
| parent | a18202792ad4f64ba8762544899cac827ac1d5cd (diff) | |
| parent | 8f31e191c6caa1986276f2dda207135a255ee1f6 (diff) | |
| download | rust-cee05080219bde70125882ef32c0a882544b9f50.tar.gz rust-cee05080219bde70125882ef32c0a882544b9f50.zip | |
Rollup merge of #40815 - estebank:issue-40006, r=GuillaumeGomez
Identify missing item category in `impl`s
```rust
struct S;
impl S {
pub hello_method(&self) {
println!("Hello");
}
}
fn main() { S.hello_method(); }
```
```rust
error: missing `fn` for method declaration
--> file.rs:3:4
|
3 | pub hello_method(&self) {
| ^ missing `fn`
```
Fix #40006. r? @pnkfelix CC @jonathandturner @GuillaumeGomez
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 57 |
1 files changed, 42 insertions, 15 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a27fc070ebe..8595bfc9f79 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4657,25 +4657,30 @@ impl<'a> Parser<'a> { }) } - fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) { - match *visa { - Visibility::Inherited => (), + fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) { + if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) { + err.emit(); + } + } + + fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> { + match *vis { + Visibility::Inherited => Ok(()), _ => { let is_macro_rules: bool = match self.token { token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), _ => false, }; if is_macro_rules { - self.diagnostic().struct_span_err(span, "can't qualify macro_rules \ - invocation with `pub`") - .help("did you mean #[macro_export]?") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); + err.help("did you mean #[macro_export]?"); + Err(err) } else { - self.diagnostic().struct_span_err(span, "can't qualify macro \ - invocation with `pub`") - .help("try adjusting the macro to put `pub` \ - inside the invocation") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro invocation with `pub`"); + err.help("try adjusting the macro to put `pub` inside the invocation"); + Err(err) } } } @@ -4686,14 +4691,36 @@ impl<'a> Parser<'a> { -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { - // method macro. + // Method macro. let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis, prev_span); + // Before complaining about trying to set a macro as `pub`, + // check if `!` comes after the path. + let err = self.complain_if_pub_macro_diag(&vis, prev_span); let lo = self.span; let pth = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; + let bang_err = self.expect(&token::Not); + if let Err(mut err) = err { + if let Err(mut bang_err) = bang_err { + // Given this code `pub path(`, it seems like this is not setting the + // visibility of a macro invocation, but rather a mistyped method declaration. + // Create a diagnostic pointing out that `fn` is missing. + // + // x | pub path(&self) { + // | ^ missing `fn` for method declaration + + err.cancel(); + bang_err.cancel(); + // pub path( + // ^^ `sp` below will point to this + let sp = prev_span.between(self.prev_span); + err = self.diagnostic() + .struct_span_err(sp, "missing `fn` for method declaration"); + err.span_label(sp, &"missing `fn`"); + } + return Err(err); + } // eat a matched-delimiter token tree: let (delim, tts) = self.expect_delimited_token_tree()?; |
