@@ -22,11 +22,14 @@ pub fn obligations<'a, 'tcx>(
22
22
ty : Ty < ' tcx > ,
23
23
span : Span ,
24
24
) -> 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
+ } ;
30
33
if wf. compute ( ty) {
31
34
debug ! ( "wf::obligations({:?}, body_id={:?}) = {:?}" , ty, body_id, wf. out) ;
32
35
let result = wf. normalize ( ) ;
@@ -47,8 +50,9 @@ pub fn trait_obligations<'a, 'tcx>(
47
50
body_id : hir:: HirId ,
48
51
trait_ref : & ty:: TraitRef < ' tcx > ,
49
52
span : Span ,
53
+ item : Option < & ' tcx hir:: Item > ,
50
54
) -> 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 } ;
52
56
wf. compute_trait_ref ( trait_ref, Elaborate :: All ) ;
53
57
wf. normalize ( )
54
58
}
@@ -60,7 +64,7 @@ pub fn predicate_obligations<'a, 'tcx>(
60
64
predicate : & ty:: Predicate < ' tcx > ,
61
65
span : Span ,
62
66
) -> 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 } ;
64
68
65
69
// (*) ok to skip binders, because wf code is prepared for it
66
70
match * predicate {
@@ -107,6 +111,7 @@ struct WfPredicates<'a, 'tcx> {
107
111
body_id : hir:: HirId ,
108
112
span : Span ,
109
113
out : Vec < traits:: PredicateObligation < ' tcx > > ,
114
+ item : Option < & ' tcx hir:: Item > ,
110
115
}
111
116
112
117
/// Controls whether we "elaborate" supertraits and so forth on the WF
@@ -157,33 +162,54 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
157
162
. collect ( )
158
163
}
159
164
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`.
162
166
fn compute_trait_ref ( & mut self , trait_ref : & ty:: TraitRef < ' tcx > , elaborate : Elaborate ) {
163
167
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 ) ;
165
169
let cause = self . cause ( traits:: MiscObligation ) ;
166
170
let param_env = self . param_env ;
167
171
168
172
if let Elaborate :: All = elaborate {
169
173
let predicates = obligations. iter ( )
170
- . map ( |obligation| obligation. predicate . clone ( ) )
171
- . collect ( ) ;
174
+ . map ( |obligation| obligation. predicate . clone ( ) )
175
+ . collect ( ) ;
172
176
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 ;
173
179
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)
175
200
} ) ;
176
201
self . out . extend ( implied_obligations) ;
177
202
}
178
203
179
204
self . out . extend ( obligations) ;
180
205
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
+ ) ) ) ;
187
213
}
188
214
189
215
/// Pushes the obligations required for `trait_ref::Item` to be WF
0 commit comments