@@ -17,7 +17,9 @@ use rustc_span::lev_distance;
17
17
use rustc_span:: symbol:: { kw, sym, Ident } ;
18
18
use rustc_span:: { source_map, FileName , MultiSpan , Span , Symbol } ;
19
19
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
20
- use rustc_trait_selection:: traits:: { FulfillmentError , Obligation } ;
20
+ use rustc_trait_selection:: traits:: {
21
+ FulfillmentError , Obligation , ObligationCause , ObligationCauseCode ,
22
+ } ;
21
23
22
24
use std:: cmp:: Ordering ;
23
25
use std:: iter;
@@ -787,9 +789,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
787
789
_ => None ,
788
790
}
789
791
} ;
792
+
793
+ // Find all the requirements that come from a local `impl` block.
794
+ let mut skip_list: FxHashSet < _ > = Default :: default ( ) ;
795
+ let mut spanned_predicates: FxHashMap < MultiSpan , _ > = Default :: default ( ) ;
796
+ for ( data, p, parent_p) in unsatisfied_predicates
797
+ . iter ( )
798
+ . filter_map ( |( p, parent, c) | c. as_ref ( ) . map ( |c| ( p, parent, c) ) )
799
+ . filter_map ( |( p, parent, c) | match c. code {
800
+ ObligationCauseCode :: ImplDerivedObligation ( ref data) => {
801
+ Some ( ( data, p, parent) )
802
+ }
803
+ _ => None ,
804
+ } )
805
+ {
806
+ let parent_trait_ref = data. parent_trait_ref ;
807
+ let parent_def_id = parent_trait_ref. def_id ( ) ;
808
+ let path = parent_trait_ref. print_only_trait_path ( ) ;
809
+ let tr_self_ty = parent_trait_ref. skip_binder ( ) . self_ty ( ) ;
810
+ let mut candidates = vec ! [ ] ;
811
+ self . tcx . for_each_relevant_impl (
812
+ parent_def_id,
813
+ parent_trait_ref. self_ty ( ) . skip_binder ( ) ,
814
+ |impl_def_id| match self . tcx . hir ( ) . get_if_local ( impl_def_id) {
815
+ Some ( Node :: Item ( hir:: Item {
816
+ kind : hir:: ItemKind :: Impl ( hir:: Impl { .. } ) ,
817
+ ..
818
+ } ) ) => {
819
+ candidates. push ( impl_def_id) ;
820
+ }
821
+ _ => { }
822
+ } ,
823
+ ) ;
824
+ if let [ def_id] = & candidates[ ..] {
825
+ match self . tcx . hir ( ) . get_if_local ( * def_id) {
826
+ Some ( Node :: Item ( hir:: Item {
827
+ kind : hir:: ItemKind :: Impl ( hir:: Impl { of_trait, self_ty, .. } ) ,
828
+ ..
829
+ } ) ) => {
830
+ if let Some ( pred) = parent_p {
831
+ // Done to add the "doesn't satisfy" `span_label`.
832
+ let _ = format_pred ( * pred) ;
833
+ }
834
+ skip_list. insert ( p) ;
835
+ let mut spans = Vec :: with_capacity ( 2 ) ;
836
+ if let Some ( trait_ref) = of_trait {
837
+ spans. push ( trait_ref. path . span ) ;
838
+ }
839
+ spans. push ( self_ty. span ) ;
840
+ let entry = spanned_predicates. entry ( spans. into ( ) ) ;
841
+ entry
842
+ . or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) )
843
+ . 2
844
+ . push ( p) ;
845
+ }
846
+ _ => { }
847
+ }
848
+ }
849
+ }
850
+ for ( span, ( path, self_ty, preds) ) in spanned_predicates {
851
+ err. span_note (
852
+ span,
853
+ & format ! (
854
+ "the following trait bounds were not satisfied because of the \
855
+ requirements of the implementation of `{}` for `{}`:\n {}",
856
+ path,
857
+ self_ty,
858
+ preds
859
+ . into_iter( )
860
+ // .map(|pred| format!("{:?}", pred))
861
+ . filter_map( |pred| format_pred( * pred) )
862
+ . map( |( p, _) | format!( "`{}`" , p) )
863
+ . collect:: <Vec <_>>( )
864
+ . join( "\n " ) ,
865
+ ) ,
866
+ ) ;
867
+ }
868
+
869
+ // The requirements that didn't have an `impl` span to show.
790
870
let mut bound_list = unsatisfied_predicates
791
871
. iter ( )
792
- . filter_map ( |( pred, parent_pred) | {
872
+ . filter ( |( pred, _, _parent_pred) | !skip_list. contains ( & pred) )
873
+ . filter_map ( |( pred, parent_pred, _cause) | {
793
874
format_pred ( * pred) . map ( |( p, self_ty) | match parent_pred {
794
875
None => format ! ( "`{}`" , & p) ,
795
876
Some ( parent_pred) => match format_pred ( * parent_pred) {
@@ -832,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
832
913
for ( span, msg) in bound_spans. into_iter ( ) {
833
914
err. span_label ( span, & msg) ;
834
915
}
835
- if !bound_list. is_empty ( ) {
916
+ if !bound_list. is_empty ( ) || !skip_list . is_empty ( ) {
836
917
let bound_list = bound_list
837
918
. into_iter ( )
838
919
. map ( |( _, path) | path)
@@ -842,9 +923,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
842
923
err. set_primary_message ( & format ! (
843
924
"the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
844
925
) ) ;
845
- err. note ( & format ! (
846
- "the following trait bounds were not satisfied:\n {bound_list}"
847
- ) ) ;
926
+ if !bound_list. is_empty ( ) {
927
+ err. note ( & format ! (
928
+ "the following trait bounds were not satisfied:\n {bound_list}"
929
+ ) ) ;
930
+ }
848
931
self . suggest_derive ( & mut err, & unsatisfied_predicates) ;
849
932
850
933
unsatisfied_bounds = true ;
@@ -1058,18 +1141,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1058
1141
err. span_note ( spans, & msg) ;
1059
1142
}
1060
1143
1061
- let preds: Vec < _ > = errors. iter ( ) . map ( |e| ( e. obligation . predicate , None ) ) . collect ( ) ;
1144
+ let preds: Vec < _ > = errors
1145
+ . iter ( )
1146
+ . map ( |e| ( e. obligation . predicate , None , Some ( e. obligation . cause . clone ( ) ) ) )
1147
+ . collect ( ) ;
1062
1148
self . suggest_derive ( err, & preds) ;
1063
1149
}
1064
1150
1065
1151
fn suggest_derive (
1066
1152
& self ,
1067
1153
err : & mut DiagnosticBuilder < ' _ > ,
1068
- unsatisfied_predicates : & Vec < ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) > ,
1154
+ unsatisfied_predicates : & Vec < (
1155
+ ty:: Predicate < ' tcx > ,
1156
+ Option < ty:: Predicate < ' tcx > > ,
1157
+ Option < ObligationCause < ' tcx > > ,
1158
+ ) > ,
1069
1159
) {
1070
1160
let mut derives = Vec :: < ( String , Span , String ) > :: new ( ) ;
1071
1161
let mut traits = Vec :: < Span > :: new ( ) ;
1072
- for ( pred, _) in unsatisfied_predicates {
1162
+ for ( pred, _, _ ) in unsatisfied_predicates {
1073
1163
let trait_pred = match pred. kind ( ) . skip_binder ( ) {
1074
1164
ty:: PredicateKind :: Trait ( trait_pred) => trait_pred,
1075
1165
_ => continue ,
@@ -1260,7 +1350,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1260
1350
item_name : Ident ,
1261
1351
source : SelfSource < ' tcx > ,
1262
1352
valid_out_of_scope_traits : Vec < DefId > ,
1263
- unsatisfied_predicates : & [ ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) ] ,
1353
+ unsatisfied_predicates : & [ (
1354
+ ty:: Predicate < ' tcx > ,
1355
+ Option < ty:: Predicate < ' tcx > > ,
1356
+ Option < ObligationCause < ' tcx > > ,
1357
+ ) ] ,
1264
1358
unsatisfied_bounds : bool ,
1265
1359
) {
1266
1360
let mut alt_rcvr_sugg = false ;
@@ -1376,7 +1470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1376
1470
// this isn't perfect (that is, there are cases when
1377
1471
// implementing a trait would be legal but is rejected
1378
1472
// here).
1379
- unsatisfied_predicates. iter ( ) . all ( |( p, _) | {
1473
+ unsatisfied_predicates. iter ( ) . all ( |( p, _, _ ) | {
1380
1474
match p. kind ( ) . skip_binder ( ) {
1381
1475
// Hide traits if they are present in predicates as they can be fixed without
1382
1476
// having to implement them.
0 commit comments