@@ -791,12 +791,30 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
791
791
}
792
792
}
793
793
794
+ fn find_field ( tcx : TyCtxt < ' _ > , ( def_id, ident) : ( DefId , Ident ) ) -> Option < FieldIdx > {
795
+ tcx. adt_def ( def_id) . non_enum_variant ( ) . fields . iter_enumerated ( ) . find_map ( |( idx, field) | {
796
+ if field. is_unnamed ( ) {
797
+ let field_ty = tcx. type_of ( field. did ) . instantiate_identity ( ) ;
798
+ let adt_def = field_ty. ty_adt_def ( ) . expect ( "expect Adt for unnamed field" ) ;
799
+ tcx. find_field ( ( adt_def. did ( ) , ident) ) . map ( |_| idx)
800
+ } else {
801
+ ( field. ident ( tcx) . normalize_to_macros_2_0 ( ) == ident) . then_some ( idx)
802
+ }
803
+ } )
804
+ }
805
+
794
806
#[ derive( Clone , Copy ) ]
795
807
struct NestedSpan {
796
808
span : Span ,
797
809
nested_field_span : Span ,
798
810
}
799
811
812
+ impl NestedSpan {
813
+ fn to_field_already_declared_nested_help ( & self ) -> errors:: FieldAlreadyDeclaredNestedHelp {
814
+ errors:: FieldAlreadyDeclaredNestedHelp { span : self . span }
815
+ }
816
+ }
817
+
800
818
#[ derive( Clone , Copy ) ]
801
819
enum FieldDeclSpan {
802
820
NotNested ( Span ) ,
@@ -815,87 +833,131 @@ impl From<NestedSpan> for FieldDeclSpan {
815
833
}
816
834
}
817
835
818
- /// Check the uniqueness of fields across adt where there are
819
- /// nested fields imported from an unnamed field.
820
- fn check_field_uniqueness_in_nested_adt (
821
- tcx : TyCtxt < ' _ > ,
822
- adt_def : ty:: AdtDef < ' _ > ,
823
- check : & mut impl FnMut ( Ident , /* nested_field_span */ Span ) ,
824
- ) {
825
- for field in adt_def. all_fields ( ) {
826
- if field. is_unnamed ( ) {
827
- // Here we don't care about the generic parameters, so `instantiate_identity` is enough.
828
- match tcx. type_of ( field. did ) . instantiate_identity ( ) . kind ( ) {
829
- ty:: Adt ( adt_def, _) => {
830
- check_field_uniqueness_in_nested_adt ( tcx, * adt_def, & mut * check) ;
836
+ struct FieldUniquenessCheckContext < ' tcx > {
837
+ tcx : TyCtxt < ' tcx > ,
838
+ seen_fields : FxHashMap < Ident , FieldDeclSpan > ,
839
+ }
840
+
841
+ impl < ' tcx > FieldUniquenessCheckContext < ' tcx > {
842
+ fn new ( tcx : TyCtxt < ' tcx > ) -> Self {
843
+ Self { tcx, seen_fields : FxHashMap :: default ( ) }
844
+ }
845
+
846
+ /// Check if a given field `ident` declared at `field_decl` has been declared elsewhere before.
847
+ fn check_field_decl ( & mut self , ident : Ident , field_decl : FieldDeclSpan ) {
848
+ use FieldDeclSpan :: * ;
849
+ let field_name = ident. name ;
850
+ let ident = ident. normalize_to_macros_2_0 ( ) ;
851
+ match ( field_decl, self . seen_fields . get ( & ident) . copied ( ) ) {
852
+ ( NotNested ( span) , Some ( NotNested ( prev_span) ) ) => {
853
+ self . tcx . dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: NotNested {
854
+ field_name,
855
+ span,
856
+ prev_span,
857
+ } ) ;
858
+ }
859
+ ( NotNested ( span) , Some ( Nested ( prev) ) ) => {
860
+ self . tcx . dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: PreviousNested {
861
+ field_name,
862
+ span,
863
+ prev_span : prev. span ,
864
+ prev_nested_field_span : prev. nested_field_span ,
865
+ prev_help : prev. to_field_already_declared_nested_help ( ) ,
866
+ } ) ;
867
+ }
868
+ (
869
+ Nested ( current @ NestedSpan { span, nested_field_span, .. } ) ,
870
+ Some ( NotNested ( prev_span) ) ,
871
+ ) => {
872
+ self . tcx . dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: CurrentNested {
873
+ field_name,
874
+ span,
875
+ nested_field_span,
876
+ help : current. to_field_already_declared_nested_help ( ) ,
877
+ prev_span,
878
+ } ) ;
879
+ }
880
+ ( Nested ( current @ NestedSpan { span, nested_field_span } ) , Some ( Nested ( prev) ) ) => {
881
+ self . tcx . dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: BothNested {
882
+ field_name,
883
+ span,
884
+ nested_field_span,
885
+ help : current. to_field_already_declared_nested_help ( ) ,
886
+ prev_span : prev. span ,
887
+ prev_nested_field_span : prev. nested_field_span ,
888
+ prev_help : prev. to_field_already_declared_nested_help ( ) ,
889
+ } ) ;
890
+ }
891
+ ( field_decl, None ) => {
892
+ self . seen_fields . insert ( ident, field_decl) ;
893
+ }
894
+ }
895
+ }
896
+
897
+ /// Check the uniqueness of fields across adt where there are
898
+ /// nested fields imported from an unnamed field.
899
+ fn check_field_in_nested_adt ( & mut self , adt_def : ty:: AdtDef < ' _ > , unnamed_field_span : Span ) {
900
+ for field in adt_def. all_fields ( ) {
901
+ if field. is_unnamed ( ) {
902
+ // Here we don't care about the generic parameters, so `instantiate_identity` is enough.
903
+ match self . tcx . type_of ( field. did ) . instantiate_identity ( ) . kind ( ) {
904
+ ty:: Adt ( adt_def, _) => {
905
+ self . check_field_in_nested_adt ( * adt_def, unnamed_field_span) ;
906
+ }
907
+ ty_kind => span_bug ! (
908
+ self . tcx. def_span( field. did) ,
909
+ "Unexpected TyKind in FieldUniquenessCheckContext::check_field_in_nested_adt(): {ty_kind:?}"
910
+ ) ,
831
911
}
832
- ty_kind => bug ! (
833
- "Unexpected ty kind in check_field_uniqueness_in_nested_adt(): {ty_kind:?}"
834
- ) ,
912
+ } else {
913
+ self . check_field_decl (
914
+ field. ident ( self . tcx ) ,
915
+ NestedSpan {
916
+ span : unnamed_field_span,
917
+ nested_field_span : self . tcx . def_span ( field. did ) ,
918
+ }
919
+ . into ( ) ,
920
+ ) ;
835
921
}
836
- } else {
837
- check ( field. ident ( tcx) , tcx. def_span ( field. did ) ) ;
838
922
}
839
923
}
840
- }
841
924
842
- /// Check the uniqueness of fields in a struct variant, and recursively
843
- /// check the nested fields if it is an unnamed field with type of an
844
- /// annoymous adt.
845
- fn check_field_uniqueness (
846
- tcx : TyCtxt < ' _ > ,
847
- field : & hir:: FieldDef < ' _ > ,
848
- check : & mut impl FnMut ( Ident , FieldDeclSpan ) ,
849
- ) {
850
- if field. ident . name == kw:: Underscore {
851
- let ty_span = field. ty . span ;
925
+ /// Check the uniqueness of fields in a struct variant, and recursively
926
+ /// check the nested fields if it is an unnamed field with type of an
927
+ /// annoymous adt.
928
+ fn check_field ( & mut self , field : & hir:: FieldDef < ' _ > ) {
929
+ if field. ident . name != kw:: Underscore {
930
+ self . check_field_decl ( field. ident , field. span . into ( ) ) ;
931
+ return ;
932
+ }
852
933
match & field. ty . kind {
853
934
hir:: TyKind :: AnonAdt ( item_id) => {
854
- match & tcx. hir_node ( item_id. hir_id ( ) ) . expect_item ( ) . kind {
935
+ match & self . tcx . hir_node ( item_id. hir_id ( ) ) . expect_item ( ) . kind {
855
936
hir:: ItemKind :: Struct ( variant_data, ..)
856
937
| hir:: ItemKind :: Union ( variant_data, ..) => {
857
- variant_data
858
- . fields ( )
859
- . iter ( )
860
- . for_each ( |f| check_field_uniqueness ( tcx, f, & mut * check) ) ;
938
+ variant_data. fields ( ) . iter ( ) . for_each ( |f| self . check_field ( f) ) ;
861
939
}
862
940
item_kind => span_bug ! (
863
- ty_span ,
864
- "Unexpected item kind in check_field_uniqueness (): {item_kind:?}"
941
+ field . ty . span ,
942
+ "Unexpected ItemKind in FieldUniquenessCheckContext::check_field (): {item_kind:?}"
865
943
) ,
866
944
}
867
945
}
868
946
hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, hir:: Path { res, .. } ) ) => {
869
- check_field_uniqueness_in_nested_adt (
870
- tcx,
871
- tcx. adt_def ( res. def_id ( ) ) ,
872
- & mut |ident, nested_field_span| {
873
- check ( ident, NestedSpan { span : field. span , nested_field_span } . into ( ) )
874
- } ,
875
- ) ;
947
+ self . check_field_in_nested_adt ( self . tcx . adt_def ( res. def_id ( ) ) , field. span ) ;
876
948
}
877
949
// Abort due to errors (there must be an error if an unnamed field
878
950
// has any type kind other than an anonymous adt or a named adt)
879
- _ => {
880
- debug_assert ! ( tcx. dcx( ) . has_errors( ) . is_some( ) ) ;
881
- tcx. dcx ( ) . abort_if_errors ( )
951
+ ty_kind => {
952
+ self . tcx . dcx ( ) . span_delayed_bug (
953
+ field. ty . span ,
954
+ format ! ( "Unexpected TyKind in FieldUniquenessCheckContext::check_field(): {ty_kind:?}" ) ,
955
+ ) ;
956
+ // FIXME: errors during AST validation should abort the compilation before reaching here.
957
+ self . tcx . dcx ( ) . abort_if_errors ( ) ;
882
958
}
883
959
}
884
- return ;
885
960
}
886
- check ( field. ident , field. span . into ( ) ) ;
887
- }
888
-
889
- fn find_field ( tcx : TyCtxt < ' _ > , ( def_id, ident) : ( DefId , Ident ) ) -> Option < FieldIdx > {
890
- tcx. adt_def ( def_id) . non_enum_variant ( ) . fields . iter_enumerated ( ) . find_map ( |( idx, field) | {
891
- if field. is_unnamed ( ) {
892
- let field_ty = tcx. type_of ( field. did ) . instantiate_identity ( ) ;
893
- let adt_def = field_ty. ty_adt_def ( ) . expect ( "expect Adt for unnamed field" ) ;
894
- tcx. find_field ( ( adt_def. did ( ) , ident) ) . map ( |_| idx)
895
- } else {
896
- ( field. ident ( tcx) . normalize_to_macros_2_0 ( ) == ident) . then_some ( idx)
897
- }
898
- } )
899
961
}
900
962
901
963
fn convert_variant (
@@ -909,58 +971,16 @@ fn convert_variant(
909
971
is_anonymous : bool ,
910
972
) -> ty:: VariantDef {
911
973
let mut has_unnamed_fields = false ;
912
- let mut seen_fields : FxHashMap < Ident , FieldDeclSpan > = Default :: default ( ) ;
974
+ let mut field_uniqueness_check_ctx = FieldUniquenessCheckContext :: new ( tcx ) ;
913
975
let fields = def
914
976
. fields ( )
915
977
. iter ( )
916
978
. inspect ( |f| {
917
979
has_unnamed_fields |= f. ident . name == kw:: Underscore ;
980
+ // We only check named ADT here because anonymous ADTs are checked inside
981
+ // the nammed ADT in which they are defined.
918
982
if !is_anonymous {
919
- check_field_uniqueness ( tcx, f, & mut |ident, field_decl| {
920
- use FieldDeclSpan :: * ;
921
- let field_name = ident. name ;
922
- let ident = ident. normalize_to_macros_2_0 ( ) ;
923
- match ( field_decl, seen_fields. get ( & ident) . copied ( ) ) {
924
- ( NotNested ( span) , Some ( NotNested ( prev_span) ) ) => {
925
- tcx. dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: NotNested {
926
- field_name,
927
- span,
928
- prev_span,
929
- } ) ;
930
- }
931
- ( NotNested ( span) , Some ( Nested ( prev) ) ) => {
932
- tcx. dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: PreviousNested {
933
- field_name,
934
- span,
935
- prev_span : prev. span ,
936
- prev_nested_field_span : prev. nested_field_span ,
937
- } ) ;
938
- }
939
- (
940
- Nested ( NestedSpan { span, nested_field_span } ) ,
941
- Some ( NotNested ( prev_span) ) ,
942
- ) => {
943
- tcx. dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: CurrentNested {
944
- field_name,
945
- span,
946
- nested_field_span,
947
- prev_span,
948
- } ) ;
949
- }
950
- ( Nested ( NestedSpan { span, nested_field_span } ) , Some ( Nested ( prev) ) ) => {
951
- tcx. dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared :: BothNested {
952
- field_name,
953
- span,
954
- nested_field_span,
955
- prev_span : prev. span ,
956
- prev_nested_field_span : prev. nested_field_span ,
957
- } ) ;
958
- }
959
- ( field_decl, None ) => {
960
- seen_fields. insert ( ident, field_decl) ;
961
- }
962
- }
963
- } ) ;
983
+ field_uniqueness_check_ctx. check_field ( f) ;
964
984
}
965
985
} )
966
986
. map ( |f| ty:: FieldDef {
0 commit comments