@@ -880,6 +880,97 @@ impl<'a> Parser<'a> {
880
880
}
881
881
}
882
882
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
+
883
974
/// Eats and discards tokens until one of `kets` is encountered. Respects token trees,
884
975
/// passes through any errors encountered. Used for error recovery.
885
976
pub ( super ) fn eat_to_tokens ( & mut self , kets : & [ & TokenKind ] ) {
0 commit comments