@@ -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,77 @@ 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 ) {
167+ let tcx = self . infcx . tcx ;
163168 let obligations = self . nominal_obligations ( trait_ref. def_id , trait_ref. substs ) ;
164169
165170 let cause = self . cause ( traits:: MiscObligation ) ;
166171 let param_env = self . param_env ;
167172
168173 if let Elaborate :: All = elaborate {
174+ let trait_assoc_items = tcx. associated_items ( trait_ref. def_id ) ;
175+
169176 let predicates = obligations. iter ( )
170- . map ( |obligation| obligation. predicate . clone ( ) )
171- . collect ( ) ;
172- let implied_obligations = traits:: elaborate_predicates ( self . infcx . tcx , predicates) ;
177+ . map ( |obligation| obligation. predicate . clone ( ) )
178+ . collect ( ) ;
179+ let implied_obligations = traits:: elaborate_predicates ( tcx, predicates) ;
180+ let item_span: Option < Span > = self . item . map ( |i| i. span ) ;
181+ let item = & self . item ;
173182 let implied_obligations = implied_obligations. map ( |pred| {
174- traits:: Obligation :: new ( cause. clone ( ) , param_env, pred)
183+ let mut cause = cause. clone ( ) ;
184+ match & pred {
185+ ty:: Predicate :: Projection ( proj) => {
186+ if let Some ( hir:: ItemKind :: Impl ( .., impl_items) ) = item. map ( |i| & i. kind ) {
187+ let trait_assoc_item = tcx. associated_item ( proj. projection_def_id ( ) ) ;
188+ if let Some ( impl_item) = impl_items. iter ( ) . filter ( |item| {
189+ item. ident == trait_assoc_item. ident
190+ } ) . next ( ) {
191+ cause. span = impl_item. span ;
192+ cause. code = traits:: AssocTypeBound (
193+ item_span,
194+ trait_assoc_item. ident . span ,
195+ ) ;
196+ }
197+ }
198+ }
199+ ty:: Predicate :: Trait ( proj) => {
200+ if let (
201+ ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) ,
202+ Some ( hir:: ItemKind :: Impl ( .., impl_items) ) ,
203+ ) = ( & proj. skip_binder ( ) . self_ty ( ) . kind , item. map ( |i| & i. kind ) ) {
204+ if let Some ( ( impl_item, trait_assoc_item) ) = trait_assoc_items. clone ( )
205+ . filter ( |i| i. def_id == * item_def_id)
206+ . next ( )
207+ . and_then ( |trait_assoc_item| impl_items. iter ( )
208+ . filter ( |i| i. ident == trait_assoc_item. ident )
209+ . next ( )
210+ . map ( |impl_item| ( impl_item, trait_assoc_item) ) )
211+ {
212+ cause. span = impl_item. span ;
213+ cause. code = traits:: AssocTypeBound (
214+ item_span,
215+ trait_assoc_item. ident . span ,
216+ ) ;
217+ }
218+ }
219+ }
220+ _ => { }
221+ }
222+ traits:: Obligation :: new ( cause, param_env, pred)
175223 } ) ;
176224 self . out . extend ( implied_obligations) ;
177225 }
178226
179227 self . out . extend ( obligations) ;
180228
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) ) ) ) ;
229+ self . out . extend ( trait_ref. substs . types ( )
230+ . filter ( |ty| !ty. has_escaping_bound_vars ( ) )
231+ . map ( |ty| traits:: Obligation :: new (
232+ cause. clone ( ) ,
233+ param_env,
234+ ty:: Predicate :: WellFormed ( ty) ,
235+ ) ) ) ;
187236 }
188237
189238 /// Pushes the obligations required for `trait_ref::Item` to be WF
0 commit comments