@@ -4657,25 +4657,30 @@ impl<'a> Parser<'a> {
46574657 } )
46584658 }
46594659
4660- fn complain_if_pub_macro ( & mut self , visa : & Visibility , span : Span ) {
4661- match * visa {
4662- Visibility :: Inherited => ( ) ,
4660+ fn complain_if_pub_macro ( & mut self , vis : & Visibility , sp : Span ) {
4661+ if let Err ( mut err) = self . complain_if_pub_macro_diag ( vis, sp) {
4662+ err. emit ( ) ;
4663+ }
4664+ }
4665+
4666+ fn complain_if_pub_macro_diag ( & mut self , vis : & Visibility , sp : Span ) -> PResult < ' a , ( ) > {
4667+ match * vis {
4668+ Visibility :: Inherited => Ok ( ( ) ) ,
46634669 _ => {
46644670 let is_macro_rules: bool = match self . token {
46654671 token:: Ident ( sid) => sid. name == Symbol :: intern ( "macro_rules" ) ,
46664672 _ => false ,
46674673 } ;
46684674 if is_macro_rules {
4669- self . diagnostic ( ) . struct_span_err ( span , "can't qualify macro_rules \
4670- invocation with `pub`")
4671- . help ( "did you mean #[macro_export]?" )
4672- . emit ( ) ;
4675+ let mut err = self . diagnostic ( )
4676+ . struct_span_err ( sp , "can't qualify macro_rules invocation with `pub`") ;
4677+ err . help ( "did you mean #[macro_export]?" ) ;
4678+ Err ( err )
46734679 } else {
4674- self . diagnostic ( ) . struct_span_err ( span, "can't qualify macro \
4675- invocation with `pub`")
4676- . help ( "try adjusting the macro to put `pub` \
4677- inside the invocation")
4678- . emit ( ) ;
4680+ let mut err = self . diagnostic ( )
4681+ . struct_span_err ( sp, "can't qualify macro invocation with `pub`" ) ;
4682+ err. help ( "try adjusting the macro to put `pub` inside the invocation" ) ;
4683+ Err ( err)
46794684 }
46804685 }
46814686 }
@@ -4686,14 +4691,36 @@ impl<'a> Parser<'a> {
46864691 -> PResult < ' a , ( Ident , Vec < ast:: Attribute > , ast:: ImplItemKind ) > {
46874692 // code copied from parse_macro_use_or_failure... abstraction!
46884693 if self . token . is_path_start ( ) {
4689- // method macro.
4694+ // Method macro.
46904695
46914696 let prev_span = self . prev_span ;
4692- self . complain_if_pub_macro ( & vis, prev_span) ;
4697+ // Before complaining about trying to set a macro as `pub`,
4698+ // check if `!` comes after the path.
4699+ let err = self . complain_if_pub_macro_diag ( & vis, prev_span) ;
46934700
46944701 let lo = self . span ;
46954702 let pth = self . parse_path ( PathStyle :: Mod ) ?;
4696- self . expect ( & token:: Not ) ?;
4703+ let bang_err = self . expect ( & token:: Not ) ;
4704+ if let Err ( mut err) = err {
4705+ if let Err ( mut bang_err) = bang_err {
4706+ // Given this code `pub path(`, it seems like this is not setting the
4707+ // visibility of a macro invocation, but rather a mistyped method declaration.
4708+ // Create a diagnostic pointing out that `fn` is missing.
4709+ //
4710+ // x | pub path(&self) {
4711+ // | ^ missing `fn` for method declaration
4712+
4713+ err. cancel ( ) ;
4714+ bang_err. cancel ( ) ;
4715+ // pub path(
4716+ // ^^ `sp` below will point to this
4717+ let sp = prev_span. between ( self . prev_span ) ;
4718+ err = self . diagnostic ( )
4719+ . struct_span_err ( sp, "missing `fn` for method declaration" ) ;
4720+ err. span_label ( sp, & "missing `fn`" ) ;
4721+ }
4722+ return Err ( err) ;
4723+ }
46974724
46984725 // eat a matched-delimiter token tree:
46994726 let ( delim, tts) = self . expect_delimited_token_tree ( ) ?;
0 commit comments