@@ -22,11 +22,14 @@ pub fn obligations<'a, 'tcx>(
2222 ty : Ty < ' tcx > ,
2323 span : Span ,
2424) -> Option < Vec < traits:: PredicateObligation < ' tcx > > > {
25- let mut wf = WfPredicates { infcx,
26- param_env,
27- body_id,
28- span,
29- out : vec ! [ ] } ;
25+ let mut wf = WfPredicates {
26+ infcx,
27+ param_env,
28+ body_id,
29+ span,
30+ out : vec ! [ ] ,
31+ item : None ,
32+ } ;
3033 if wf. compute ( ty) {
3134 debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
3235 let result = wf. normalize ( ) ;
@@ -47,8 +50,9 @@ pub fn trait_obligations<'a, 'tcx>(
4750 body_id : hir:: HirId ,
4851 trait_ref : & ty:: TraitRef < ' tcx > ,
4952 span : Span ,
53+ item : Option < & ' tcx hir:: Item > ,
5054) -> Vec < traits:: PredicateObligation < ' tcx > > {
51- let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] } ;
55+ let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item } ;
5256 wf. compute_trait_ref ( trait_ref, Elaborate :: All ) ;
5357 wf. normalize ( )
5458}
@@ -60,7 +64,7 @@ pub fn predicate_obligations<'a, 'tcx>(
6064 predicate : & ty:: Predicate < ' tcx > ,
6165 span : Span ,
6266) -> Vec < traits:: PredicateObligation < ' tcx > > {
63- let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] } ;
67+ let mut wf = WfPredicates { infcx, param_env, body_id, span, out : vec ! [ ] , item : None } ;
6468
6569 // (*) ok to skip binders, because wf code is prepared for it
6670 match * predicate {
@@ -107,6 +111,7 @@ struct WfPredicates<'a, 'tcx> {
107111 body_id : hir:: HirId ,
108112 span : Span ,
109113 out : Vec < traits:: PredicateObligation < ' tcx > > ,
114+ item : Option < & ' tcx hir:: Item > ,
110115}
111116
112117/// Controls whether we "elaborate" supertraits and so forth on the WF
@@ -157,33 +162,54 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
157162 . collect ( )
158163 }
159164
160- /// Pushes the obligations required for `trait_ref` to be WF into
161- /// `self.out`.
165+ /// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
162166 fn compute_trait_ref ( & mut self , trait_ref : & ty:: TraitRef < ' tcx > , elaborate : Elaborate ) {
163167 let obligations = self . nominal_obligations ( trait_ref. def_id , trait_ref. substs ) ;
164-
168+ let assoc_items = self . infcx . tcx . associated_items ( trait_ref . def_id ) ;
165169 let cause = self . cause ( traits:: MiscObligation ) ;
166170 let param_env = self . param_env ;
167171
168172 if let Elaborate :: All = elaborate {
169173 let predicates = obligations. iter ( )
170- . map ( |obligation| obligation. predicate . clone ( ) )
171- . collect ( ) ;
174+ . map ( |obligation| obligation. predicate . clone ( ) )
175+ . collect ( ) ;
172176 let implied_obligations = traits:: elaborate_predicates ( self . infcx . tcx , predicates) ;
177+ let item_span: Option < Span > = self . item . map ( |i| i. span ) ;
178+ let item = & self . item ;
173179 let implied_obligations = implied_obligations. map ( |pred| {
174- traits:: Obligation :: new ( cause. clone ( ) , param_env, pred)
180+ let mut cause = cause. clone ( ) ;
181+ if let ty:: Predicate :: Trait ( proj) = & pred {
182+ if let (
183+ ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) ,
184+ Some ( hir:: ItemKind :: Impl ( .., bounds) ) ,
185+ ) = ( & proj. skip_binder ( ) . self_ty ( ) . kind , item. map ( |i| & i. kind ) ) {
186+ if let Some ( ( bound, assoc_item) ) = assoc_items. clone ( )
187+ . filter ( |i| i. def_id == * item_def_id)
188+ . next ( )
189+ . and_then ( |assoc_item| bounds. iter ( )
190+ . filter ( |b| b. ident == assoc_item. ident )
191+ . next ( )
192+ . map ( |bound| ( bound, assoc_item) ) )
193+ {
194+ cause. span = bound. span ;
195+ cause. code = traits:: AssocTypeBound ( item_span, assoc_item. ident . span ) ;
196+ }
197+ }
198+ }
199+ traits:: Obligation :: new ( cause, param_env, pred)
175200 } ) ;
176201 self . out . extend ( implied_obligations) ;
177202 }
178203
179204 self . out . extend ( obligations) ;
180205
181- self . out . extend (
182- trait_ref. substs . types ( )
183- . filter ( |ty| !ty. has_escaping_bound_vars ( ) )
184- . map ( |ty| traits:: Obligation :: new ( cause. clone ( ) ,
185- param_env,
186- ty:: Predicate :: WellFormed ( ty) ) ) ) ;
206+ self . out . extend ( trait_ref. substs . types ( )
207+ . filter ( |ty| !ty. has_escaping_bound_vars ( ) )
208+ . map ( |ty| traits:: Obligation :: new (
209+ cause. clone ( ) ,
210+ param_env,
211+ ty:: Predicate :: WellFormed ( ty) ,
212+ ) ) ) ;
187213 }
188214
189215 /// Pushes the obligations required for `trait_ref::Item` to be WF
0 commit comments