@@ -11,6 +11,7 @@ use rustc_ast::{
1111 self as ast, BareFnTy , FnRetTy , GenericBound , GenericBounds , GenericParam , Generics , Lifetime ,
1212 MacCall , MutTy , Mutability , PolyTraitRef , TraitBoundModifier , TraitObjectSyntax , Ty , TyKind ,
1313} ;
14+ use rustc_ast_pretty:: pprust;
1415use rustc_errors:: { pluralize, struct_span_err, Applicability , PResult } ;
1516use rustc_span:: source_map:: Span ;
1617use rustc_span:: symbol:: { kw, sym, Ident } ;
@@ -43,17 +44,24 @@ pub(super) enum AllowPlus {
4344 No ,
4445}
4546
46- #[ derive( PartialEq ) ]
47+ #[ derive( PartialEq , Clone , Copy ) ]
4748pub ( super ) enum RecoverQPath {
4849 Yes ,
4950 No ,
5051}
5152
53+ #[ derive( PartialEq , Clone , Copy ) ]
5254pub ( super ) enum RecoverQuestionMark {
5355 Yes ,
5456 No ,
5557}
5658
59+ #[ derive( PartialEq , Clone , Copy ) ]
60+ pub ( super ) enum RecoverAnonEnum {
61+ Yes ,
62+ No ,
63+ }
64+
5765/// Signals whether parsing a type should recover `->`.
5866///
5967/// More specifically, when parsing a function like:
@@ -86,7 +94,7 @@ impl RecoverReturnSign {
8694}
8795
8896// Is `...` (`CVarArgs`) legal at this level of type parsing?
89- #[ derive( PartialEq ) ]
97+ #[ derive( PartialEq , Clone , Copy ) ]
9098enum AllowCVariadic {
9199 Yes ,
92100 No ,
@@ -111,6 +119,7 @@ impl<'a> Parser<'a> {
111119 RecoverReturnSign :: Yes ,
112120 None ,
113121 RecoverQuestionMark :: Yes ,
122+ RecoverAnonEnum :: No ,
114123 )
115124 }
116125
@@ -125,6 +134,7 @@ impl<'a> Parser<'a> {
125134 RecoverReturnSign :: Yes ,
126135 Some ( ty_params) ,
127136 RecoverQuestionMark :: Yes ,
137+ RecoverAnonEnum :: No ,
128138 )
129139 }
130140
@@ -139,6 +149,7 @@ impl<'a> Parser<'a> {
139149 RecoverReturnSign :: Yes ,
140150 None ,
141151 RecoverQuestionMark :: Yes ,
152+ RecoverAnonEnum :: Yes ,
142153 )
143154 }
144155
@@ -156,6 +167,7 @@ impl<'a> Parser<'a> {
156167 RecoverReturnSign :: Yes ,
157168 None ,
158169 RecoverQuestionMark :: Yes ,
170+ RecoverAnonEnum :: No ,
159171 )
160172 }
161173
@@ -169,6 +181,7 @@ impl<'a> Parser<'a> {
169181 RecoverReturnSign :: Yes ,
170182 None ,
171183 RecoverQuestionMark :: No ,
184+ RecoverAnonEnum :: No ,
172185 )
173186 }
174187
@@ -180,6 +193,7 @@ impl<'a> Parser<'a> {
180193 RecoverReturnSign :: Yes ,
181194 None ,
182195 RecoverQuestionMark :: No ,
196+ RecoverAnonEnum :: No ,
183197 )
184198 }
185199
@@ -192,6 +206,7 @@ impl<'a> Parser<'a> {
192206 RecoverReturnSign :: OnlyFatArrow ,
193207 None ,
194208 RecoverQuestionMark :: Yes ,
209+ RecoverAnonEnum :: No ,
195210 )
196211 }
197212
@@ -211,6 +226,7 @@ impl<'a> Parser<'a> {
211226 recover_return_sign,
212227 None ,
213228 RecoverQuestionMark :: Yes ,
229+ RecoverAnonEnum :: Yes ,
214230 ) ?;
215231 FnRetTy :: Ty ( ty)
216232 } else if recover_return_sign. can_recover ( & self . token . kind ) {
@@ -232,6 +248,7 @@ impl<'a> Parser<'a> {
232248 recover_return_sign,
233249 None ,
234250 RecoverQuestionMark :: Yes ,
251+ RecoverAnonEnum :: Yes ,
235252 ) ?;
236253 FnRetTy :: Ty ( ty)
237254 } else {
@@ -247,6 +264,7 @@ impl<'a> Parser<'a> {
247264 recover_return_sign : RecoverReturnSign ,
248265 ty_generics : Option < & Generics > ,
249266 recover_question_mark : RecoverQuestionMark ,
267+ recover_anon_enum : RecoverAnonEnum ,
250268 ) -> PResult < ' a , P < Ty > > {
251269 let allow_qpath_recovery = recover_qpath == RecoverQPath :: Yes ;
252270 maybe_recover_from_interpolated_ty_qpath ! ( self , allow_qpath_recovery) ;
@@ -325,14 +343,55 @@ impl<'a> Parser<'a> {
325343 let mut ty = self . mk_ty ( span, kind) ;
326344
327345 // Try to recover from use of `+` with incorrect priority.
328- if matches ! ( allow_plus, AllowPlus :: Yes ) {
346+ if allow_plus == AllowPlus :: Yes {
329347 self . maybe_recover_from_bad_type_plus ( & ty) ?;
330348 } else {
331349 self . maybe_report_ambiguous_plus ( impl_dyn_multi, & ty) ;
332350 }
333- if let RecoverQuestionMark :: Yes = recover_question_mark {
351+ if RecoverQuestionMark :: Yes = = recover_question_mark {
334352 ty = self . maybe_recover_from_question_mark ( ty) ;
335353 }
354+ if recover_anon_enum == RecoverAnonEnum :: Yes
355+ && self . check_noexpect ( & token:: BinOp ( token:: Or ) )
356+ && self . look_ahead ( 1 , |t| t. can_begin_type ( ) )
357+ {
358+ let mut pipes = vec ! [ self . token. span] ;
359+ let mut types = vec ! [ ty] ;
360+ loop {
361+ if !self . eat ( & token:: BinOp ( token:: Or ) ) {
362+ break ;
363+ }
364+ pipes. push ( self . prev_token . span ) ;
365+ types. push ( self . parse_ty_common (
366+ allow_plus,
367+ allow_c_variadic,
368+ recover_qpath,
369+ recover_return_sign,
370+ ty_generics,
371+ recover_question_mark,
372+ RecoverAnonEnum :: No ,
373+ ) ?) ;
374+ }
375+ let mut err = self . struct_span_err ( pipes, "anonymous enums are not supported" ) ;
376+ for ty in & types {
377+ err. span_label ( ty. span , "" ) ;
378+ }
379+ err. help ( & format ! (
380+ "create a named `enum` and use it here instead:\n enum Name {{\n {}\n }}" ,
381+ types
382+ . iter( )
383+ . enumerate( )
384+ . map( |( i, t) | format!(
385+ " Variant{}({})," ,
386+ i + 1 , // Lets not confuse people with zero-indexing :)
387+ pprust:: to_string( |s| s. print_type( & t) ) ,
388+ ) )
389+ . collect:: <Vec <_>>( )
390+ . join( "\n " ) ,
391+ ) ) ;
392+ err. emit ( ) ;
393+ return Ok ( self . mk_ty ( lo. to ( self . prev_token . span ) , TyKind :: Err ) ) ;
394+ }
336395 if allow_qpath_recovery { self . maybe_recover_from_bad_qpath ( ty) } else { Ok ( ty) }
337396 }
338397
0 commit comments