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: 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:
parent
c62e532f3d
commit
57009caabd
3 changed files with 80 additions and 15 deletions
|
@ -4660,25 +4660,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4689,14 +4694,41 @@ 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.lo;
|
||||
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:
|
||||
let (delim, tts) = self.expect_delimited_token_tree()?;
|
||||
|
|
21
src/test/ui/did_you_mean/issue-40006.rs
Normal file
21
src/test/ui/did_you_mean/issue-40006.rs
Normal 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();
|
||||
}
|
12
src/test/ui/did_you_mean/issue-40006.stderr
Normal file
12
src/test/ui/did_you_mean/issue-40006.stderr
Normal 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
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue