@@ -846,128 +846,82 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
846
846
// Locate trait methods
847
847
let tcx = ccx. tcx ;
848
848
let trait_items = tcx. trait_items ( impl_trait_ref. def_id ) ;
849
+ let mut overridden_associated_type = None ;
849
850
850
851
// Check existing impl methods to see if they are both present in trait
851
852
// and compatible with trait signature
852
853
for impl_item in impl_items {
854
+ let ty_impl_item = ccx. tcx . impl_or_trait_item ( local_def ( impl_item. id ) ) ;
855
+ let ty_trait_item = trait_items. iter ( )
856
+ . find ( |ac| ac. name ( ) == ty_impl_item. name ( ) )
857
+ . unwrap_or_else ( || {
858
+ // This is checked by resolve
859
+ tcx. sess . span_bug ( impl_item. span ,
860
+ & format ! ( "impl-item `{}` is not a member of `{:?}`" ,
861
+ token:: get_name( ty_impl_item. name( ) ) ,
862
+ impl_trait_ref) ) ;
863
+ } ) ;
853
864
match impl_item. node {
854
865
ast:: ConstImplItem ( ..) => {
855
- let impl_const_def_id = local_def ( impl_item. id ) ;
856
- let impl_const_ty = ccx. tcx . impl_or_trait_item ( impl_const_def_id) ;
866
+ let impl_const = match ty_impl_item {
867
+ ty:: ConstTraitItem ( ref cti) => cti,
868
+ _ => tcx. sess . span_bug ( impl_item. span , "non-const impl-item for const" )
869
+ } ;
857
870
858
871
// Find associated const definition.
859
- let opt_associated_const =
860
- trait_items. iter ( )
861
- . find ( |ac| ac. name ( ) == impl_const_ty. name ( ) ) ;
862
- match opt_associated_const {
863
- Some ( associated_const) => {
864
- match ( associated_const, & impl_const_ty) {
865
- ( & ty:: ConstTraitItem ( ref const_trait) ,
866
- & ty:: ConstTraitItem ( ref const_impl) ) => {
867
- compare_const_impl ( ccx. tcx ,
868
- & const_impl,
869
- impl_item. span ,
870
- & const_trait,
871
- & * impl_trait_ref) ;
872
- }
873
- _ => {
874
- span_err ! ( tcx. sess, impl_item. span, E0323 ,
875
- "item `{}` is an associated const, \
876
- which doesn't match its trait `{:?}`",
877
- token:: get_name( impl_const_ty. name( ) ) ,
878
- impl_trait_ref)
879
- }
880
- }
881
- }
882
- None => {
883
- // This is `span_bug` as it should have already been
884
- // caught in resolve.
885
- tcx. sess . span_bug (
886
- impl_item. span ,
887
- & format ! (
888
- "associated const `{}` is not a member of \
889
- trait `{:?}`",
890
- token:: get_name( impl_const_ty. name( ) ) ,
891
- impl_trait_ref) ) ;
892
- }
872
+ if let & ty:: ConstTraitItem ( ref trait_const) = ty_trait_item {
873
+ compare_const_impl ( ccx. tcx ,
874
+ & impl_const,
875
+ impl_item. span ,
876
+ trait_const,
877
+ & * impl_trait_ref) ;
878
+ } else {
879
+ span_err ! ( tcx. sess, impl_item. span, E0323 ,
880
+ "item `{}` is an associated const, \
881
+ which doesn't match its trait `{:?}`",
882
+ token:: get_name( impl_const. name) ,
883
+ impl_trait_ref)
893
884
}
894
885
}
895
886
ast:: MethodImplItem ( ref sig, ref body) => {
896
887
check_trait_fn_not_const ( ccx, impl_item. span , sig. constness ) ;
897
888
898
- let impl_method_def_id = local_def ( impl_item. id ) ;
899
- let impl_item_ty = ccx. tcx . impl_or_trait_item ( impl_method_def_id) ;
900
-
901
- // If this is an impl of a trait method, find the
902
- // corresponding method definition in the trait.
903
- let opt_trait_method_ty =
904
- trait_items. iter ( )
905
- . find ( |ti| ti. name ( ) == impl_item_ty. name ( ) ) ;
906
- match opt_trait_method_ty {
907
- Some ( trait_method_ty) => {
908
- match ( trait_method_ty, & impl_item_ty) {
909
- ( & ty:: MethodTraitItem ( ref trait_method_ty) ,
910
- & ty:: MethodTraitItem ( ref impl_method_ty) ) => {
911
- compare_impl_method ( ccx. tcx ,
912
- & * * impl_method_ty,
913
- impl_item. span ,
914
- body. id ,
915
- & * * trait_method_ty,
916
- & * impl_trait_ref) ;
917
- }
918
- _ => {
919
- span_err ! ( tcx. sess, impl_item. span, E0324 ,
920
- "item `{}` is an associated method, \
921
- which doesn't match its trait `{:?}`",
922
- token:: get_name( impl_item_ty. name( ) ) ,
923
- impl_trait_ref)
924
- }
925
- }
926
- }
927
- None => {
928
- // This is span_bug as it should have already been
929
- // caught in resolve.
930
- tcx. sess . span_bug (
931
- impl_item. span ,
932
- & format ! ( "method `{}` is not a member of trait `{:?}`" ,
933
- token:: get_name( impl_item_ty. name( ) ) ,
934
- impl_trait_ref) ) ;
935
- }
889
+ let impl_method = match ty_impl_item {
890
+ ty:: MethodTraitItem ( ref mti) => mti,
891
+ _ => tcx. sess . span_bug ( impl_item. span , "non-method impl-item for method" )
892
+ } ;
893
+
894
+ if let & ty:: MethodTraitItem ( ref trait_method) = ty_trait_item {
895
+ compare_impl_method ( ccx. tcx ,
896
+ & impl_method,
897
+ impl_item. span ,
898
+ body. id ,
899
+ & trait_method,
900
+ & impl_trait_ref) ;
901
+ } else {
902
+ span_err ! ( tcx. sess, impl_item. span, E0324 ,
903
+ "item `{}` is an associated method, \
904
+ which doesn't match its trait `{:?}`",
905
+ token:: get_name( impl_method. name) ,
906
+ impl_trait_ref)
936
907
}
937
908
}
938
909
ast:: TypeImplItem ( _) => {
939
- let typedef_def_id = local_def ( impl_item. id ) ;
940
- let typedef_ty = ccx. tcx . impl_or_trait_item ( typedef_def_id) ;
941
-
942
- // If this is an impl of an associated type, find the
943
- // corresponding type definition in the trait.
944
- let opt_associated_type =
945
- trait_items. iter ( )
946
- . find ( |ti| ti. name ( ) == typedef_ty. name ( ) ) ;
947
- match opt_associated_type {
948
- Some ( associated_type) => {
949
- match ( associated_type, & typedef_ty) {
950
- ( & ty:: TypeTraitItem ( _) , & ty:: TypeTraitItem ( _) ) => { }
951
- _ => {
952
- span_err ! ( tcx. sess, impl_item. span, E0325 ,
953
- "item `{}` is an associated type, \
954
- which doesn't match its trait `{:?}`",
955
- token:: get_name( typedef_ty. name( ) ) ,
956
- impl_trait_ref)
957
- }
958
- }
959
- }
960
- None => {
961
- // This is `span_bug` as it should have already been
962
- // caught in resolve.
963
- tcx. sess . span_bug (
964
- impl_item. span ,
965
- & format ! (
966
- "associated type `{}` is not a member of \
967
- trait `{:?}`",
968
- token:: get_name( typedef_ty. name( ) ) ,
969
- impl_trait_ref) ) ;
910
+ let impl_type = match ty_impl_item {
911
+ ty:: TypeTraitItem ( ref tti) => tti,
912
+ _ => tcx. sess . span_bug ( impl_item. span , "non-type impl-item for type" )
913
+ } ;
914
+
915
+ if let & ty:: TypeTraitItem ( ref at) = ty_trait_item {
916
+ if let Some ( _) = at. ty {
917
+ overridden_associated_type = Some ( impl_item) ;
970
918
}
919
+ } else {
920
+ span_err ! ( tcx. sess, impl_item. span, E0325 ,
921
+ "item `{}` is an associated type, \
922
+ which doesn't match its trait `{:?}`",
923
+ token:: get_name( impl_type. name) ,
924
+ impl_trait_ref)
971
925
}
972
926
}
973
927
ast:: MacImplItem ( _) => tcx. sess . span_bug ( impl_item. span ,
@@ -979,6 +933,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
979
933
let provided_methods = tcx. provided_trait_methods ( impl_trait_ref. def_id ) ;
980
934
let associated_consts = tcx. associated_consts ( impl_trait_ref. def_id ) ;
981
935
let mut missing_items = Vec :: new ( ) ;
936
+ let mut invalidated_items = Vec :: new ( ) ;
937
+ let associated_type_overridden = overridden_associated_type. is_some ( ) ;
982
938
for trait_item in trait_items. iter ( ) {
983
939
match * trait_item {
984
940
ty:: ConstTraitItem ( ref associated_const) => {
@@ -993,9 +949,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
993
949
let is_provided =
994
950
associated_consts. iter ( ) . any ( |ac| ac. default . is_some ( ) &&
995
951
ac. name == associated_const. name ) ;
996
- if !is_implemented && !is_provided {
997
- missing_items. push ( format ! ( "`{}`" ,
998
- token:: get_name( associated_const. name) ) ) ;
952
+ if !is_implemented {
953
+ if !is_provided {
954
+ missing_items. push ( associated_const. name ) ;
955
+ } else if associated_type_overridden {
956
+ invalidated_items. push ( associated_const. name ) ;
957
+ }
999
958
}
1000
959
}
1001
960
ty:: MethodTraitItem ( ref trait_method) => {
@@ -1010,8 +969,12 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1010
969
} ) ;
1011
970
let is_provided =
1012
971
provided_methods. iter ( ) . any ( |m| m. name == trait_method. name ) ;
1013
- if !is_implemented && !is_provided {
1014
- missing_items. push ( format ! ( "`{}`" , token:: get_name( trait_method. name) ) ) ;
972
+ if !is_implemented {
973
+ if !is_provided {
974
+ missing_items. push ( trait_method. name ) ;
975
+ } else if associated_type_overridden {
976
+ invalidated_items. push ( trait_method. name ) ;
977
+ }
1015
978
}
1016
979
}
1017
980
ty:: TypeTraitItem ( ref associated_type) => {
@@ -1024,17 +987,34 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
1024
987
}
1025
988
} ) ;
1026
989
let is_provided = associated_type. ty . is_some ( ) ;
1027
- if !is_implemented && !is_provided {
1028
- missing_items. push ( format ! ( "`{}`" , token:: get_name( associated_type. name) ) ) ;
990
+ if !is_implemented {
991
+ if !is_provided {
992
+ missing_items. push ( associated_type. name ) ;
993
+ } else if associated_type_overridden {
994
+ invalidated_items. push ( associated_type. name ) ;
995
+ }
1029
996
}
1030
997
}
1031
998
}
1032
999
}
1033
1000
1034
1001
if !missing_items. is_empty ( ) {
1035
1002
span_err ! ( tcx. sess, impl_span, E0046 ,
1036
- "not all trait items implemented, missing: {}" ,
1037
- missing_items. connect( ", " ) ) ;
1003
+ "not all trait items implemented, missing: `{}`" ,
1004
+ missing_items. iter( )
1005
+ . map( <ast:: Name >:: as_str)
1006
+ . collect:: <Vec <_>>( ) . connect( "`, `" ) )
1007
+ }
1008
+
1009
+ if !invalidated_items. is_empty ( ) {
1010
+ let invalidator = overridden_associated_type. unwrap ( ) ;
1011
+ span_err ! ( tcx. sess, invalidator. span, E0399 ,
1012
+ "the following trait items need to be reimplemented \
1013
+ as `{}` was overridden: `{}`",
1014
+ invalidator. ident. as_str( ) ,
1015
+ invalidated_items. iter( )
1016
+ . map( <ast:: Name >:: as_str)
1017
+ . collect:: <Vec <_>>( ) . connect( "`, `" ) )
1038
1018
}
1039
1019
}
1040
1020
0 commit comments