@@ -23,7 +23,7 @@ use super::{
23
23
AttrWrapper , ExpKeywordPair , ExpTokenPair , FollowedByType , ForceCollect , Parser , PathStyle ,
24
24
Recovered , Trailing , UsePreAttrPos ,
25
25
} ;
26
- use crate :: errors:: { self , MacroExpandsToAdtField } ;
26
+ use crate :: errors:: { self , FnPointerCannotBeAsync , FnPointerCannotBeConst , MacroExpandsToAdtField } ;
27
27
use crate :: { exp, fluent_generated as fluent} ;
28
28
29
29
impl < ' a > Parser < ' a > {
@@ -2402,7 +2402,7 @@ impl<'a> Parser<'a> {
2402
2402
case : Case ,
2403
2403
) -> PResult < ' a , ( Ident , FnSig , Generics , Option < P < FnContract > > , Option < P < Block > > ) > {
2404
2404
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`
2406
2406
let ident = self . parse_ident ( ) ?; // `foo`
2407
2407
let mut generics = self . parse_generics ( ) ?; // `<'a, T, ...>`
2408
2408
let decl = match self . parse_fn_decl (
@@ -2658,16 +2658,37 @@ impl<'a> Parser<'a> {
2658
2658
///
2659
2659
/// `vis` represents the visibility that was already parsed, if any. Use
2660
2660
/// `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.
2661
2664
pub ( super ) fn parse_fn_front_matter (
2662
2665
& mut self ,
2663
2666
orig_vis : & Visibility ,
2664
2667
case : Case ,
2668
+ parsing_mode : FrontMatterParsingMode ,
2665
2669
) -> PResult < ' a , FnHeader > {
2666
2670
let sp_start = self . token . span ;
2667
2671
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
+ }
2668
2680
2669
2681
let async_start_sp = self . token . span ;
2670
2682
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()`
2671
2692
2672
2693
let unsafe_start_sp = self . token . span ;
2673
2694
let safety = self . parse_safety ( case) ;
@@ -2703,6 +2724,11 @@ impl<'a> Parser<'a> {
2703
2724
enum WrongKw {
2704
2725
Duplicated ( Span ) ,
2705
2726
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 ,
2706
2732
}
2707
2733
2708
2734
// We may be able to recover
@@ -2716,7 +2742,21 @@ impl<'a> Parser<'a> {
2716
2742
Const :: Yes ( sp) => Some ( WrongKw :: Duplicated ( sp) ) ,
2717
2743
Const :: No => {
2718
2744
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
+ }
2720
2760
}
2721
2761
}
2722
2762
} else if self . check_keyword ( exp ! ( Async ) ) {
@@ -2742,7 +2782,21 @@ impl<'a> Parser<'a> {
2742
2782
closure_id : DUMMY_NODE_ID ,
2743
2783
return_impl_trait_id : DUMMY_NODE_ID ,
2744
2784
} ) ;
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
+ }
2746
2800
}
2747
2801
}
2748
2802
} else if self . check_keyword ( exp ! ( Unsafe ) ) {
@@ -3194,3 +3248,12 @@ enum IsMacroRulesItem {
3194
3248
Yes { has_bang : bool } ,
3195
3249
No ,
3196
3250
}
3251
+
3252
+ #[ derive( Copy , Clone , PartialEq , Eq ) ]
3253
+ pub ( super ) enum FrontMatterParsingMode {
3254
+ /// Parse the front matter of a function declaration
3255
+ Function ,
3256
+ /// Parse the front matter of a function pointet type.
3257
+ /// For function pointer types, the `const` and `async` keywords are not permitted.
3258
+ FunctionPtrType ,
3259
+ }
0 commit comments