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) {
|
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()?;
|
||||||
|
|
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