@@ -223,60 +223,87 @@ enum Elaborate {
223223    None , 
224224} 
225225
226+ /// Points the cause span of a super predicate at the relevant associated type. 
227+ /// 
228+ /// Given a trait impl item: 
229+ /// 
230+ /// ```ignore (incomplete) 
231+ /// impl TargetTrait for TargetType { 
232+ ///    type Assoc = SomeType; 
233+ /// } 
234+ /// ``` 
235+ /// 
236+ /// And a super predicate of `TargetTrait` that has any of the following forms: 
237+ /// 
238+ /// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc` 
239+ /// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType` 
240+ /// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait` 
241+ /// 
242+ /// Replace the span of the cause with the span of the associated item: 
243+ /// 
244+ /// ```ignore (incomplete) 
245+ /// impl TargetTrait for TargetType { 
246+ ///     type Assoc = SomeType; 
247+ /// //               ^^^^^^^^ this span 
248+ /// } 
249+ /// ``` 
250+ /// 
251+ /// Note that bounds that can be expressed as associated item bounds are **not** 
252+ /// super predicates. This means that form 2 and 3 from above are only relevant if 
253+ /// the [`GenericArgsRef`] of the projection type are not its identity arguments. 
226254fn  extend_cause_with_original_assoc_item_obligation < ' tcx > ( 
227255    tcx :  TyCtxt < ' tcx > , 
228-     trait_ref :  ty:: TraitRef < ' tcx > , 
229256    item :  Option < & hir:: Item < ' tcx > > , 
230257    cause :  & mut  traits:: ObligationCause < ' tcx > , 
231258    pred :  ty:: Predicate < ' tcx > , 
232259)  { 
233-     debug ! ( 
234-         "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}" , 
235-         trait_ref,  item,  cause,  pred
236-     ) ; 
260+     debug ! ( ?item,  ?cause,  ?pred,  "extended_cause_with_original_assoc_item_obligation" ) ; 
237261    let  ( items,  impl_def_id)  = match  item { 
238262        Some ( hir:: Item  {  kind :  hir:: ItemKind :: Impl ( impl_) ,  owner_id,  .. } )  => { 
239263            ( impl_. items ,  * owner_id) 
240264        } 
241265        _ => return , 
242266    } ; 
243-     let  fix_span =
244-         |impl_item_ref :  & hir:: ImplItemRef | match  tcx. hir ( ) . impl_item ( impl_item_ref. id ) . kind  { 
245-             hir:: ImplItemKind :: Const ( ty,  _)  | hir:: ImplItemKind :: Type ( ty)  => ty. span , 
246-             _ => impl_item_ref. span , 
247-         } ; 
267+ 
268+     let  ty_to_impl_span = |ty :  Ty < ' _ > | { 
269+         if  let  ty:: Alias ( ty:: Projection ,  projection_ty)  = ty. kind ( ) 
270+             && let  Some ( & impl_item_id)  =
271+                 tcx. impl_item_implementor_ids ( impl_def_id) . get ( & projection_ty. def_id ) 
272+             && let  Some ( impl_item)  =
273+                 items. iter ( ) . find ( |item| item. id . owner_id . to_def_id ( )  == impl_item_id) 
274+         { 
275+             Some ( tcx. hir ( ) . impl_item ( impl_item. id ) . expect_type ( ) . span ) 
276+         }  else  { 
277+             None 
278+         } 
279+     } ; 
248280
249281    // It is fine to skip the binder as we don't care about regions here. 
250282    match  pred. kind ( ) . skip_binder ( )  { 
251283        ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( proj) )  => { 
252-             // The obligation comes not from the current `impl` nor the `trait` being implemented, 
253-             // but rather from a "second order" obligation, where an associated type has a 
254-             // projection coming from another associated type. See 
255-             // `tests/ui/associated-types/point-at-type-on-obligation-failure.rs` and 
256-             // `traits-assoc-type-in-supertrait-bad.rs`. 
257-             if  let  Some ( ty:: Alias ( ty:: Projection ,  projection_ty) )  =
258-                 proj. term . ty ( ) . map ( |ty| ty. kind ( ) ) 
259-                 && let  Some ( & impl_item_id)  =
260-                     tcx. impl_item_implementor_ids ( impl_def_id) . get ( & projection_ty. def_id ) 
261-                 && let  Some ( impl_item_span)  = items
262-                     . iter ( ) 
263-                     . find ( |item| item. id . owner_id . to_def_id ( )  == impl_item_id) 
264-                     . map ( fix_span) 
284+             // Form 1: The obligation comes not from the current `impl` nor the `trait` being 
285+             // implemented, but rather from a "second order" obligation, where an associated 
286+             // type has a projection coming from another associated type. 
287+             // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example. 
288+             if  let  Some ( term_ty)  = proj. term . ty ( ) 
289+                 && let  Some ( impl_item_span)  = ty_to_impl_span ( term_ty) 
265290            { 
266291                cause. span  = impl_item_span; 
267292            } 
293+ 
294+             // Form 2: A projection obligation for an associated item failed to be met. 
295+             // We overwrite the span from above to ensure that a bound like 
296+             // `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same 
297+             // span for both obligations that it is lowered to. 
298+             if  let  Some ( impl_item_span)  = ty_to_impl_span ( proj. self_ty ( ) )  { 
299+                 cause. span  = impl_item_span; 
300+             } 
268301        } 
302+ 
269303        ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( pred) )  => { 
270-             // An associated item obligation born out of the `trait` failed to be met. An example 
271-             // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`. 
304+             // Form 3: A trait obligation for an associated item failed to be met. 
272305            debug ! ( "extended_cause_with_original_assoc_item_obligation trait proj {:?}" ,  pred) ; 
273-             if  let  ty:: Alias ( ty:: Projection ,  ty:: AliasTy  {  def_id,  .. } )  = * pred. self_ty ( ) . kind ( ) 
274-                 && let  Some ( & impl_item_id)  = tcx. impl_item_implementor_ids ( impl_def_id) . get ( & def_id) 
275-                 && let  Some ( impl_item_span)  = items
276-                     . iter ( ) 
277-                     . find ( |item| item. id . owner_id . to_def_id ( )  == impl_item_id) 
278-                     . map ( fix_span) 
279-             { 
306+             if  let  Some ( impl_item_span)  = ty_to_impl_span ( pred. self_ty ( ) )  { 
280307                cause. span  = impl_item_span; 
281308            } 
282309        } 
@@ -355,9 +382,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
355382                    traits:: ObligationCauseCode :: DerivedObligation , 
356383                ) ; 
357384            } 
358-             extend_cause_with_original_assoc_item_obligation ( 
359-                 tcx,  trait_ref,  item,  & mut  cause,  predicate, 
360-             ) ; 
385+             extend_cause_with_original_assoc_item_obligation ( tcx,  item,  & mut  cause,  predicate) ; 
361386            traits:: Obligation :: with_depth ( tcx,  cause,  depth,  param_env,  predicate) 
362387        } ; 
363388
0 commit comments