@@ -4660,25 +4660,30 @@ impl<'a> Parser<'a> {
4660
4660
} )
4661
4661
}
4662
4662
4663
- fn complain_if_pub_macro ( & mut self , visa : & Visibility , span : Span ) {
4664
- match * visa {
4665
- Visibility :: Inherited => ( ) ,
4663
+ fn complain_if_pub_macro ( & mut self , vis : & Visibility , sp : Span ) {
4664
+ if let Err ( mut err) = self . complain_if_pub_macro_diag ( vis, sp) {
4665
+ err. emit ( ) ;
4666
+ }
4667
+ }
4668
+
4669
+ fn complain_if_pub_macro_diag ( & mut self , vis : & Visibility , sp : Span ) -> PResult < ' a , ( ) > {
4670
+ match * vis {
4671
+ Visibility :: Inherited => Ok ( ( ) ) ,
4666
4672
_ => {
4667
4673
let is_macro_rules: bool = match self . token {
4668
4674
token:: Ident ( sid) => sid. name == Symbol :: intern ( "macro_rules" ) ,
4669
4675
_ => false ,
4670
4676
} ;
4671
4677
if is_macro_rules {
4672
- self . diagnostic ( ) . struct_span_err ( span , "can't qualify macro_rules \
4673
- invocation with `pub`")
4674
- . help ( "did you mean #[macro_export]?" )
4675
- . emit ( ) ;
4678
+ let mut err = self . diagnostic ( )
4679
+ . struct_span_err ( sp , "can't qualify macro_rules invocation with `pub`") ;
4680
+ err . help ( "did you mean #[macro_export]?" ) ;
4681
+ Err ( err )
4676
4682
} else {
4677
- self . diagnostic ( ) . struct_span_err ( span, "can't qualify macro \
4678
- invocation with `pub`")
4679
- . help ( "try adjusting the macro to put `pub` \
4680
- inside the invocation")
4681
- . emit ( ) ;
4683
+ let mut err = self . diagnostic ( )
4684
+ . struct_span_err ( sp, "can't qualify macro invocation with `pub`" ) ;
4685
+ err. help ( "try adjusting the macro to put `pub` inside the invocation" ) ;
4686
+ Err ( err)
4682
4687
}
4683
4688
}
4684
4689
}
@@ -4689,14 +4694,41 @@ impl<'a> Parser<'a> {
4689
4694
-> PResult < ' a , ( Ident , Vec < ast:: Attribute > , ast:: ImplItemKind ) > {
4690
4695
// code copied from parse_macro_use_or_failure... abstraction!
4691
4696
if self . token . is_path_start ( ) {
4692
- // method macro.
4697
+ // Method macro.
4693
4698
4694
4699
let prev_span = self . prev_span ;
4695
- self . complain_if_pub_macro ( & vis, prev_span) ;
4700
+ // Before complaining about trying to set a macro as `pub`,
4701
+ // check if `!` comes after the path.
4702
+ let err = self . complain_if_pub_macro_diag ( & vis, prev_span) ;
4696
4703
4697
4704
let lo = self . span . lo ;
4698
4705
let pth = self . parse_path ( PathStyle :: Mod ) ?;
4699
- self . expect ( & token:: Not ) ?;
4706
+ let bang_err = self . expect ( & token:: Not ) ;
4707
+ if let Err ( mut err) = err {
4708
+ if let Err ( mut bang_err) = bang_err {
4709
+ // Given this code `pub path(`, it seems like this is not setting the
4710
+ // visibility of a macro invocation, but rather a mistyped method declaration.
4711
+ // Keep the macro diagnostic, but also provide a hint that `fn` might be
4712
+ // missing. Don't complain about the missing `!` as a separate diagnostic, add
4713
+ // label in the appropriate place as part of one unified diagnostic.
4714
+ //
4715
+ // x | pub path(&self) {
4716
+ // | ^^^- - expected `!` here for a macro invocation
4717
+ // | |
4718
+ // | did you mean to write `fn` here for a method declaration?
4719
+
4720
+ bang_err. cancel ( ) ;
4721
+ err. span_label ( self . span , & "expected `!` here for a macro invocation" ) ;
4722
+ // pub path(
4723
+ // ^^ `sp` below will point to this
4724
+ let sp = mk_sp ( prev_span. hi , self . prev_span . lo ) ;
4725
+ err. span_label ( sp,
4726
+ & "did you mean to write `fn` here for a method declaration?" ) ;
4727
+ }
4728
+ return Err ( err) ;
4729
+ } else if let Err ( bang_err) = bang_err {
4730
+ return Err ( bang_err) ;
4731
+ }
4700
4732
4701
4733
// eat a matched-delimiter token tree:
4702
4734
let ( delim, tts) = self . expect_delimited_token_tree ( ) ?;
0 commit comments