@@ -7,6 +7,7 @@ use crate::autoderef::Autoderef;
7
7
use crate :: infer:: InferCtxt ;
8
8
use crate :: traits:: normalize_projection_type;
9
9
10
+ use rustc_data_structures:: fx:: FxHashSet ;
10
11
use rustc_data_structures:: stack:: ensure_sufficient_stack;
11
12
use rustc_errors:: { error_code, struct_span_err, Applicability , DiagnosticBuilder , Style } ;
12
13
use rustc_hir as hir;
@@ -158,6 +159,7 @@ pub trait InferCtxtExt<'tcx> {
158
159
predicate : & T ,
159
160
cause_code : & ObligationCauseCode < ' tcx > ,
160
161
obligated_types : & mut Vec < & ty:: TyS < ' tcx > > ,
162
+ seen_requirements : & mut FxHashSet < DefId > ,
161
163
) where
162
164
T : fmt:: Display ;
163
165
@@ -1787,6 +1789,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1787
1789
& obligation. predicate ,
1788
1790
next_code. unwrap ( ) ,
1789
1791
& mut Vec :: new ( ) ,
1792
+ & mut Default :: default ( ) ,
1790
1793
) ;
1791
1794
}
1792
1795
@@ -1796,6 +1799,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
1796
1799
predicate : & T ,
1797
1800
cause_code : & ObligationCauseCode < ' tcx > ,
1798
1801
obligated_types : & mut Vec < & ty:: TyS < ' tcx > > ,
1802
+ seen_requirements : & mut FxHashSet < DefId > ,
1799
1803
) where
1800
1804
T : fmt:: Display ,
1801
1805
{
@@ -2050,25 +2054,52 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
2050
2054
& parent_predicate,
2051
2055
& data. parent_code ,
2052
2056
obligated_types,
2057
+ seen_requirements,
2053
2058
)
2054
2059
} ) ;
2055
2060
}
2056
2061
}
2057
2062
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 ( ) ;
2059
2065
err. note ( & format ! (
2060
2066
"required because of the requirements on the impl of `{}` for `{}`" ,
2061
2067
parent_trait_ref. print_only_trait_path( ) ,
2062
2068
parent_trait_ref. skip_binder( ) . self_ty( )
2063
2069
) ) ;
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
+ }
2065
2095
// #74711: avoid a stack overflow
2066
2096
ensure_sufficient_stack ( || {
2067
2097
self . note_obligation_cause_code (
2068
2098
err,
2069
2099
& parent_predicate,
2070
2100
& data. parent_code ,
2071
2101
obligated_types,
2102
+ seen_requirements,
2072
2103
)
2073
2104
} ) ;
2074
2105
}
@@ -2082,20 +2113,21 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
2082
2113
& parent_predicate,
2083
2114
& data. parent_code ,
2084
2115
obligated_types,
2116
+ seen_requirements,
2085
2117
)
2086
2118
} ) ;
2087
2119
}
2088
2120
ObligationCauseCode :: CompareImplMethodObligation { .. } => {
2089
2121
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",
2092
2124
predicate
2093
2125
) ) ;
2094
2126
}
2095
2127
ObligationCauseCode :: CompareImplTypeObligation { .. } => {
2096
2128
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",
2099
2131
predicate
2100
2132
) ) ;
2101
2133
}
0 commit comments