@@ -17,7 +17,9 @@ use rustc_span::lev_distance;
1717use rustc_span:: symbol:: { kw, sym, Ident } ;
1818use rustc_span:: { source_map, FileName , MultiSpan , Span , Symbol } ;
1919use 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+ } ;
2123
2224use std:: cmp:: Ordering ;
2325use std:: iter;
@@ -787,9 +789,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
787789 _ => None ,
788790 }
789791 } ;
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.
790870 let mut bound_list = unsatisfied_predicates
791871 . iter ( )
792- . filter_map ( |( pred, parent_pred) | {
872+ . filter ( |( pred, _, _parent_pred) | !skip_list. contains ( & pred) )
873+ . filter_map ( |( pred, parent_pred, _cause) | {
793874 format_pred ( * pred) . map ( |( p, self_ty) | match parent_pred {
794875 None => format ! ( "`{}`" , & p) ,
795876 Some ( parent_pred) => match format_pred ( * parent_pred) {
@@ -832,7 +913,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
832913 for ( span, msg) in bound_spans. into_iter ( ) {
833914 err. span_label ( span, & msg) ;
834915 }
835- if !bound_list. is_empty ( ) {
916+ if !bound_list. is_empty ( ) || !skip_list . is_empty ( ) {
836917 let bound_list = bound_list
837918 . into_iter ( )
838919 . map ( |( _, path) | path)
@@ -842,9 +923,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
842923 err. set_primary_message ( & format ! (
843924 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
844925 ) ) ;
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+ }
848931 self . suggest_derive ( & mut err, & unsatisfied_predicates) ;
849932
850933 unsatisfied_bounds = true ;
@@ -1058,18 +1141,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10581141 err. span_note ( spans, & msg) ;
10591142 }
10601143
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 ( ) ;
10621148 self . suggest_derive ( err, & preds) ;
10631149 }
10641150
10651151 fn suggest_derive (
10661152 & self ,
10671153 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+ ) > ,
10691159 ) {
10701160 let mut derives = Vec :: < ( String , Span , String ) > :: new ( ) ;
10711161 let mut traits = Vec :: < Span > :: new ( ) ;
1072- for ( pred, _) in unsatisfied_predicates {
1162+ for ( pred, _, _ ) in unsatisfied_predicates {
10731163 let trait_pred = match pred. kind ( ) . skip_binder ( ) {
10741164 ty:: PredicateKind :: Trait ( trait_pred) => trait_pred,
10751165 _ => continue ,
@@ -1260,7 +1350,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12601350 item_name : Ident ,
12611351 source : SelfSource < ' tcx > ,
12621352 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+ ) ] ,
12641358 unsatisfied_bounds : bool ,
12651359 ) {
12661360 let mut alt_rcvr_sugg = false ;
@@ -1376,7 +1470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13761470 // this isn't perfect (that is, there are cases when
13771471 // implementing a trait would be legal but is rejected
13781472 // here).
1379- unsatisfied_predicates. iter ( ) . all ( |( p, _) | {
1473+ unsatisfied_predicates. iter ( ) . all ( |( p, _, _ ) | {
13801474 match p. kind ( ) . skip_binder ( ) {
13811475 // Hide traits if they are present in predicates as they can be fixed without
13821476 // having to implement them.
0 commit comments