@@ -880,6 +880,97 @@ impl<'a> Parser<'a> {
880880 }
881881 }
882882
883+ pub ( super ) fn check_anonymous_enum ( & mut self , span : Span , tys : & [ P < Ty > ] ) -> PResult < ' a , ( ) > {
884+ use std:: fmt:: Write ;
885+ if tys. len ( ) <= 1 {
886+ return Ok ( ( ) ) ;
887+ }
888+
889+ fn variant_name_and_ty < ' a > (
890+ ty : & ' a Ty ,
891+ lifetimes : & mut FxHashSet < & ' a str > ,
892+ ) -> Option < ( String , String ) > {
893+ match & ty. kind {
894+ TyKind :: Path ( _, path) => {
895+ let mut name = String :: new ( ) ;
896+ let mut ty_string = String :: new ( ) ;
897+
898+ if let Some ( seg) = path. segments . iter ( ) . last ( ) {
899+ name. push_str ( seg. ident . name . as_str ( ) ) ;
900+ ty_string. push_str ( seg. ident . name . as_str ( ) ) ;
901+
902+ if let Some ( _args) = & seg. args {
903+ ty_string. push ( '<' ) ;
904+ ty_string. push_str ( "..." ) ;
905+ ty_string. push ( '>' ) ;
906+ }
907+ }
908+
909+ Some ( ( name, ty_string) )
910+ }
911+ TyKind :: Rptr ( lifetime, ty) => {
912+ if let Some ( ( mut name, ty) ) = variant_name_and_ty ( & ty. ty , lifetimes) {
913+ name. push_str ( "Ref" ) ;
914+ let lifetime =
915+ lifetime. as_ref ( ) . map ( |l| l. ident . name . as_str ( ) ) . unwrap_or ( "'lifetime" ) ;
916+ lifetimes. insert ( lifetime) ;
917+ Some ( ( name, format ! ( "&{} {}" , lifetime, ty) ) )
918+ } else {
919+ None
920+ }
921+ }
922+ _ => None ,
923+ }
924+ }
925+
926+ let mut err = self . struct_span_err ( span, "anonymous enums are not supported" ) ;
927+ let mut variant_content = String :: new ( ) ;
928+ let mut variant_name_set = FxHashSet :: default ( ) ;
929+ let mut lifetimes = FxHashSet :: default ( ) ;
930+ tys. iter ( ) . for_each ( |ty| {
931+ let name_ty = variant_name_and_ty ( ty, & mut lifetimes) ;
932+ if let Some ( ( variant_name, ty) ) = name_ty {
933+ let variant_name = crate :: utils:: to_camel_case ( & variant_name) ;
934+ if !variant_name_set. contains ( & variant_name) {
935+ let _ = writeln ! (
936+ & mut variant_content,
937+ " {variant_name}({ty})" ,
938+ variant_name = variant_name,
939+ ty = ty
940+ ) ;
941+ variant_name_set. insert ( variant_name) ;
942+ }
943+ }
944+ } ) ;
945+
946+ let mut suggestion_code = String :: new ( ) ;
947+ suggestion_code. push_str ( "enum SomeEnum" ) ;
948+ if lifetimes. len ( ) > 0 {
949+ suggestion_code. push_str ( "<" ) ;
950+ #[ allow( rustc:: potential_query_instability) ]
951+ let mut iter = lifetimes. into_iter ( ) ;
952+ if let Some ( lifetime) = iter. next ( ) {
953+ suggestion_code. push_str ( lifetime) ;
954+ while let Some ( lifetime) = iter. next ( ) {
955+ suggestion_code. push_str ( "," ) ;
956+ suggestion_code. push_str ( lifetime) ;
957+ }
958+ }
959+ suggestion_code. push_str ( ">" ) ;
960+ }
961+ suggestion_code. push_str ( "{\n " ) ;
962+ suggestion_code. push_str ( & variant_content) ;
963+ suggestion_code. push_str ( "}\n " ) ;
964+ err. span_suggestion (
965+ span,
966+ "consider using enum as return type" ,
967+ "SomeEnum" ,
968+ Applicability :: HasPlaceholders ,
969+ )
970+ . note ( suggestion_code) ;
971+ Err ( err)
972+ }
973+
883974 /// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
884975 /// passes through any errors encountered. Used for error recovery.
885976 pub ( super ) fn eat_to_tokens ( & mut self , kets : & [ & TokenKind ] ) {
0 commit comments