@@ -2788,69 +2788,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
27882788 errors : Vec < FulfillmentError < ' tcx > > ,
27892789 suggest_derive : bool ,
27902790 ) {
2791- let all_local_types_needing_impls =
2792- errors. iter ( ) . all ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
2791+ let preds: Vec < _ > = errors
2792+ . iter ( )
2793+ . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
27932794 ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
27942795 match pred. self_ty ( ) . kind ( ) {
2795- ty:: Adt ( def , _) => def . did ( ) . is_local ( ) ,
2796- _ => false ,
2796+ ty:: Adt ( _ , _) => Some ( pred ) ,
2797+ _ => None ,
27972798 }
27982799 }
2799- _ => false ,
2800- } ) ;
2801- let mut preds: Vec < _ > = errors
2802- . iter ( )
2803- . filter_map ( |e| match e. obligation . predicate . kind ( ) . skip_binder ( ) {
2804- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => Some ( pred) ,
28052800 _ => None ,
28062801 } )
28072802 . collect ( ) ;
2808- preds. sort_by_key ( |pred| pred. trait_ref . to_string ( ) ) ;
2809- let def_ids = preds
2803+
2804+ // Note for local items and foreign items respectively.
2805+ let ( mut local_preds, mut foreign_preds) : ( Vec < _ > , Vec < _ > ) =
2806+ preds. iter ( ) . partition ( |& pred| {
2807+ if let ty:: Adt ( def, _) = pred. self_ty ( ) . kind ( ) {
2808+ def. did ( ) . is_local ( )
2809+ } else {
2810+ false
2811+ }
2812+ } ) ;
2813+
2814+ local_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
2815+ let local_def_ids = local_preds
28102816 . iter ( )
28112817 . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
28122818 ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
28132819 _ => None ,
28142820 } )
28152821 . collect :: < FxIndexSet < _ > > ( ) ;
2816- let mut spans : MultiSpan = def_ids
2822+ let mut local_spans : MultiSpan = local_def_ids
28172823 . iter ( )
28182824 . filter_map ( |def_id| {
28192825 let span = self . tcx . def_span ( * def_id) ;
28202826 if span. is_dummy ( ) { None } else { Some ( span) }
28212827 } )
28222828 . collect :: < Vec < _ > > ( )
28232829 . into ( ) ;
2824-
2825- for pred in & preds {
2830+ for pred in & local_preds {
28262831 match pred. self_ty ( ) . kind ( ) {
2827- ty:: Adt ( def, _) if def . did ( ) . is_local ( ) => {
2828- spans . push_span_label (
2832+ ty:: Adt ( def, _) => {
2833+ local_spans . push_span_label (
28292834 self . tcx . def_span ( def. did ( ) ) ,
28302835 format ! ( "must implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
28312836 ) ;
28322837 }
28332838 _ => { }
28342839 }
28352840 }
2836-
2837- if all_local_types_needing_impls && spans. primary_span ( ) . is_some ( ) {
2838- let msg = if preds. len ( ) == 1 {
2841+ if local_spans. primary_span ( ) . is_some ( ) {
2842+ let msg = if local_preds. len ( ) == 1 {
28392843 format ! (
28402844 "an implementation of `{}` might be missing for `{}`" ,
2841- preds [ 0 ] . trait_ref. print_trait_sugared( ) ,
2842- preds [ 0 ] . self_ty( )
2845+ local_preds [ 0 ] . trait_ref. print_trait_sugared( ) ,
2846+ local_preds [ 0 ] . self_ty( )
28432847 )
28442848 } else {
28452849 format ! (
28462850 "the following type{} would have to `impl` {} required trait{} for this \
28472851 operation to be valid",
2848- pluralize!( def_ids. len( ) ) ,
2849- if def_ids. len( ) == 1 { "its" } else { "their" } ,
2850- pluralize!( preds. len( ) ) ,
2852+ pluralize!( local_def_ids. len( ) ) ,
2853+ if local_def_ids. len( ) == 1 { "its" } else { "their" } ,
2854+ pluralize!( local_preds. len( ) ) ,
2855+ )
2856+ } ;
2857+ err. span_note ( local_spans, msg) ;
2858+ }
2859+
2860+ foreign_preds. sort_by_key ( |pred : & & ty:: TraitPredicate < ' _ > | pred. trait_ref . to_string ( ) ) ;
2861+ let foreign_def_ids = foreign_preds
2862+ . iter ( )
2863+ . filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
2864+ ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
2865+ _ => None ,
2866+ } )
2867+ . collect :: < FxIndexSet < _ > > ( ) ;
2868+ let mut foreign_spans: MultiSpan = foreign_def_ids
2869+ . iter ( )
2870+ . filter_map ( |def_id| {
2871+ let span = self . tcx . def_span ( * def_id) ;
2872+ if span. is_dummy ( ) { None } else { Some ( span) }
2873+ } )
2874+ . collect :: < Vec < _ > > ( )
2875+ . into ( ) ;
2876+ for pred in & foreign_preds {
2877+ match pred. self_ty ( ) . kind ( ) {
2878+ ty:: Adt ( def, _) => {
2879+ foreign_spans. push_span_label (
2880+ self . tcx . def_span ( def. did ( ) ) ,
2881+ format ! ( "not implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
2882+ ) ;
2883+ }
2884+ _ => { }
2885+ }
2886+ }
2887+ if foreign_spans. primary_span ( ) . is_some ( ) {
2888+ let msg = if foreign_preds. len ( ) == 1 {
2889+ format ! (
2890+ "the foreign item type `{}` doesn't implement `{}`" ,
2891+ foreign_preds[ 0 ] . self_ty( ) ,
2892+ foreign_preds[ 0 ] . trait_ref. print_trait_sugared( )
2893+ )
2894+ } else {
2895+ format ! (
2896+ "the foreign item type{} {} implement required trait{} for this \
2897+ operation to be valid",
2898+ pluralize!( foreign_def_ids. len( ) ) ,
2899+ if foreign_def_ids. len( ) > 1 { "don't" } else { "doesn't" } ,
2900+ pluralize!( foreign_preds. len( ) ) ,
28512901 )
28522902 } ;
2853- err. span_note ( spans , msg) ;
2903+ err. span_note ( foreign_spans , msg) ;
28542904 }
28552905
28562906 let preds: Vec < _ > = errors
0 commit comments