@@ -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, false ) ?; // `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,35 @@ 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 `is_fn_pointer_type`, 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
+ is_fn_pointer_type : bool ,
2665
2669
) -> PResult < ' a , FnHeader > {
2666
2670
let sp_start = self . token . span ;
2667
2671
let constness = self . parse_constness ( case) ;
2672
+ if is_fn_pointer_type && let Const :: Yes ( const_span) = constness {
2673
+ self . dcx ( ) . emit_err ( FnPointerCannotBeConst {
2674
+ span : const_span,
2675
+ suggestion : const_span. until ( self . token . span ) ,
2676
+ } ) ;
2677
+ }
2668
2678
2669
2679
let async_start_sp = self . token . span ;
2670
2680
let coroutine_kind = self . parse_coroutine_kind ( case) ;
2681
+ if is_fn_pointer_type
2682
+ && let Some ( ast:: CoroutineKind :: Async { span : async_span, .. } ) = coroutine_kind
2683
+ {
2684
+ self . dcx ( ) . emit_err ( FnPointerCannotBeAsync {
2685
+ span : async_span,
2686
+ suggestion : async_span. until ( self . token . span ) ,
2687
+ } ) ;
2688
+ }
2689
+ // FIXME(gen_blocks): emit a similar error for `gen fn()`
2671
2690
2672
2691
let unsafe_start_sp = self . token . span ;
2673
2692
let safety = self . parse_safety ( case) ;
@@ -2703,6 +2722,11 @@ impl<'a> Parser<'a> {
2703
2722
enum WrongKw {
2704
2723
Duplicated ( Span ) ,
2705
2724
Misplaced ( Span ) ,
2725
+ /// `MisplacedDisallowedQualifier` is only used instead of `Misplaced`,
2726
+ /// when the misplaced keyword is disallowed by `is_fn_pointer_type`.
2727
+ /// In this case, we avoid generating the suggestion to swap around the keywords,
2728
+ /// as we already generated a suggestion to remove the keyword earlier.
2729
+ MisplacedDisallowedQualifier ,
2706
2730
}
2707
2731
2708
2732
// We may be able to recover
@@ -2716,7 +2740,18 @@ impl<'a> Parser<'a> {
2716
2740
Const :: Yes ( sp) => Some ( WrongKw :: Duplicated ( sp) ) ,
2717
2741
Const :: No => {
2718
2742
recover_constness = Const :: Yes ( self . token . span ) ;
2719
- Some ( WrongKw :: Misplaced ( async_start_sp) )
2743
+ if is_fn_pointer_type {
2744
+ self . dcx ( ) . emit_err ( FnPointerCannotBeConst {
2745
+ span : self . token . span ,
2746
+ suggestion : self
2747
+ . token
2748
+ . span
2749
+ . with_lo ( self . prev_token . span . hi ( ) ) ,
2750
+ } ) ;
2751
+ Some ( WrongKw :: MisplacedDisallowedQualifier )
2752
+ } else {
2753
+ Some ( WrongKw :: Misplaced ( async_start_sp) )
2754
+ }
2720
2755
}
2721
2756
}
2722
2757
} else if self . check_keyword ( exp ! ( Async ) ) {
@@ -2742,7 +2777,18 @@ impl<'a> Parser<'a> {
2742
2777
closure_id : DUMMY_NODE_ID ,
2743
2778
return_impl_trait_id : DUMMY_NODE_ID ,
2744
2779
} ) ;
2745
- Some ( WrongKw :: Misplaced ( unsafe_start_sp) )
2780
+ if is_fn_pointer_type {
2781
+ self . dcx ( ) . emit_err ( FnPointerCannotBeAsync {
2782
+ span : self . token . span ,
2783
+ suggestion : self
2784
+ . token
2785
+ . span
2786
+ . with_lo ( self . prev_token . span . hi ( ) ) ,
2787
+ } ) ;
2788
+ Some ( WrongKw :: MisplacedDisallowedQualifier )
2789
+ } else {
2790
+ Some ( WrongKw :: Misplaced ( unsafe_start_sp) )
2791
+ }
2746
2792
}
2747
2793
}
2748
2794
} else if self . check_keyword ( exp ! ( Unsafe ) ) {
0 commit comments