@@ -82,6 +82,30 @@ pub fn translate_substs<'tcx>(
8282 source_impl : DefId ,
8383 source_substs : SubstsRef < ' tcx > ,
8484 target_node : specialization_graph:: Node ,
85+ ) -> SubstsRef < ' tcx > {
86+ translate_substs_with_cause (
87+ infcx,
88+ param_env,
89+ source_impl,
90+ source_substs,
91+ target_node,
92+ |_, _| ObligationCause :: dummy ( ) ,
93+ )
94+ }
95+
96+ /// Like [translate_substs], but obligations from the parent implementation
97+ /// are registered with the provided `ObligationCause`.
98+ ///
99+ /// This is for reporting *region* errors from those bounds. Type errors should
100+ /// not happen because the specialization graph already checks for those, and
101+ /// will result in an ICE.
102+ pub fn translate_substs_with_cause < ' tcx > (
103+ infcx : & InferCtxt < ' tcx > ,
104+ param_env : ty:: ParamEnv < ' tcx > ,
105+ source_impl : DefId ,
106+ source_substs : SubstsRef < ' tcx > ,
107+ target_node : specialization_graph:: Node ,
108+ cause : impl Fn ( usize , Span ) -> ObligationCause < ' tcx > ,
85109) -> SubstsRef < ' tcx > {
86110 debug ! (
87111 "translate_substs({:?}, {:?}, {:?}, {:?})" ,
@@ -99,14 +123,13 @@ pub fn translate_substs<'tcx>(
99123 return source_substs;
100124 }
101125
102- fulfill_implication ( infcx, param_env, source_trait_ref, target_impl) . unwrap_or_else (
103- |( ) | {
126+ fulfill_implication ( infcx, param_env, source_trait_ref, source_impl , target_impl, cause )
127+ . unwrap_or_else ( |( ) | {
104128 bug ! (
105129 "When translating substitutions from {source_impl:?} to {target_impl:?}, \
106130 the expected specialization failed to hold"
107131 )
108- } ,
109- )
132+ } )
110133 }
111134 specialization_graph:: Node :: Trait ( ..) => source_trait_ref. substs ,
112135 } ;
@@ -153,20 +176,12 @@ pub(super) fn specializes(tcx: TyCtxt<'_>, (impl1_def_id, impl2_def_id): (DefId,
153176
154177 // Create an infcx, taking the predicates of impl1 as assumptions:
155178 let infcx = tcx. infer_ctxt ( ) . build ( ) ;
156- let impl1_trait_ref =
157- match traits:: fully_normalize ( & infcx, ObligationCause :: dummy ( ) , penv, impl1_trait_ref) {
158- Ok ( impl1_trait_ref) => impl1_trait_ref,
159- Err ( _errors) => {
160- tcx. sess . delay_span_bug (
161- tcx. def_span ( impl1_def_id) ,
162- format ! ( "failed to fully normalize {impl1_trait_ref}" ) ,
163- ) ;
164- impl1_trait_ref
165- }
166- } ;
167179
168180 // Attempt to prove that impl2 applies, given all of the above.
169- fulfill_implication ( & infcx, penv, impl1_trait_ref, impl2_def_id) . is_ok ( )
181+ fulfill_implication ( & infcx, penv, impl1_trait_ref, impl1_def_id, impl2_def_id, |_, _| {
182+ ObligationCause :: dummy ( )
183+ } )
184+ . is_ok ( )
170185}
171186
172187/// Attempt to fulfill all obligations of `target_impl` after unification with
@@ -178,23 +193,41 @@ fn fulfill_implication<'tcx>(
178193 infcx : & InferCtxt < ' tcx > ,
179194 param_env : ty:: ParamEnv < ' tcx > ,
180195 source_trait_ref : ty:: TraitRef < ' tcx > ,
196+ source_impl : DefId ,
181197 target_impl : DefId ,
198+ error_cause : impl Fn ( usize , Span ) -> ObligationCause < ' tcx > ,
182199) -> Result < SubstsRef < ' tcx > , ( ) > {
183200 debug ! (
184201 "fulfill_implication({:?}, trait_ref={:?} |- {:?} applies)" ,
185202 param_env, source_trait_ref, target_impl
186203 ) ;
187204
205+ let source_trait_ref = match traits:: fully_normalize (
206+ & infcx,
207+ ObligationCause :: dummy ( ) ,
208+ param_env,
209+ source_trait_ref,
210+ ) {
211+ Ok ( source_trait_ref) => source_trait_ref,
212+ Err ( _errors) => {
213+ infcx. tcx . sess . delay_span_bug (
214+ infcx. tcx . def_span ( source_impl) ,
215+ format ! ( "failed to fully normalize {source_trait_ref}" ) ,
216+ ) ;
217+ source_trait_ref
218+ }
219+ } ;
220+
188221 let source_trait = ImplSubject :: Trait ( source_trait_ref) ;
189222
190223 let selcx = & mut SelectionContext :: new ( & infcx) ;
191224 let target_substs = infcx. fresh_substs_for_item ( DUMMY_SP , target_impl) ;
192225 let ( target_trait, obligations) =
193- util:: impl_subject_and_oblig ( selcx, param_env, target_impl, target_substs) ;
226+ util:: impl_subject_and_oblig ( selcx, param_env, target_impl, target_substs, error_cause ) ;
194227
195228 // do the impls unify? If not, no specialization.
196229 let Ok ( InferOk { obligations : more_obligations, .. } ) =
197- infcx. at ( & ObligationCause :: dummy ( ) , param_env, ) . eq ( DefineOpaqueTypes :: No , source_trait, target_trait)
230+ infcx. at ( & ObligationCause :: dummy ( ) , param_env) . eq ( DefineOpaqueTypes :: No , source_trait, target_trait)
198231 else {
199232 debug ! (
200233 "fulfill_implication: {:?} does not unify with {:?}" ,
0 commit comments