@@ -43,12 +43,23 @@ pub(super) enum RecoverQPath {
4343 No ,
4444}
4545
46- #[ derive( PartialEq ) ]
47- pub ( super ) enum RecoverFatArrow {
46+ #[ derive( Copy , Clone , PartialEq ) ]
47+ pub ( super ) enum RecoverReturnSign {
4848 Yes ,
49+ OnlyFatArrow ,
4950 No ,
5051}
5152
53+ impl RecoverReturnSign {
54+ fn can_recover ( self , token : & TokenKind ) -> bool {
55+ match self {
56+ Self :: Yes => matches ! ( token, token:: FatArrow | token:: Colon ) ,
57+ Self :: OnlyFatArrow => matches ! ( token, token:: FatArrow ) ,
58+ Self :: No => false ,
59+ }
60+ }
61+ }
62+
5263// Is `...` (`CVarArgs`) legal at this level of type parsing?
5364#[ derive( PartialEq ) ]
5465enum AllowCVariadic {
@@ -68,14 +79,24 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
6879impl < ' a > Parser < ' a > {
6980 /// Parses a type.
7081 pub fn parse_ty ( & mut self ) -> PResult < ' a , P < Ty > > {
71- self . parse_ty_common ( AllowPlus :: Yes , RecoverQPath :: Yes , AllowCVariadic :: No )
82+ self . parse_ty_common (
83+ AllowPlus :: Yes ,
84+ RecoverQPath :: Yes ,
85+ AllowCVariadic :: No ,
86+ RecoverReturnSign :: Yes ,
87+ )
7288 }
7389
7490 /// Parse a type suitable for a function or function pointer parameter.
7591 /// The difference from `parse_ty` is that this version allows `...`
7692 /// (`CVarArgs`) at the top level of the type.
7793 pub ( super ) fn parse_ty_for_param ( & mut self ) -> PResult < ' a , P < Ty > > {
78- self . parse_ty_common ( AllowPlus :: Yes , RecoverQPath :: Yes , AllowCVariadic :: Yes )
94+ self . parse_ty_common (
95+ AllowPlus :: Yes ,
96+ RecoverQPath :: Yes ,
97+ AllowCVariadic :: Yes ,
98+ RecoverReturnSign :: Yes ,
99+ )
79100 }
80101
81102 /// Parses a type in restricted contexts where `+` is not permitted.
@@ -85,21 +106,41 @@ impl<'a> Parser<'a> {
85106 /// Example 2: `value1 as TYPE + value2`
86107 /// `+` is prohibited to avoid interactions with expression grammar.
87108 pub ( super ) fn parse_ty_no_plus ( & mut self ) -> PResult < ' a , P < Ty > > {
88- self . parse_ty_common ( AllowPlus :: No , RecoverQPath :: Yes , AllowCVariadic :: No )
109+ self . parse_ty_common (
110+ AllowPlus :: No ,
111+ RecoverQPath :: Yes ,
112+ AllowCVariadic :: No ,
113+ RecoverReturnSign :: Yes ,
114+ )
115+ }
116+
117+ /// Parse a type without recovering `:` as `->` to avoid breaking code such as `where fn() : for<'a>`
118+ pub ( super ) fn parse_ty_for_where_clause ( & mut self ) -> PResult < ' a , P < Ty > > {
119+ self . parse_ty_common (
120+ AllowPlus :: Yes ,
121+ RecoverQPath :: Yes ,
122+ AllowCVariadic :: Yes ,
123+ RecoverReturnSign :: OnlyFatArrow ,
124+ )
89125 }
90126
91127 /// Parses an optional return type `[ -> TY ]` in a function declaration.
92128 pub ( super ) fn parse_ret_ty (
93129 & mut self ,
94130 allow_plus : AllowPlus ,
95131 recover_qpath : RecoverQPath ,
96- recover_fat_arrow : RecoverFatArrow ,
132+ recover_return_sign : RecoverReturnSign ,
97133 ) -> PResult < ' a , FnRetTy > {
98134 Ok ( if self . eat ( & token:: RArrow ) {
99135 // FIXME(Centril): Can we unconditionally `allow_plus`?
100- let ty = self . parse_ty_common ( allow_plus, recover_qpath, AllowCVariadic :: No ) ?;
136+ let ty = self . parse_ty_common (
137+ allow_plus,
138+ recover_qpath,
139+ AllowCVariadic :: No ,
140+ recover_return_sign,
141+ ) ?;
101142 FnRetTy :: Ty ( ty)
102- } else if recover_fat_arrow == RecoverFatArrow :: Yes && self . token == token :: FatArrow {
143+ } else if recover_return_sign . can_recover ( & self . token . kind ) {
103144 // Don't `eat` to prevent `=>` from being added as an expected token which isn't
104145 // actually expected and could only confuse users
105146 self . bump ( ) ;
@@ -111,7 +152,12 @@ impl<'a> Parser<'a> {
111152 Applicability :: MachineApplicable ,
112153 )
113154 . emit ( ) ;
114- let ty = self . parse_ty_common ( allow_plus, recover_qpath, AllowCVariadic :: No ) ?;
155+ let ty = self . parse_ty_common (
156+ allow_plus,
157+ recover_qpath,
158+ AllowCVariadic :: No ,
159+ recover_return_sign,
160+ ) ?;
115161 FnRetTy :: Ty ( ty)
116162 } else {
117163 FnRetTy :: Default ( self . token . span . shrink_to_lo ( ) )
@@ -123,6 +169,7 @@ impl<'a> Parser<'a> {
123169 allow_plus : AllowPlus ,
124170 recover_qpath : RecoverQPath ,
125171 allow_c_variadic : AllowCVariadic ,
172+ recover_return_sign : RecoverReturnSign ,
126173 ) -> PResult < ' a , P < Ty > > {
127174 let allow_qpath_recovery = recover_qpath == RecoverQPath :: Yes ;
128175 maybe_recover_from_interpolated_ty_qpath ! ( self , allow_qpath_recovery) ;
@@ -150,14 +197,14 @@ impl<'a> Parser<'a> {
150197 TyKind :: Infer
151198 } else if self . check_fn_front_matter ( ) {
152199 // Function pointer type
153- self . parse_ty_bare_fn ( lo, Vec :: new ( ) ) ?
200+ self . parse_ty_bare_fn ( lo, Vec :: new ( ) , recover_return_sign ) ?
154201 } else if self . check_keyword ( kw:: For ) {
155202 // Function pointer type or bound list (trait object type) starting with a poly-trait.
156203 // `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
157204 // `for<'lt> Trait1<'lt> + Trait2 + 'a`
158205 let lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?;
159206 if self . check_fn_front_matter ( ) {
160- self . parse_ty_bare_fn ( lo, lifetime_defs) ?
207+ self . parse_ty_bare_fn ( lo, lifetime_defs, recover_return_sign ) ?
161208 } else {
162209 let path = self . parse_path ( PathStyle :: Type ) ?;
163210 let parse_plus = allow_plus == AllowPlus :: Yes && self . check_plus ( ) ;
@@ -359,9 +406,14 @@ impl<'a> Parser<'a> {
359406 /// Function Style ABI Parameter types
360407 /// ```
361408 /// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
362- fn parse_ty_bare_fn ( & mut self , lo : Span , params : Vec < GenericParam > ) -> PResult < ' a , TyKind > {
409+ fn parse_ty_bare_fn (
410+ & mut self ,
411+ lo : Span ,
412+ params : Vec < GenericParam > ,
413+ recover_return_sign : RecoverReturnSign ,
414+ ) -> PResult < ' a , TyKind > {
363415 let ast:: FnHeader { ext, unsafety, constness, asyncness } = self . parse_fn_front_matter ( ) ?;
364- let decl = self . parse_fn_decl ( |_| false , AllowPlus :: No ) ?;
416+ let decl = self . parse_fn_decl ( |_| false , AllowPlus :: No , recover_return_sign ) ?;
365417 let whole_span = lo. to ( self . prev_token . span ) ;
366418 if let ast:: Const :: Yes ( span) = constness {
367419 self . error_fn_ptr_bad_qualifier ( whole_span, span, "const" ) ;
0 commit comments