@@ -846,15 +846,13 @@ pub(super) fn check_specialization_validity<'tcx>(
846846 Ok ( ancestors) => ancestors,
847847 Err ( _) => return ,
848848 } ;
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+ } ) ;
858856
859857 let opt_result = ancestor_impls. find_map ( |( parent_impl, parent_item) | {
860858 match parent_item {
@@ -931,105 +929,72 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
931929 // Check existing impl methods to see if they are both present in trait
932930 // and compatible with trait signature
933931 for impl_item in impl_items {
934- let namespace = impl_item. kind . namespace ( ) ;
935932 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 {
948966 match impl_item. kind {
949967 hir:: ImplItemKind :: Const ( ..) => {
950968 // 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+ ) ;
977976 }
978977 hir:: ImplItemKind :: Fn ( ..) => {
979978 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+ ) ;
1005987 }
1006988 hir:: ImplItemKind :: TyAlias ( _) => {
1007989 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+ ) ;
1033998 }
1034999 }
10351000
@@ -1040,6 +1005,8 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
10401005 impl_id. to_def_id ( ) ,
10411006 impl_item,
10421007 ) ;
1008+ } else {
1009+ report_mismatch_error ( tcx, ty_trait_item. def_id , impl_trait_ref, impl_item, & ty_impl_item) ;
10431010 }
10441011 }
10451012
@@ -1065,6 +1032,58 @@ pub(super) fn check_impl_items_against_trait<'tcx>(
10651032 }
10661033}
10671034
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+
10681087/// Checks whether a type can be represented in memory. In particular, it
10691088/// identifies types that contain themselves without indirection through a
10701089/// pointer, which would mean their size is unbounded.
0 commit comments