@@ -2788,69 +2788,119 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2788
2788
errors : Vec < FulfillmentError < ' tcx > > ,
2789
2789
suggest_derive : bool ,
2790
2790
) {
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 ( ) {
2793
2794
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) ) => {
2794
2795
match pred. self_ty ( ) . kind ( ) {
2795
- ty:: Adt ( def , _) => def . did ( ) . is_local ( ) ,
2796
- _ => false ,
2796
+ ty:: Adt ( _ , _) => Some ( pred ) ,
2797
+ _ => None ,
2797
2798
}
2798
2799
}
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) ,
2805
2800
_ => None ,
2806
2801
} )
2807
2802
. 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
2810
2816
. iter ( )
2811
2817
. filter_map ( |pred| match pred. self_ty ( ) . kind ( ) {
2812
2818
ty:: Adt ( def, _) => Some ( def. did ( ) ) ,
2813
2819
_ => None ,
2814
2820
} )
2815
2821
. collect :: < FxIndexSet < _ > > ( ) ;
2816
- let mut spans : MultiSpan = def_ids
2822
+ let mut local_spans : MultiSpan = local_def_ids
2817
2823
. iter ( )
2818
2824
. filter_map ( |def_id| {
2819
2825
let span = self . tcx . def_span ( * def_id) ;
2820
2826
if span. is_dummy ( ) { None } else { Some ( span) }
2821
2827
} )
2822
2828
. collect :: < Vec < _ > > ( )
2823
2829
. into ( ) ;
2824
-
2825
- for pred in & preds {
2830
+ for pred in & local_preds {
2826
2831
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 (
2829
2834
self . tcx . def_span ( def. did ( ) ) ,
2830
2835
format ! ( "must implement `{}`" , pred. trait_ref. print_trait_sugared( ) ) ,
2831
2836
) ;
2832
2837
}
2833
2838
_ => { }
2834
2839
}
2835
2840
}
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 {
2839
2843
format ! (
2840
2844
"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( )
2843
2847
)
2844
2848
} else {
2845
2849
format ! (
2846
2850
"the following type{} would have to `impl` {} required trait{} for this \
2847
2851
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( ) ) ,
2851
2901
)
2852
2902
} ;
2853
- err. span_note ( spans , msg) ;
2903
+ err. span_note ( foreign_spans , msg) ;
2854
2904
}
2855
2905
2856
2906
let preds: Vec < _ > = errors
0 commit comments