@@ -2831,69 +2831,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
28312831 errors : Vec < FulfillmentError < ' tcx > > ,
28322832 suggest_derive : bool ,
28332833 ) {
2834- let all_local_types_needing_impls =
2835- errors. iter ( ) . all ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
2834+ let preds: Vec < _ > = errors
2835+ . iter ( )
2836+ . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
28362837 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
28372838 match pred. self_ty ( ) . kind ( ) {
2838- ty:: Adt ( def , _) => def . did ( ) . is_local ( ) ,
2839- _ => false ,
2839+ ty:: Adt ( _ , _) => Some ( pred ) ,
2840+ _ => None ,
28402841 }
28412842 }
2842- _ => false ,
2843- } ) ;
2844- let mut preds: Vec < _ > = errors
2845- . iter ( )
2846- . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
2847- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => Some ( pred) ,
28482843 _ => None ,
28492844 } )
28502845 . collect ( ) ;
2851- preds. sort_by_key ( |pred| pred. trait_ref . to_string ( ) ) ;
2852- let def_ids = preds
2846+
2847+ // Note for local items and foreign items respectively.
2848+ let ( mut local_preds, mut foreign_preds) : ( Vec < _ > , Vec < _ > ) =
2849+ preds. iter ( ) . partition ( |& pred| {
2850+ if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
2851+ def. did ( ) . is_local ( )
2852+ } else {
2853+ false
2854+ }
2855+ } ) ;
2856+
2857+ local_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
2858+ let local_def_ids = local_preds
28532859 . iter ( )
28542860 . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
28552861 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
28562862 _ => None ,
28572863 } )
28582864 . collect :: < FxIndexSet < _ > > ( ) ;
2859- let mut spans : MultiSpan = def_ids
2865+ let mut local_spans : MultiSpan = local_def_ids
28602866 . iter ( )
28612867 . filter_map ( |def_id| {
28622868 let span = self . tcx . def_span ( * def_id) ;
28632869 if span. is_dummy ( ) { None } else { Some ( span) }
28642870 } )
28652871 . collect :: < Vec < _ > > ( )
28662872 . into ( ) ;
2867-
2868- for pred in & preds {
2873+ for pred in & local_preds {
28692874 match pred. self_ty ( ) . kind ( ) {
2870- ty:: Adt ( def, _) if def . did ( ) . is_local ( ) => {
2871- spans . push_span_label (
2875+ ty:: Adt ( def, _) => {
2876+ local_spans . push_span_label (
28722877 self . tcx . def_span ( def. did ( ) ) ,
28732878 format ! ( "must implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
28742879 ) ;
28752880 }
28762881 _ => { }
28772882 }
28782883 }
2879-
2880- if all_local_types_needing_impls && spans. primary_span ( ) . is_some ( ) {
2881- let msg = if preds. len ( ) == 1 {
2884+ if local_spans. primary_span ( ) . is_some ( ) {
2885+ let msg = if local_preds. len ( ) == 1 {
28822886 format ! (
28832887 "an implementation of `{}` might be missing for `{}`" ,
2884- preds [ 0 ] . trait_ref. print_trait_sugared( ) ,
2885- preds [ 0 ] . self_ty( )
2888+ local_preds [ 0 ] . trait_ref. print_trait_sugared( ) ,
2889+ local_preds [ 0 ] . self_ty( )
28862890 )
28872891 } else {
28882892 format ! (
28892893 "the following type{} would have to `impl` {} required trait{} for this \
28902894 operation to be valid",
2891- pluralize!( def_ids. len( ) ) ,
2892- if def_ids. len( ) == 1 { "its" } else { "their" } ,
2893- pluralize!( preds. len( ) ) ,
2895+ pluralize!( local_def_ids. len( ) ) ,
2896+ if local_def_ids. len( ) == 1 { "its" } else { "their" } ,
2897+ pluralize!( local_preds. len( ) ) ,
2898+ )
2899+ } ;
2900+ err. span_note ( local_spans, msg) ;
2901+ }
2902+
2903+ foreign_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
2904+ let foreign_def_ids = foreign_preds
2905+ . iter ( )
2906+ . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
2907+ ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
2908+ _ => None ,
2909+ } )
2910+ . collect :: < FxIndexSet < _ > > ( ) ;
2911+ let mut foreign_spans: MultiSpan = foreign_def_ids
2912+ . iter ( )
2913+ . filter_map ( |def_id| {
2914+ let span = self . tcx . def_span ( * def_id) ;
2915+ if span. is_dummy ( ) { None } else { Some ( span) }
2916+ } )
2917+ . collect :: < Vec < _ > > ( )
2918+ . into ( ) ;
2919+ for pred in & foreign_preds {
2920+ match pred. self_ty ( ) . kind ( ) {
2921+ ty:: Adt ( def, _) => {
2922+ foreign_spans. push_span_label (
2923+ self . tcx . def_span ( def. did ( ) ) ,
2924+ format ! ( "not implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
2925+ ) ;
2926+ }
2927+ _ => { }
2928+ }
2929+ }
2930+ if foreign_spans. primary_span ( ) . is_some ( ) {
2931+ let msg = if foreign_preds. len ( ) == 1 {
2932+ format ! (
2933+ "the foreign item type `{}` doesn't implement `{}`" ,
2934+ foreign_preds[ 0 ] . self_ty( ) ,
2935+ foreign_preds[ 0 ] . trait_ref. print_trait_sugared( )
2936+ )
2937+ } else {
2938+ format ! (
2939+ "the foreign item type{} {} implement required trait{} for this \
2940+ operation to be valid",
2941+ pluralize!( foreign_def_ids. len( ) ) ,
2942+ if foreign_def_ids. len( ) > 1 { "don't" } else { "doesn't" } ,
2943+ pluralize!( foreign_preds. len( ) ) ,
28942944 )
28952945 } ;
2896- err. span_note ( spans , msg) ;
2946+ err. span_note ( foreign_spans , msg) ;
28972947 }
28982948
28992949 let preds: Vec < _ > = errors
0 commit comments