@@ -23,7 +23,7 @@ use super::{
2323    AttrWrapper ,  ExpKeywordPair ,  ExpTokenPair ,  FollowedByType ,  ForceCollect ,  Parser ,  PathStyle , 
2424    Recovered ,  Trailing ,  UsePreAttrPos , 
2525} ; 
26- use  crate :: errors:: { self ,  MacroExpandsToAdtField } ; 
26+ use  crate :: errors:: { self ,  FnPointerCannotBeAsync ,   FnPointerCannotBeConst ,   MacroExpandsToAdtField } ; 
2727use  crate :: { exp,  fluent_generated as  fluent} ; 
2828
2929impl < ' a >  Parser < ' a >  { 
@@ -2402,7 +2402,7 @@ impl<'a> Parser<'a> {
24022402        case :  Case , 
24032403    )  -> PResult < ' a ,  ( Ident ,  FnSig ,  Generics ,  Option < P < FnContract > > ,  Option < P < Block > > ) >  { 
24042404        let  fn_span = self . token . span ; 
2405-         let  header = self . parse_fn_front_matter ( vis,  case) ?;  // `const ... fn` 
2405+         let  header = self . parse_fn_front_matter ( vis,  case,   FrontMatterParsingMode :: Function ) ?;  // `const ... fn` 
24062406        let  ident = self . parse_ident ( ) ?;  // `foo` 
24072407        let  mut  generics = self . parse_generics ( ) ?;  // `<'a, T, ...>` 
24082408        let  decl = match  self . parse_fn_decl ( 
@@ -2658,16 +2658,37 @@ impl<'a> Parser<'a> {
26582658     /// 
26592659     /// `vis` represents the visibility that was already parsed, if any. Use 
26602660     /// `Visibility::Inherited` when no visibility is known. 
2661+      /// 
2662+      /// If `parsing_mode` is `FrontMatterParsingMode::FunctionPtrType`, we error on `const` and `async` qualifiers, 
2663+      /// which are not allowed in function pointer types. 
26612664     pub ( super )  fn  parse_fn_front_matter ( 
26622665        & mut  self , 
26632666        orig_vis :  & Visibility , 
26642667        case :  Case , 
2668+         parsing_mode :  FrontMatterParsingMode , 
26652669    )  -> PResult < ' a ,  FnHeader >  { 
26662670        let  sp_start = self . token . span ; 
26672671        let  constness = self . parse_constness ( case) ; 
2672+         if  parsing_mode == FrontMatterParsingMode :: FunctionPtrType 
2673+             && let  Const :: Yes ( const_span)  = constness
2674+         { 
2675+             self . dcx ( ) . emit_err ( FnPointerCannotBeConst  { 
2676+                 span :  const_span, 
2677+                 suggestion :  const_span. until ( self . token . span ) , 
2678+             } ) ; 
2679+         } 
26682680
26692681        let  async_start_sp = self . token . span ; 
26702682        let  coroutine_kind = self . parse_coroutine_kind ( case) ; 
2683+         if  parsing_mode == FrontMatterParsingMode :: FunctionPtrType 
2684+             && let  Some ( ast:: CoroutineKind :: Async  {  span :  async_span,  .. } )  = coroutine_kind
2685+         { 
2686+             self . dcx ( ) . emit_err ( FnPointerCannotBeAsync  { 
2687+                 span :  async_span, 
2688+                 suggestion :  async_span. until ( self . token . span ) , 
2689+             } ) ; 
2690+         } 
2691+         // FIXME(gen_blocks): emit a similar error for `gen fn()` 
26712692
26722693        let  unsafe_start_sp = self . token . span ; 
26732694        let  safety = self . parse_safety ( case) ; 
@@ -2703,6 +2724,11 @@ impl<'a> Parser<'a> {
27032724                    enum  WrongKw  { 
27042725                        Duplicated ( Span ) , 
27052726                        Misplaced ( Span ) , 
2727+                         /// `MisplacedDisallowedQualifier` is only used instead of `Misplaced`, 
2728+                          /// when the misplaced keyword is disallowed by the current `FrontMatterParsingMode`. 
2729+                          /// In this case, we avoid generating the suggestion to swap around the keywords, 
2730+                          /// as we already generated a suggestion to remove the keyword earlier. 
2731+                          MisplacedDisallowedQualifier , 
27062732                    } 
27072733
27082734                    // We may be able to recover 
@@ -2716,7 +2742,21 @@ impl<'a> Parser<'a> {
27162742                            Const :: Yes ( sp)  => Some ( WrongKw :: Duplicated ( sp) ) , 
27172743                            Const :: No  => { 
27182744                                recover_constness = Const :: Yes ( self . token . span ) ; 
2719-                                 Some ( WrongKw :: Misplaced ( async_start_sp) ) 
2745+                                 match  parsing_mode { 
2746+                                     FrontMatterParsingMode :: Function  => { 
2747+                                         Some ( WrongKw :: Misplaced ( async_start_sp) ) 
2748+                                     } 
2749+                                     FrontMatterParsingMode :: FunctionPtrType  => { 
2750+                                         self . dcx ( ) . emit_err ( FnPointerCannotBeConst  { 
2751+                                             span :  self . token . span , 
2752+                                             suggestion :  self 
2753+                                                 . token 
2754+                                                 . span 
2755+                                                 . with_lo ( self . prev_token . span . hi ( ) ) , 
2756+                                         } ) ; 
2757+                                         Some ( WrongKw :: MisplacedDisallowedQualifier ) 
2758+                                     } 
2759+                                 } 
27202760                            } 
27212761                        } 
27222762                    }  else  if  self . check_keyword ( exp ! ( Async ) )  { 
@@ -2742,7 +2782,21 @@ impl<'a> Parser<'a> {
27422782                                    closure_id :  DUMMY_NODE_ID , 
27432783                                    return_impl_trait_id :  DUMMY_NODE_ID , 
27442784                                } ) ; 
2745-                                 Some ( WrongKw :: Misplaced ( unsafe_start_sp) ) 
2785+                                 match  parsing_mode { 
2786+                                     FrontMatterParsingMode :: Function  => { 
2787+                                         Some ( WrongKw :: Misplaced ( async_start_sp) ) 
2788+                                     } 
2789+                                     FrontMatterParsingMode :: FunctionPtrType  => { 
2790+                                         self . dcx ( ) . emit_err ( FnPointerCannotBeAsync  { 
2791+                                             span :  self . token . span , 
2792+                                             suggestion :  self 
2793+                                                 . token 
2794+                                                 . span 
2795+                                                 . with_lo ( self . prev_token . span . hi ( ) ) , 
2796+                                         } ) ; 
2797+                                         Some ( WrongKw :: MisplacedDisallowedQualifier ) 
2798+                                     } 
2799+                                 } 
27462800                            } 
27472801                        } 
27482802                    }  else  if  self . check_keyword ( exp ! ( Unsafe ) )  { 
@@ -2840,14 +2894,20 @@ impl<'a> Parser<'a> {
28402894
28412895                    // FIXME(gen_blocks): add keyword recovery logic for genness 
28422896
2843-                     if  wrong_kw . is_some ( ) 
2897+                     if  let   Some ( wrong_kw )  = wrong_kw 
28442898                        && self . may_recover ( ) 
28452899                        && self . look_ahead ( 1 ,  |tok| tok. is_keyword_case ( kw:: Fn ,  case) ) 
28462900                    { 
28472901                        // Advance past the misplaced keyword and `fn` 
28482902                        self . bump ( ) ; 
28492903                        self . bump ( ) ; 
2850-                         err. emit ( ) ; 
2904+                         // When we recover from a `MisplacedDisallowedQualifier`, we already emitted an error for the disallowed qualifier 
2905+                         // So we don't emit another error that the qualifier is unexpected. 
2906+                         if  matches ! ( wrong_kw,  WrongKw :: MisplacedDisallowedQualifier )  { 
2907+                             err. cancel ( ) ; 
2908+                         }  else  { 
2909+                             err. emit ( ) ; 
2910+                         } 
28512911                        return  Ok ( FnHeader  { 
28522912                            constness :  recover_constness, 
28532913                            safety :  recover_safety, 
@@ -3194,3 +3254,12 @@ enum IsMacroRulesItem {
31943254    Yes  {  has_bang :  bool  } , 
31953255    No , 
31963256} 
3257+ 
3258+ #[ derive( Copy ,  Clone ,  PartialEq ,  Eq ) ]  
3259+ pub ( super )  enum  FrontMatterParsingMode  { 
3260+     /// Parse the front matter of a function declaration 
3261+      Function , 
3262+     /// Parse the front matter of a function pointet type. 
3263+      /// For function pointer types, the `const` and `async` keywords are not permitted. 
3264+      FunctionPtrType , 
3265+ } 
0 commit comments