1
Fork 0

Identify missing item category in impls

```rust
struct S;
impl S {
    pub hello_method(&self) {
        println!("Hello");
    }
}
fn main() { S.hello_method(); }
```

```rust
error: can't qualify macro invocation with `pub`
 --> file.rs:3:4
  |
3 |     pub hello_method(&self) {
  |     ^^^-            - expected `!` here for a macro invocation
  |        |
  |        did you mean to write `fn` here for a method declaration?
  |
  = help: try adjusting the macro to put `pub` inside the invocation
```
This commit is contained in:
Esteban Küber 2017-03-24 23:00:21 -07:00
parent c62e532f3d
commit 57009caabd
3 changed files with 80 additions and 15 deletions

View file

@ -4660,25 +4660,30 @@ impl<'a> Parser<'a> {
}) })
} }
fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) { fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) {
match *visa { if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) {
Visibility::Inherited => (), 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 { let is_macro_rules: bool = match self.token {
token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), token::Ident(sid) => sid.name == Symbol::intern("macro_rules"),
_ => false, _ => false,
}; };
if is_macro_rules { if is_macro_rules {
self.diagnostic().struct_span_err(span, "can't qualify macro_rules \ let mut err = self.diagnostic()
invocation with `pub`") .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`");
.help("did you mean #[macro_export]?") err.help("did you mean #[macro_export]?");
.emit(); Err(err)
} else { } else {
self.diagnostic().struct_span_err(span, "can't qualify macro \ let mut err = self.diagnostic()
invocation with `pub`") .struct_span_err(sp, "can't qualify macro invocation with `pub`");
.help("try adjusting the macro to put `pub` \ err.help("try adjusting the macro to put `pub` inside the invocation");
inside the invocation") Err(err)
.emit();
} }
} }
} }
@ -4689,14 +4694,41 @@ impl<'a> Parser<'a> {
-> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> { -> PResult<'a, (Ident, Vec<ast::Attribute>, ast::ImplItemKind)> {
// code copied from parse_macro_use_or_failure... abstraction! // code copied from parse_macro_use_or_failure... abstraction!
if self.token.is_path_start() { if self.token.is_path_start() {
// method macro. // Method macro.
let prev_span = self.prev_span; 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.lo; let lo = self.span.lo;
let pth = self.parse_path(PathStyle::Mod)?; 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.
// Keep the macro diagnostic, but also provide a hint that `fn` might be
// missing. Don't complain about the missing `!` as a separate diagnostic, add
// label in the appropriate place as part of one unified diagnostic.
//
// x | pub path(&self) {
// | ^^^- - expected `!` here for a macro invocation
// | |
// | did you mean to write `fn` here for a method declaration?
bang_err.cancel();
err.span_label(self.span, &"expected `!` here for a macro invocation");
// pub path(
// ^^ `sp` below will point to this
let sp = mk_sp(prev_span.hi, self.prev_span.lo);
err.span_label(sp,
&"did you mean to write `fn` here for a method declaration?");
}
return Err(err);
} else if let Err(bang_err) = bang_err {
return Err(bang_err);
}
// eat a matched-delimiter token tree: // eat a matched-delimiter token tree:
let (delim, tts) = self.expect_delimited_token_tree()?; let (delim, tts) = self.expect_delimited_token_tree()?;

View file

@ -0,0 +1,21 @@
// 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.
struct S;
impl S {
pub hello_method(&self) {
println!("Hello");
}
}
fn main() {
S.hello_method();
}

View file

@ -0,0 +1,12 @@
error: can't qualify macro invocation with `pub`
--> $DIR/issue-40006.rs:14:5
|
14 | pub hello_method(&self) {
| ^^^- - expected `!` here for a macro invocation
| |
| did you mean to write `fn` here for a method declaration?
|
= help: try adjusting the macro to put `pub` inside the invocation
error: aborting due to previous error