@@ -7,6 +7,7 @@ use crate::autoderef::Autoderef;
77use crate :: infer:: InferCtxt ;
88use crate :: traits:: normalize_projection_type;
99
10+ use rustc_data_structures:: fx:: FxHashSet ;
1011use rustc_data_structures:: stack:: ensure_sufficient_stack;
1112use rustc_errors:: { error_code, struct_span_err, Applicability , DiagnosticBuilder , Style } ;
1213use rustc_hir as hir;
@@ -158,6 +159,7 @@ pub trait InferCtxtExt<'tcx> {
158159 predicate : & T ,
159160 cause_code : & ObligationCauseCode < ' tcx > ,
160161 obligated_types : & mut Vec < & ty:: TyS < ' tcx > > ,
162+ seen_requirements : & mut FxHashSet < DefId > ,
161163 ) where
162164 T : fmt:: Display ;
163165
@@ -1787,6 +1789,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
17871789 & obligation. predicate ,
17881790 next_code. unwrap ( ) ,
17891791 & mut Vec :: new ( ) ,
1792+ & mut Default :: default ( ) ,
17901793 ) ;
17911794 }
17921795
@@ -1796,6 +1799,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
17961799 predicate : & T ,
17971800 cause_code : & ObligationCauseCode < ' tcx > ,
17981801 obligated_types : & mut Vec < & ty:: TyS < ' tcx > > ,
1802+ seen_requirements : & mut FxHashSet < DefId > ,
17991803 ) where
18001804 T : fmt:: Display ,
18011805 {
@@ -2050,25 +2054,52 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20502054 & parent_predicate,
20512055 & data. parent_code ,
20522056 obligated_types,
2057+ seen_requirements,
20532058 )
20542059 } ) ;
20552060 }
20562061 }
20572062 ObligationCauseCode :: ImplDerivedObligation ( ref data) => {
2058- let parent_trait_ref = self . resolve_vars_if_possible ( data. parent_trait_ref ) ;
2063+ let mut parent_trait_ref = self . resolve_vars_if_possible ( data. parent_trait_ref ) ;
2064+ let parent_def_id = parent_trait_ref. def_id ( ) ;
20592065 err. note ( & format ! (
20602066 "required because of the requirements on the impl of `{}` for `{}`" ,
20612067 parent_trait_ref. print_only_trait_path( ) ,
20622068 parent_trait_ref. skip_binder( ) . self_ty( )
20632069 ) ) ;
2064- let parent_predicate = parent_trait_ref. without_const ( ) . to_predicate ( tcx) ;
2070+
2071+ let mut parent_predicate = parent_trait_ref. without_const ( ) . to_predicate ( tcx) ;
2072+ let mut data = data;
2073+ let mut count = 0 ;
2074+ seen_requirements. insert ( parent_def_id) ;
2075+ while let ObligationCauseCode :: ImplDerivedObligation ( child) = & * data. parent_code {
2076+ // Skip redundant recursive obligation notes. See `ui/issue-20413.rs`.
2077+ let child_trait_ref = self . resolve_vars_if_possible ( child. parent_trait_ref ) ;
2078+ let child_def_id = child_trait_ref. def_id ( ) ;
2079+ if seen_requirements. insert ( child_def_id) {
2080+ break ;
2081+ }
2082+ count += 1 ;
2083+ data = child;
2084+ parent_predicate = child_trait_ref. without_const ( ) . to_predicate ( tcx) ;
2085+ parent_trait_ref = child_trait_ref;
2086+ }
2087+ if count > 0 {
2088+ err. note ( & format ! ( "{} redundant requirements hidden" , count) ) ;
2089+ err. note ( & format ! (
2090+ "required because of the requirements on the impl of `{}` for `{}`" ,
2091+ parent_trait_ref. print_only_trait_path( ) ,
2092+ parent_trait_ref. skip_binder( ) . self_ty( )
2093+ ) ) ;
2094+ }
20652095 // #74711: avoid a stack overflow
20662096 ensure_sufficient_stack ( || {
20672097 self . note_obligation_cause_code (
20682098 err,
20692099 & parent_predicate,
20702100 & data. parent_code ,
20712101 obligated_types,
2102+ seen_requirements,
20722103 )
20732104 } ) ;
20742105 }
@@ -2082,20 +2113,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
20822113 & parent_predicate,
20832114 & data. parent_code ,
20842115 obligated_types,
2116+ seen_requirements,
20852117 )
20862118 } ) ;
20872119 }
20882120 ObligationCauseCode :: CompareImplMethodObligation { .. } => {
20892121 err. note ( & format ! (
2090- "the requirement `{}` appears on the impl method \
2091- but not on the corresponding trait method",
2122+ "the requirement `{}` appears on the impl method but not on the corresponding \
2123+ trait method",
20922124 predicate
20932125 ) ) ;
20942126 }
20952127 ObligationCauseCode :: CompareImplTypeObligation { .. } => {
20962128 err. note ( & format ! (
2097- "the requirement `{}` appears on the associated impl type \
2098- but not on the corresponding associated trait type",
2129+ "the requirement `{}` appears on the associated impl type but not on the \
2130+ corresponding associated trait type",
20992131 predicate
21002132 ) ) ;
21012133 }
0 commit comments