@@ -43,12 +43,23 @@ pub(super) enum RecoverQPath {
43
43
No ,
44
44
}
45
45
46
- #[ derive( PartialEq ) ]
47
- pub ( super ) enum RecoverFatArrow {
46
+ #[ derive( Copy , Clone , PartialEq ) ]
47
+ pub ( super ) enum RecoverReturnSign {
48
48
Yes ,
49
+ OnlyFatArrow ,
49
50
No ,
50
51
}
51
52
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
+
52
63
// Is `...` (`CVarArgs`) legal at this level of type parsing?
53
64
#[ derive( PartialEq ) ]
54
65
enum AllowCVariadic {
@@ -68,14 +79,24 @@ fn can_continue_type_after_non_fn_ident(t: &Token) -> bool {
68
79
impl < ' a > Parser < ' a > {
69
80
/// Parses a type.
70
81
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
+ )
72
88
}
73
89
74
90
/// Parse a type suitable for a function or function pointer parameter.
75
91
/// The difference from `parse_ty` is that this version allows `...`
76
92
/// (`CVarArgs`) at the top level of the type.
77
93
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
+ )
79
100
}
80
101
81
102
/// Parses a type in restricted contexts where `+` is not permitted.
@@ -85,21 +106,41 @@ impl<'a> Parser<'a> {
85
106
/// Example 2: `value1 as TYPE + value2`
86
107
/// `+` is prohibited to avoid interactions with expression grammar.
87
108
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
+ )
89
125
}
90
126
91
127
/// Parses an optional return type `[ -> TY ]` in a function declaration.
92
128
pub ( super ) fn parse_ret_ty (
93
129
& mut self ,
94
130
allow_plus : AllowPlus ,
95
131
recover_qpath : RecoverQPath ,
96
- recover_fat_arrow : RecoverFatArrow ,
132
+ recover_return_sign : RecoverReturnSign ,
97
133
) -> PResult < ' a , FnRetTy > {
98
134
Ok ( if self . eat ( & token:: RArrow ) {
99
135
// 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
+ ) ?;
101
142
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 ) {
103
144
// Don't `eat` to prevent `=>` from being added as an expected token which isn't
104
145
// actually expected and could only confuse users
105
146
self . bump ( ) ;
@@ -111,7 +152,12 @@ impl<'a> Parser<'a> {
111
152
Applicability :: MachineApplicable ,
112
153
)
113
154
. 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
+ ) ?;
115
161
FnRetTy :: Ty ( ty)
116
162
} else {
117
163
FnRetTy :: Default ( self . token . span . shrink_to_lo ( ) )
@@ -123,6 +169,7 @@ impl<'a> Parser<'a> {
123
169
allow_plus : AllowPlus ,
124
170
recover_qpath : RecoverQPath ,
125
171
allow_c_variadic : AllowCVariadic ,
172
+ recover_return_sign : RecoverReturnSign ,
126
173
) -> PResult < ' a , P < Ty > > {
127
174
let allow_qpath_recovery = recover_qpath == RecoverQPath :: Yes ;
128
175
maybe_recover_from_interpolated_ty_qpath ! ( self , allow_qpath_recovery) ;
@@ -150,14 +197,14 @@ impl<'a> Parser<'a> {
150
197
TyKind :: Infer
151
198
} else if self . check_fn_front_matter ( ) {
152
199
// Function pointer type
153
- self . parse_ty_bare_fn ( lo, Vec :: new ( ) ) ?
200
+ self . parse_ty_bare_fn ( lo, Vec :: new ( ) , recover_return_sign ) ?
154
201
} else if self . check_keyword ( kw:: For ) {
155
202
// Function pointer type or bound list (trait object type) starting with a poly-trait.
156
203
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
157
204
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
158
205
let lifetime_defs = self . parse_late_bound_lifetime_defs ( ) ?;
159
206
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 ) ?
161
208
} else {
162
209
let path = self . parse_path ( PathStyle :: Type ) ?;
163
210
let parse_plus = allow_plus == AllowPlus :: Yes && self . check_plus ( ) ;
@@ -359,9 +406,14 @@ impl<'a> Parser<'a> {
359
406
/// Function Style ABI Parameter types
360
407
/// ```
361
408
/// 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 > {
363
415
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 ) ?;
365
417
let whole_span = lo. to ( self . prev_token . span ) ;
366
418
if let ast:: Const :: Yes ( span) = constness {
367
419
self . error_fn_ptr_bad_qualifier ( whole_span, span, "const" ) ;
0 commit comments