@@ -789,64 +789,100 @@ fn convert_enum_variant_types(tcx: TyCtxt<'_>, def_id: DefId) {
789
789
}
790
790
}
791
791
792
- /*
793
- /// In a type definition, we check that unnamed field names are distinct.
794
- fn check_unnamed_fields_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>) {
795
- let mut seen_fields: FxHashMap<Ident, Option<Span>> = Default::default();
796
- fn check_fields_anon_adt_defn<'tcx>(tcx: TyCtxt<'tcx>, item: &hir::Item<'tcx>, seen_fields: &mut FxHashMap<Ident, Option<Span>>) {
797
- let fields = match &item.kind {
798
- hir::ItemKind::Struct(fields, _) | hir::ItemKind::Union(fields, _) => fields,
799
- _ => return,
800
- };
801
- for field in fields.fields() {
802
- if field.ident.name == kw::Underscore {
803
- if let hir::TyKind::AnonAdt(item_id) = field.ty.kind() {
804
- let item = tcx.hir().item(item_id);
805
- check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
806
- } else {
807
- let field_ty = match tcx.type_of(field.def_id).instantiate_identity().ty_adt_def() {
808
- Some(adt_ty) => adt_ty,
809
- None => {
810
- tcx.sess.emit_err(err);
811
- return;
812
- }
813
- };
814
- if let Some(def_id) = field_ty.did().as_local() {
815
- let item = tcx.hir().item(hir::ItemId { owner_id: hir::OwnerId { def_id }});
816
- check_fields_anon_adt_defn(tcx, item, &mut *seen_fields);
817
- }
792
+ #[ derive( Clone , Copy ) ]
793
+ struct NestedSpan {
794
+ span : Span ,
795
+ nested_field_span : Span ,
796
+ }
797
+
798
+ #[ derive( Clone , Copy ) ]
799
+ enum FieldDeclSpan {
800
+ NotNested ( Span ) ,
801
+ Nested ( NestedSpan ) ,
802
+ }
803
+
804
+ impl From < Span > for FieldDeclSpan {
805
+ fn from ( span : Span ) -> Self {
806
+ Self :: NotNested ( span)
807
+ }
808
+ }
809
+
810
+ impl From < NestedSpan > for FieldDeclSpan {
811
+ fn from ( span : NestedSpan ) -> Self {
812
+ Self :: Nested ( span)
813
+ }
814
+ }
815
+
816
+ /// Check the uniqueness of fields across adt where there are
817
+ /// nested fields imported from an unnamed field.
818
+ fn check_field_uniqueness_in_nested_adt (
819
+ tcx : TyCtxt < ' _ > ,
820
+ adt_def : ty:: AdtDef < ' _ > ,
821
+ check : & mut impl FnMut ( Ident , /* nested_field_span */ Span ) ,
822
+ ) {
823
+ for field in adt_def. all_fields ( ) {
824
+ if field. is_unnamed ( ) {
825
+ // Here we don't care about the generic parameters, so `instantiate_identity` is enough.
826
+ match tcx. type_of ( field. did ) . instantiate_identity ( ) . kind ( ) {
827
+ ty:: Adt ( adt_def, _) => {
828
+ check_field_uniqueness_in_nested_adt ( tcx, * adt_def, & mut * check) ;
818
829
}
819
- field_ty.flags()
820
- let inner_adt_def = field_ty.ty_adt_def().expect("expect an adt");
821
- check_fields_anon_adt_defn(tcx, adt_def, &mut *seen_fields);
822
- } else {
823
- let span = field.did.as_local().map(|did| {
824
- let hir_id = tcx.hir().local_def_id_to_hir_id(did);
825
- tcx.hir().span(hir_id)
826
- });
827
- match seen_fields.get(&ident.normalize_to_macros_2_0()).cloned() {
828
- Some(Some(prev_span)) => {
829
- tcx.sess.emit_err(errors::FieldAlreadyDeclared {
830
- field_name: ident,
831
- span: f.span,
832
- prev_span,
833
- });
834
- }
835
- Some(None) => {
836
- tcx.sess.emit_err(errors::FieldAlreadyDeclared {
837
- field_name: f.ident,
838
- span: f.span,
839
- prev_span,
840
- });
830
+ ty_kind => bug ! (
831
+ "Unexpected ty kind in check_field_uniqueness_in_nested_adt(): {ty_kind:?}"
832
+ ) ,
833
+ }
834
+ } else {
835
+ check ( field. ident ( tcx) , tcx. def_span ( field. did ) ) ;
836
+ }
837
+ }
838
+ }
839
+
840
+ /// Check the uniqueness of fields in a struct variant, and recursively
841
+ /// check the nested fields if it is an unnamed field with type of an
842
+ /// annoymous adt.
843
+ fn check_field_uniqueness (
844
+ tcx : TyCtxt < ' _ > ,
845
+ field : & hir:: FieldDef < ' _ > ,
846
+ check : & mut impl FnMut ( Ident , FieldDeclSpan ) ,
847
+ ) {
848
+ if field. ident . name == kw:: Underscore {
849
+ let ty_span = field. ty . span ;
850
+ match & field. ty . kind {
851
+ hir:: TyKind :: AnonAdt ( item_id) => {
852
+ match & tcx. hir_node ( item_id. hir_id ( ) ) . expect_item ( ) . kind {
853
+ hir:: ItemKind :: Struct ( variant_data, ..)
854
+ | hir:: ItemKind :: Union ( variant_data, ..) => {
855
+ variant_data
856
+ . fields ( )
857
+ . iter ( )
858
+ . for_each ( |f| check_field_uniqueness ( tcx, f, & mut * check) ) ;
841
859
}
842
- None =>
843
- seen_fields.insert(f.ident.normalize_to_macros_2_0(), f.span);
860
+ item_kind => span_bug ! (
861
+ ty_span,
862
+ "Unexpected item kind in check_field_uniqueness(): {item_kind:?}"
863
+ ) ,
844
864
}
845
865
}
866
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( _, hir:: Path { res, .. } ) ) => {
867
+ check_field_uniqueness_in_nested_adt (
868
+ tcx,
869
+ tcx. adt_def ( res. def_id ( ) ) ,
870
+ & mut |ident, nested_field_span| {
871
+ check ( ident, NestedSpan { span : field. span , nested_field_span } . into ( ) )
872
+ } ,
873
+ ) ;
874
+ }
875
+ // Abort due to errors (there must be an error if an unnamed field
876
+ // has any type kind other than an anonymous adt or a named adt)
877
+ _ => {
878
+ debug_assert ! ( tcx. sess. has_errors( ) . is_some( ) ) ;
879
+ tcx. sess . abort_if_errors ( )
880
+ }
846
881
}
882
+ return ;
847
883
}
884
+ check ( field. ident , field. span . into ( ) ) ;
848
885
}
849
- */
850
886
851
887
fn convert_variant (
852
888
tcx : TyCtxt < ' _ > ,
@@ -856,27 +892,61 @@ fn convert_variant(
856
892
def : & hir:: VariantData < ' _ > ,
857
893
adt_kind : ty:: AdtKind ,
858
894
parent_did : LocalDefId ,
895
+ is_anonymous : bool ,
859
896
) -> ty:: VariantDef {
860
897
let mut has_unnamed_fields = false ;
861
- let mut seen_fields: FxHashMap < Ident , Span > = Default :: default ( ) ;
898
+ let mut seen_fields: FxHashMap < Ident , FieldDeclSpan > = Default :: default ( ) ;
862
899
let fields = def
863
900
. fields ( )
864
901
. iter ( )
865
902
. inspect ( |f| {
866
- // Skip the unnamed field here, we will check it later.
867
- if f. ident . name == kw:: Underscore {
868
- has_unnamed_fields = true ;
869
- return ;
870
- }
871
- let dup_span = seen_fields. get ( & f. ident . normalize_to_macros_2_0 ( ) ) . cloned ( ) ;
872
- if let Some ( prev_span) = dup_span {
873
- tcx. dcx ( ) . emit_err ( errors:: FieldAlreadyDeclared {
874
- field_name : f. ident ,
875
- span : f. span ,
876
- prev_span,
903
+ has_unnamed_fields |= f. ident . name == kw:: Underscore ;
904
+ if !is_anonymous {
905
+ check_field_uniqueness ( tcx, f, & mut |ident, field_decl| {
906
+ use FieldDeclSpan :: * ;
907
+ let field_name = ident. name ;
908
+ let ident = ident. normalize_to_macros_2_0 ( ) ;
909
+ match ( field_decl, seen_fields. get ( & ident) . copied ( ) ) {
910
+ ( NotNested ( span) , Some ( NotNested ( prev_span) ) ) => {
911
+ tcx. sess . emit_err ( errors:: FieldAlreadyDeclared :: NotNested {
912
+ field_name,
913
+ span,
914
+ prev_span,
915
+ } ) ;
916
+ }
917
+ ( NotNested ( span) , Some ( Nested ( prev) ) ) => {
918
+ tcx. sess . emit_err ( errors:: FieldAlreadyDeclared :: PreviousNested {
919
+ field_name,
920
+ span,
921
+ prev_span : prev. span ,
922
+ prev_nested_field_span : prev. nested_field_span ,
923
+ } ) ;
924
+ }
925
+ (
926
+ Nested ( NestedSpan { span, nested_field_span } ) ,
927
+ Some ( NotNested ( prev_span) ) ,
928
+ ) => {
929
+ tcx. sess . emit_err ( errors:: FieldAlreadyDeclared :: CurrentNested {
930
+ field_name,
931
+ span,
932
+ nested_field_span,
933
+ prev_span,
934
+ } ) ;
935
+ }
936
+ ( Nested ( NestedSpan { span, nested_field_span } ) , Some ( Nested ( prev) ) ) => {
937
+ tcx. sess . emit_err ( errors:: FieldAlreadyDeclared :: BothNested {
938
+ field_name,
939
+ span,
940
+ nested_field_span,
941
+ prev_span : prev. span ,
942
+ prev_nested_field_span : prev. nested_field_span ,
943
+ } ) ;
944
+ }
945
+ ( field_decl, None ) => {
946
+ seen_fields. insert ( ident, field_decl) ;
947
+ }
948
+ }
877
949
} ) ;
878
- } else {
879
- seen_fields. insert ( f. ident . normalize_to_macros_2_0 ( ) , f. span ) ;
880
950
}
881
951
} )
882
952
. map ( |f| ty:: FieldDef {
@@ -937,6 +1007,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
937
1007
& v. data ,
938
1008
AdtKind :: Enum ,
939
1009
def_id,
1010
+ is_anonymous,
940
1011
)
941
1012
} )
942
1013
. collect ( ) ;
@@ -956,6 +1027,7 @@ fn adt_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AdtDef<'_> {
956
1027
def,
957
1028
adt_kind,
958
1029
def_id,
1030
+ is_anonymous,
959
1031
) )
960
1032
. collect ( ) ;
961
1033
0 commit comments