@@ -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;
@@ -791,9 +793,88 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
791793 _ => None ,
792794 }
793795 } ;
796+
797+ // Find all the requirements that come from a local `impl` block.
798+ let mut skip_list: FxHashSet < _ > = Default :: default ( ) ;
799+ let mut spanned_predicates: FxHashMap < MultiSpan , _ > = Default :: default ( ) ;
800+ for ( data, p, parent_p) in unsatisfied_predicates
801+ . iter ( )
802+ . filter_map ( |( p, parent, c) | c. as_ref ( ) . map ( |c| ( p, parent, c) ) )
803+ . filter_map ( |( p, parent, c) | match c. code {
804+ ObligationCauseCode :: ImplDerivedObligation ( ref data) => {
805+ Some ( ( data, p, parent) )
806+ }
807+ _ => None ,
808+ } )
809+ {
810+ let parent_trait_ref = data. parent_trait_ref ;
811+ let parent_def_id = parent_trait_ref. def_id ( ) ;
812+ let path = parent_trait_ref. print_only_trait_path ( ) ;
813+ let tr_self_ty = parent_trait_ref. skip_binder ( ) . self_ty ( ) ;
814+ let mut candidates = vec ! [ ] ;
815+ self . tcx . for_each_relevant_impl (
816+ parent_def_id,
817+ parent_trait_ref. self_ty ( ) . skip_binder ( ) ,
818+ |impl_def_id| match self . tcx . hir ( ) . get_if_local ( impl_def_id) {
819+ Some ( Node :: Item ( hir:: Item {
820+ kind : hir:: ItemKind :: Impl ( hir:: Impl { .. } ) ,
821+ ..
822+ } ) ) => {
823+ candidates. push ( impl_def_id) ;
824+ }
825+ _ => { }
826+ } ,
827+ ) ;
828+ if let [ def_id] = & candidates[ ..] {
829+ match self . tcx . hir ( ) . get_if_local ( * def_id) {
830+ Some ( Node :: Item ( hir:: Item {
831+ kind : hir:: ItemKind :: Impl ( hir:: Impl { of_trait, self_ty, .. } ) ,
832+ ..
833+ } ) ) => {
834+ if let Some ( pred) = parent_p {
835+ // Done to add the "doesn't satisfy" `span_label`.
836+ let _ = format_pred ( * pred) ;
837+ }
838+ skip_list. insert ( p) ;
839+ let mut spans = Vec :: with_capacity ( 2 ) ;
840+ if let Some ( trait_ref) = of_trait {
841+ spans. push ( trait_ref. path . span ) ;
842+ }
843+ spans. push ( self_ty. span ) ;
844+ let entry = spanned_predicates. entry ( spans. into ( ) ) ;
845+ entry
846+ . or_insert_with ( || ( path, tr_self_ty, Vec :: new ( ) ) )
847+ . 2
848+ . push ( p) ;
849+ }
850+ _ => { }
851+ }
852+ }
853+ }
854+ for ( span, ( path, self_ty, preds) ) in spanned_predicates {
855+ err. span_note (
856+ span,
857+ & format ! (
858+ "the following trait bounds were not satisfied because of the \
859+ requirements of the implementation of `{}` for `{}`:\n {}",
860+ path,
861+ self_ty,
862+ preds
863+ . into_iter( )
864+ // .map(|pred| format!("{:?}", pred))
865+ . filter_map( |pred| format_pred( * pred) )
866+ . map( |( p, _) | format!( "`{}`" , p) )
867+ . collect:: <Vec <_>>( )
868+ . join( "\n " ) ,
869+ ) ,
870+ ) ;
871+ }
872+
873+ // The requirements that didn't have an `impl` span to show.
794874 let mut bound_list = unsatisfied_predicates
795875 . iter ( )
796- . filter_map ( |( pred, parent_pred) | {
876+ . filter ( |( pred, _, _parent_pred) | !skip_list. contains ( & pred) )
877+ . filter_map ( |( pred, parent_pred, _cause) | {
797878 format_pred ( * pred) . map ( |( p, self_ty) | match parent_pred {
798879 None => format ! ( "`{}`" , & p) ,
799880 Some ( parent_pred) => match format_pred ( * parent_pred) {
@@ -836,7 +917,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
836917 for ( span, msg) in bound_spans. into_iter ( ) {
837918 err. span_label ( span, & msg) ;
838919 }
839- if !bound_list. is_empty ( ) {
920+ if !bound_list. is_empty ( ) || !skip_list . is_empty ( ) {
840921 let bound_list = bound_list
841922 . into_iter ( )
842923 . map ( |( _, path) | path)
@@ -846,9 +927,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
846927 err. set_primary_message ( & format ! (
847928 "the {item_kind} `{item_name}` exists for {actual_prefix} `{ty_str}`, but its trait bounds were not satisfied"
848929 ) ) ;
849- err. note ( & format ! (
850- "the following trait bounds were not satisfied:\n {bound_list}"
851- ) ) ;
930+ if !bound_list. is_empty ( ) {
931+ err. note ( & format ! (
932+ "the following trait bounds were not satisfied:\n {bound_list}"
933+ ) ) ;
934+ }
852935 self . suggest_derive ( & mut err, & unsatisfied_predicates) ;
853936
854937 unsatisfied_bounds = true ;
@@ -1062,18 +1145,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10621145 err. span_note ( spans, & msg) ;
10631146 }
10641147
1065- let preds: Vec < _ > = errors. iter ( ) . map ( |e| ( e. obligation . predicate , None ) ) . collect ( ) ;
1148+ let preds: Vec < _ > = errors
1149+ . iter ( )
1150+ . map ( |e| ( e. obligation . predicate , None , Some ( e. obligation . cause . clone ( ) ) ) )
1151+ . collect ( ) ;
10661152 self . suggest_derive ( err, & preds) ;
10671153 }
10681154
10691155 fn suggest_derive (
10701156 & self ,
10711157 err : & mut DiagnosticBuilder < ' _ > ,
1072- unsatisfied_predicates : & Vec < ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) > ,
1158+ unsatisfied_predicates : & Vec < (
1159+ ty:: Predicate < ' tcx > ,
1160+ Option < ty:: Predicate < ' tcx > > ,
1161+ Option < ObligationCause < ' tcx > > ,
1162+ ) > ,
10731163 ) {
10741164 let mut derives = Vec :: < ( String , Span , String ) > :: new ( ) ;
10751165 let mut traits = Vec :: < Span > :: new ( ) ;
1076- for ( pred, _) in unsatisfied_predicates {
1166+ for ( pred, _, _ ) in unsatisfied_predicates {
10771167 let trait_pred = match pred. kind ( ) . skip_binder ( ) {
10781168 ty:: PredicateKind :: Trait ( trait_pred) => trait_pred,
10791169 _ => continue ,
@@ -1264,7 +1354,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12641354 item_name : Ident ,
12651355 source : SelfSource < ' tcx > ,
12661356 valid_out_of_scope_traits : Vec < DefId > ,
1267- unsatisfied_predicates : & [ ( ty:: Predicate < ' tcx > , Option < ty:: Predicate < ' tcx > > ) ] ,
1357+ unsatisfied_predicates : & [ (
1358+ ty:: Predicate < ' tcx > ,
1359+ Option < ty:: Predicate < ' tcx > > ,
1360+ Option < ObligationCause < ' tcx > > ,
1361+ ) ] ,
12681362 unsatisfied_bounds : bool ,
12691363 ) {
12701364 let mut alt_rcvr_sugg = false ;
@@ -1380,7 +1474,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13801474 // this isn't perfect (that is, there are cases when
13811475 // implementing a trait would be legal but is rejected
13821476 // here).
1383- unsatisfied_predicates. iter ( ) . all ( |( p, _) | {
1477+ unsatisfied_predicates. iter ( ) . all ( |( p, _, _ ) | {
13841478 match p. kind ( ) . skip_binder ( ) {
13851479 // Hide traits if they are present in predicates as they can be fixed without
13861480 // having to implement them.
0 commit comments