@@ -846,15 +846,13 @@ pub(super) fn check_specialization_validity<'tcx>(
846
846
Ok ( ancestors) => ancestors,
847
847
Err ( _) => return ,
848
848
} ;
849
- let mut ancestor_impls = ancestors
850
- . skip ( 1 )
851
- . filter_map ( |parent| {
852
- if parent. is_from_trait ( ) {
853
- None
854
- } else {
855
- Some ( ( parent, parent. item ( tcx, trait_item. ident , kind, trait_def. def_id ) ) )
856
- }
857
- } ) ;
849
+ let mut ancestor_impls = ancestors. skip ( 1 ) . filter_map ( |parent| {
850
+ if parent. is_from_trait ( ) {
851
+ None
852
+ } else {
853
+ Some ( ( parent, parent. item ( tcx, trait_item. ident , kind, trait_def. def_id ) ) )
854
+ }
855
+ } ) ;
858
856
859
857
let opt_result = ancestor_impls. find_map ( |( parent_impl, parent_item) | {
860
858
match parent_item {
@@ -931,105 +929,72 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
931
929
// Check existing impl methods to see if they are both present in trait
932
930
// and compatible with trait signature
933
931
for impl_item in impl_items {
934
- let namespace = impl_item. kind . namespace ( ) ;
935
932
let ty_impl_item = tcx. associated_item ( tcx. hir ( ) . local_def_id ( impl_item. hir_id ) ) ;
936
- let ty_trait_item = tcx
937
- . associated_items ( impl_trait_ref. def_id )
938
- . find_by_name_and_namespace ( tcx, ty_impl_item. ident , namespace, impl_trait_ref. def_id )
939
- . or_else ( || {
940
- // Not compatible, but needed for the error message
941
- tcx. associated_items ( impl_trait_ref. def_id )
942
- . filter_by_name ( tcx, ty_impl_item. ident , impl_trait_ref. def_id )
943
- . next ( )
944
- } ) ;
945
-
946
- // Check that impl definition matches trait definition
947
- if let Some ( ty_trait_item) = ty_trait_item {
933
+ let associated_items = tcx. associated_items ( impl_trait_ref. def_id ) ;
934
+
935
+ let mut items = associated_items. filter_by_name ( tcx, ty_impl_item. ident , impl_trait_ref. def_id ) ;
936
+
937
+ let ( compatible_kind, ty_trait_item) = if let Some ( ty_trait_item) = items. next ( ) {
938
+
939
+ let is_compatible = |ty : & & ty:: AssocItem | {
940
+ match ( ty. kind , & impl_item. kind ) {
941
+ ( ty:: AssocKind :: Const , hir:: ImplItemKind :: Const ( ..) ) => true ,
942
+ ( ty:: AssocKind :: Fn , hir:: ImplItemKind :: Fn ( ..) ) => true ,
943
+ ( ty:: AssocKind :: Type , hir:: ImplItemKind :: TyAlias ( ..) ) => true ,
944
+ _ => false
945
+ }
946
+ } ;
947
+
948
+ // If we don't have a compatible item, we'll use the first one whose name matches
949
+ // to report an error.
950
+ let mut compatible_kind = is_compatible ( & ty_trait_item) ;
951
+ let mut trait_item = ty_trait_item;
952
+
953
+ if !compatible_kind {
954
+ if let Some ( ty_trait_item) = items. find ( is_compatible) {
955
+ compatible_kind = true ;
956
+ trait_item = ty_trait_item;
957
+ }
958
+ }
959
+
960
+ ( compatible_kind, trait_item)
961
+ } else {
962
+ continue ;
963
+ } ;
964
+
965
+ if compatible_kind {
948
966
match impl_item. kind {
949
967
hir:: ImplItemKind :: Const ( ..) => {
950
968
// Find associated const definition.
951
- if ty_trait_item. kind == ty:: AssocKind :: Const {
952
- compare_const_impl (
953
- tcx,
954
- & ty_impl_item,
955
- impl_item. span ,
956
- & ty_trait_item,
957
- impl_trait_ref,
958
- ) ;
959
- } else {
960
- let mut err = struct_span_err ! (
961
- tcx. sess,
962
- impl_item. span,
963
- E0323 ,
964
- "item `{}` is an associated const, \
965
- which doesn't match its trait `{}`",
966
- ty_impl_item. ident,
967
- impl_trait_ref. print_only_trait_path( )
968
- ) ;
969
- err. span_label ( impl_item. span , "does not match trait" ) ;
970
- // We can only get the spans from local trait definition
971
- // Same for E0324 and E0325
972
- if let Some ( trait_span) = tcx. hir ( ) . span_if_local ( ty_trait_item. def_id ) {
973
- err. span_label ( trait_span, "item in trait" ) ;
974
- }
975
- err. emit ( )
976
- }
969
+ compare_const_impl (
970
+ tcx,
971
+ & ty_impl_item,
972
+ impl_item. span ,
973
+ & ty_trait_item,
974
+ impl_trait_ref,
975
+ ) ;
977
976
}
978
977
hir:: ImplItemKind :: Fn ( ..) => {
979
978
let opt_trait_span = tcx. hir ( ) . span_if_local ( ty_trait_item. def_id ) ;
980
- if ty_trait_item. kind == ty:: AssocKind :: Fn {
981
- compare_impl_method (
982
- tcx,
983
- & ty_impl_item,
984
- impl_item. span ,
985
- & ty_trait_item,
986
- impl_trait_ref,
987
- opt_trait_span,
988
- ) ;
989
- } else {
990
- let mut err = struct_span_err ! (
991
- tcx. sess,
992
- impl_item. span,
993
- E0324 ,
994
- "item `{}` is an associated method, \
995
- which doesn't match its trait `{}`",
996
- ty_impl_item. ident,
997
- impl_trait_ref. print_only_trait_path( )
998
- ) ;
999
- err. span_label ( impl_item. span , "does not match trait" ) ;
1000
- if let Some ( trait_span) = opt_trait_span {
1001
- err. span_label ( trait_span, "item in trait" ) ;
1002
- }
1003
- err. emit ( )
1004
- }
979
+ compare_impl_method (
980
+ tcx,
981
+ & ty_impl_item,
982
+ impl_item. span ,
983
+ & ty_trait_item,
984
+ impl_trait_ref,
985
+ opt_trait_span,
986
+ ) ;
1005
987
}
1006
988
hir:: ImplItemKind :: TyAlias ( _) => {
1007
989
let opt_trait_span = tcx. hir ( ) . span_if_local ( ty_trait_item. def_id ) ;
1008
- if ty_trait_item. kind == ty:: AssocKind :: Type {
1009
- compare_ty_impl (
1010
- tcx,
1011
- & ty_impl_item,
1012
- impl_item. span ,
1013
- & ty_trait_item,
1014
- impl_trait_ref,
1015
- opt_trait_span,
1016
- ) ;
1017
- } else {
1018
- let mut err = struct_span_err ! (
1019
- tcx. sess,
1020
- impl_item. span,
1021
- E0325 ,
1022
- "item `{}` is an associated type, \
1023
- which doesn't match its trait `{}`",
1024
- ty_impl_item. ident,
1025
- impl_trait_ref. print_only_trait_path( )
1026
- ) ;
1027
- err. span_label ( impl_item. span , "does not match trait" ) ;
1028
- if let Some ( trait_span) = opt_trait_span {
1029
- err. span_label ( trait_span, "item in trait" ) ;
1030
- }
1031
- err. emit ( )
1032
- }
990
+ compare_ty_impl (
991
+ tcx,
992
+ & ty_impl_item,
993
+ impl_item. span ,
994
+ & ty_trait_item,
995
+ impl_trait_ref,
996
+ opt_trait_span,
997
+ ) ;
1033
998
}
1034
999
}
1035
1000
@@ -1040,6 +1005,8 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
1040
1005
impl_id. to_def_id ( ) ,
1041
1006
impl_item,
1042
1007
) ;
1008
+ } else {
1009
+ report_mismatch_error ( tcx, ty_trait_item. def_id , impl_trait_ref, impl_item, & ty_impl_item) ;
1043
1010
}
1044
1011
}
1045
1012
@@ -1065,6 +1032,58 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
1065
1032
}
1066
1033
}
1067
1034
1035
+ #[ inline( never) ]
1036
+ #[ cold]
1037
+ fn report_mismatch_error < ' tcx > (
1038
+ tcx : TyCtxt < ' tcx > ,
1039
+ trait_item_def_id : DefId ,
1040
+ impl_trait_ref : ty:: TraitRef < ' tcx > ,
1041
+ impl_item : & hir:: ImplItem < ' _ > ,
1042
+ ty_impl_item : & ty:: AssocItem ,
1043
+ ) {
1044
+ let mut err = match impl_item. kind {
1045
+ hir:: ImplItemKind :: Const ( ..) => {
1046
+ // Find associated const definition.
1047
+ struct_span_err ! (
1048
+ tcx. sess,
1049
+ impl_item. span,
1050
+ E0323 ,
1051
+ "item `{}` is an associated const, which doesn't match its trait `{}`" ,
1052
+ ty_impl_item. ident,
1053
+ impl_trait_ref. print_only_trait_path( )
1054
+ )
1055
+ }
1056
+
1057
+ hir:: ImplItemKind :: Fn ( ..) => {
1058
+ struct_span_err ! (
1059
+ tcx. sess,
1060
+ impl_item. span,
1061
+ E0324 ,
1062
+ "item `{}` is an associated method, which doesn't match its trait `{}`" ,
1063
+ ty_impl_item. ident,
1064
+ impl_trait_ref. print_only_trait_path( )
1065
+ )
1066
+ }
1067
+
1068
+ hir:: ImplItemKind :: TyAlias ( _) => {
1069
+ struct_span_err ! (
1070
+ tcx. sess,
1071
+ impl_item. span,
1072
+ E0325 ,
1073
+ "item `{}` is an associated type, which doesn't match its trait `{}`" ,
1074
+ ty_impl_item. ident,
1075
+ impl_trait_ref. print_only_trait_path( )
1076
+ )
1077
+ }
1078
+ } ;
1079
+
1080
+ err. span_label ( impl_item. span , "does not match trait" ) ;
1081
+ if let Some ( trait_span) = tcx. hir ( ) . span_if_local ( trait_item_def_id) {
1082
+ err. span_label ( trait_span, "item in trait" ) ;
1083
+ }
1084
+ err. emit ( ) ;
1085
+ }
1086
+
1068
1087
/// Checks whether a type can be represented in memory. In particular, it
1069
1088
/// identifies types that contain themselves without indirection through a
1070
1089
/// pointer, which would mean their size is unbounded.
0 commit comments