@@ -134,6 +134,152 @@ enum Elaborate {
134
134
None ,
135
135
}
136
136
137
+ fn extend_cause_with_original_assoc_item_obligation < ' tcx > (
138
+ tcx : TyCtxt < ' tcx > ,
139
+ trait_ref : & ty:: TraitRef < ' tcx > ,
140
+ item : Option < & hir:: Item < ' tcx > > ,
141
+ cause : & mut traits:: ObligationCause < ' tcx > ,
142
+ pred : & ty:: Predicate < ' _ > ,
143
+ mut trait_assoc_items : impl Iterator < Item = ty:: AssocItem > ,
144
+ ) {
145
+ let trait_item =
146
+ tcx. hir ( ) . as_local_hir_id ( trait_ref. def_id ) . and_then ( |trait_id| tcx. hir ( ) . find ( trait_id) ) ;
147
+ let ( trait_name, trait_generics) = match trait_item {
148
+ Some ( hir:: Node :: Item ( hir:: Item {
149
+ ident,
150
+ kind : hir:: ItemKind :: Trait ( .., generics, _, _) ,
151
+ ..
152
+ } ) )
153
+ | Some ( hir:: Node :: Item ( hir:: Item {
154
+ ident,
155
+ kind : hir:: ItemKind :: TraitAlias ( generics, _) ,
156
+ ..
157
+ } ) ) => ( Some ( ident) , Some ( generics) ) ,
158
+ _ => ( None , None ) ,
159
+ } ;
160
+
161
+ let item_span = item. map ( |i| tcx. sess . source_map ( ) . guess_head_span ( i. span ) ) ;
162
+ match pred {
163
+ ty:: Predicate :: Projection ( proj) => {
164
+ // The obligation comes not from the current `impl` nor the `trait` being
165
+ // implemented, but rather from a "second order" obligation, like in
166
+ // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
167
+ //
168
+ // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
169
+ // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
170
+ // |
171
+ // LL | type Ok;
172
+ // | -- associated type defined here
173
+ // ...
174
+ // LL | impl Bar for Foo {
175
+ // | ---------------- in this `impl` item
176
+ // LL | type Ok = ();
177
+ // | ^^^^^^^^^^^^^ expected `u32`, found `()`
178
+ // |
179
+ // = note: expected type `u32`
180
+ // found type `()`
181
+ //
182
+ // FIXME: we would want to point a span to all places that contributed to this
183
+ // obligation. In the case above, it should be closer to:
184
+ //
185
+ // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
186
+ // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
187
+ // |
188
+ // LL | type Ok;
189
+ // | -- associated type defined here
190
+ // LL | type Sibling: Bar2<Ok=Self::Ok>;
191
+ // | -------------------------------- obligation set here
192
+ // ...
193
+ // LL | impl Bar for Foo {
194
+ // | ---------------- in this `impl` item
195
+ // LL | type Ok = ();
196
+ // | ^^^^^^^^^^^^^ expected `u32`, found `()`
197
+ // ...
198
+ // LL | impl Bar2 for Foo2 {
199
+ // | ---------------- in this `impl` item
200
+ // LL | type Ok = u32;
201
+ // | -------------- obligation set here
202
+ // |
203
+ // = note: expected type `u32`
204
+ // found type `()`
205
+ if let Some ( hir:: ItemKind :: Impl { items, .. } ) = item. map ( |i| & i. kind ) {
206
+ let trait_assoc_item = tcx. associated_item ( proj. projection_def_id ( ) ) ;
207
+ if let Some ( impl_item) =
208
+ items. iter ( ) . find ( |item| item. ident == trait_assoc_item. ident )
209
+ {
210
+ cause. span = impl_item. span ;
211
+ cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
212
+ impl_span : item_span,
213
+ original : trait_assoc_item. ident . span ,
214
+ bounds : vec ! [ ] ,
215
+ } ) ) ;
216
+ }
217
+ }
218
+ }
219
+ ty:: Predicate :: Trait ( proj, _) => {
220
+ // An associated item obligation born out of the `trait` failed to be met.
221
+ // Point at the `impl` that failed the obligation, the associated item that
222
+ // needed to meet the obligation, and the definition of that associated item,
223
+ // which should hold the obligation in most cases. An example can be seen in
224
+ // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
225
+ //
226
+ // error[E0277]: the trait bound `bool: Bar` is not satisfied
227
+ // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
228
+ // |
229
+ // LL | type Assoc: Bar;
230
+ // | ----- associated type defined here
231
+ // ...
232
+ // LL | impl Foo for () {
233
+ // | --------------- in this `impl` item
234
+ // LL | type Assoc = bool;
235
+ // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
236
+ //
237
+ // If the obligation comes from the where clause in the `trait`, we point at it:
238
+ //
239
+ // error[E0277]: the trait bound `bool: Bar` is not satisfied
240
+ // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
241
+ // |
242
+ // | trait Foo where <Self as Foo>>::Assoc: Bar {
243
+ // | -------------------------- restricted in this bound
244
+ // LL | type Assoc;
245
+ // | ----- associated type defined here
246
+ // ...
247
+ // LL | impl Foo for () {
248
+ // | --------------- in this `impl` item
249
+ // LL | type Assoc = bool;
250
+ // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
251
+ if let (
252
+ ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) ,
253
+ Some ( hir:: ItemKind :: Impl { items, .. } ) ,
254
+ ) = ( & proj. skip_binder ( ) . self_ty ( ) . kind , item. map ( |i| & i. kind ) )
255
+ {
256
+ if let Some ( ( impl_item, trait_assoc_item) ) = trait_assoc_items
257
+ . find ( |i| i. def_id == * item_def_id)
258
+ . and_then ( |trait_assoc_item| {
259
+ items
260
+ . iter ( )
261
+ . find ( |i| i. ident == trait_assoc_item. ident )
262
+ . map ( |impl_item| ( impl_item, trait_assoc_item) )
263
+ } )
264
+ {
265
+ let bounds = trait_generics
266
+ . map ( |generics| {
267
+ get_generic_bound_spans ( & generics, trait_name, trait_assoc_item. ident )
268
+ } )
269
+ . unwrap_or_else ( Vec :: new) ;
270
+ cause. span = impl_item. span ;
271
+ cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
272
+ impl_span : item_span,
273
+ original : trait_assoc_item. ident . span ,
274
+ bounds,
275
+ } ) ) ;
276
+ }
277
+ }
278
+ }
279
+ _ => { }
280
+ }
281
+ }
282
+
137
283
impl < ' a , ' tcx > WfPredicates < ' a , ' tcx > {
138
284
fn cause ( & mut self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
139
285
traits:: ObligationCause :: new ( self . span , self . body_id , code)
@@ -163,170 +309,20 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
163
309
let cause = self . cause ( traits:: MiscObligation ) ;
164
310
let param_env = self . param_env ;
165
311
166
- let item = & self . item ;
167
- let extend_cause_with_original_assoc_item_obligation =
168
- |cause : & mut traits:: ObligationCause < ' _ > ,
169
- pred : & ty:: Predicate < ' _ > ,
170
- trait_assoc_items : & [ ty:: AssocItem ] | {
171
- let trait_item = tcx
172
- . hir ( )
173
- . as_local_hir_id ( trait_ref. def_id )
174
- . and_then ( |trait_id| tcx. hir ( ) . find ( trait_id) ) ;
175
- let ( trait_name, trait_generics) = match trait_item {
176
- Some ( hir:: Node :: Item ( hir:: Item {
177
- ident,
178
- kind : hir:: ItemKind :: Trait ( .., generics, _, _) ,
179
- ..
180
- } ) )
181
- | Some ( hir:: Node :: Item ( hir:: Item {
182
- ident,
183
- kind : hir:: ItemKind :: TraitAlias ( generics, _) ,
184
- ..
185
- } ) ) => ( Some ( ident) , Some ( generics) ) ,
186
- _ => ( None , None ) ,
187
- } ;
188
-
189
- let item_span = item. map ( |i| tcx. sess . source_map ( ) . guess_head_span ( i. span ) ) ;
190
- match pred {
191
- ty:: Predicate :: Projection ( proj) => {
192
- // The obligation comes not from the current `impl` nor the `trait` being
193
- // implemented, but rather from a "second order" obligation, like in
194
- // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
195
- //
196
- // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
197
- // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
198
- // |
199
- // LL | type Ok;
200
- // | -- associated type defined here
201
- // ...
202
- // LL | impl Bar for Foo {
203
- // | ---------------- in this `impl` item
204
- // LL | type Ok = ();
205
- // | ^^^^^^^^^^^^^ expected `u32`, found `()`
206
- // |
207
- // = note: expected type `u32`
208
- // found type `()`
209
- //
210
- // FIXME: we would want to point a span to all places that contributed to this
211
- // obligation. In the case above, it should be closer to:
212
- //
213
- // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
214
- // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
215
- // |
216
- // LL | type Ok;
217
- // | -- associated type defined here
218
- // LL | type Sibling: Bar2<Ok=Self::Ok>;
219
- // | -------------------------------- obligation set here
220
- // ...
221
- // LL | impl Bar for Foo {
222
- // | ---------------- in this `impl` item
223
- // LL | type Ok = ();
224
- // | ^^^^^^^^^^^^^ expected `u32`, found `()`
225
- // ...
226
- // LL | impl Bar2 for Foo2 {
227
- // | ---------------- in this `impl` item
228
- // LL | type Ok = u32;
229
- // | -------------- obligation set here
230
- // |
231
- // = note: expected type `u32`
232
- // found type `()`
233
- if let Some ( hir:: ItemKind :: Impl { items, .. } ) = item. map ( |i| & i. kind ) {
234
- let trait_assoc_item = tcx. associated_item ( proj. projection_def_id ( ) ) ;
235
- if let Some ( impl_item) =
236
- items. iter ( ) . find ( |item| item. ident == trait_assoc_item. ident )
237
- {
238
- cause. span = impl_item. span ;
239
- cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
240
- impl_span : item_span,
241
- original : trait_assoc_item. ident . span ,
242
- bounds : vec ! [ ] ,
243
- } ) ) ;
244
- }
245
- }
246
- }
247
- ty:: Predicate :: Trait ( proj, _) => {
248
- // An associated item obligation born out of the `trait` failed to be met.
249
- // Point at the `impl` that failed the obligation, the associated item that
250
- // needed to meet the obligation, and the definition of that associated item,
251
- // which should hold the obligation in most cases. An example can be seen in
252
- // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
253
- //
254
- // error[E0277]: the trait bound `bool: Bar` is not satisfied
255
- // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
256
- // |
257
- // LL | type Assoc: Bar;
258
- // | ----- associated type defined here
259
- // ...
260
- // LL | impl Foo for () {
261
- // | --------------- in this `impl` item
262
- // LL | type Assoc = bool;
263
- // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
264
- //
265
- // If the obligation comes from the where clause in the `trait`, we point at it:
266
- //
267
- // error[E0277]: the trait bound `bool: Bar` is not satisfied
268
- // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
269
- // |
270
- // | trait Foo where <Self as Foo>>::Assoc: Bar {
271
- // | -------------------------- restricted in this bound
272
- // LL | type Assoc;
273
- // | ----- associated type defined here
274
- // ...
275
- // LL | impl Foo for () {
276
- // | --------------- in this `impl` item
277
- // LL | type Assoc = bool;
278
- // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
279
- if let (
280
- ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) ,
281
- Some ( hir:: ItemKind :: Impl { items, .. } ) ,
282
- ) = ( & proj. skip_binder ( ) . self_ty ( ) . kind , item. map ( |i| & i. kind ) )
283
- {
284
- if let Some ( ( impl_item, trait_assoc_item) ) = trait_assoc_items
285
- . iter ( )
286
- . find ( |i| i. def_id == * item_def_id)
287
- . and_then ( |trait_assoc_item| {
288
- items
289
- . iter ( )
290
- . find ( |i| i. ident == trait_assoc_item. ident )
291
- . map ( |impl_item| ( impl_item, trait_assoc_item) )
292
- } )
293
- {
294
- let bounds = trait_generics
295
- . map ( |generics| {
296
- get_generic_bound_spans (
297
- & generics,
298
- trait_name,
299
- trait_assoc_item. ident ,
300
- )
301
- } )
302
- . unwrap_or_else ( Vec :: new) ;
303
- cause. span = impl_item. span ;
304
- cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
305
- impl_span : item_span,
306
- original : trait_assoc_item. ident . span ,
307
- bounds,
308
- } ) ) ;
309
- }
310
- }
311
- }
312
- _ => { }
313
- }
314
- } ;
312
+ let item = self . item ;
315
313
316
314
if let Elaborate :: All = elaborate {
317
- // FIXME: Make `extend_cause_with_original_assoc_item_obligation` take an iterator
318
- // instead of a slice.
319
- let trait_assoc_items: Vec < _ > =
320
- tcx. associated_items ( trait_ref. def_id ) . in_definition_order ( ) . copied ( ) . collect ( ) ;
321
-
322
315
let predicates = obligations. iter ( ) . map ( |obligation| obligation. predicate ) . collect ( ) ;
323
316
let implied_obligations = traits:: elaborate_predicates ( tcx, predicates) ;
324
317
let implied_obligations = implied_obligations. map ( |pred| {
325
318
let mut cause = cause. clone ( ) ;
326
319
extend_cause_with_original_assoc_item_obligation (
320
+ tcx,
321
+ trait_ref,
322
+ item,
327
323
& mut cause,
328
324
& pred,
329
- & * trait_assoc_items ,
325
+ tcx . associated_items ( trait_ref . def_id ) . in_definition_order ( ) . copied ( ) ,
330
326
) ;
331
327
traits:: Obligation :: new ( cause, param_env, pred)
332
328
} ) ;
0 commit comments