@@ -134,6 +134,152 @@ enum Elaborate {
134134 None ,
135135}
136136
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+
137283impl < ' a , ' tcx > WfPredicates < ' a , ' tcx > {
138284 fn cause ( & mut self , code : traits:: ObligationCauseCode < ' tcx > ) -> traits:: ObligationCause < ' tcx > {
139285 traits:: ObligationCause :: new ( self . span , self . body_id , code)
@@ -163,170 +309,20 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
163309 let cause = self . cause ( traits:: MiscObligation ) ;
164310 let param_env = self . param_env ;
165311
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 ;
315313
316314 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-
322315 let predicates = obligations. iter ( ) . map ( |obligation| obligation. predicate ) . collect ( ) ;
323316 let implied_obligations = traits:: elaborate_predicates ( tcx, predicates) ;
324317 let implied_obligations = implied_obligations. map ( |pred| {
325318 let mut cause = cause. clone ( ) ;
326319 extend_cause_with_original_assoc_item_obligation (
320+ tcx,
321+ trait_ref,
322+ item,
327323 & mut cause,
328324 & pred,
329- & * trait_assoc_items ,
325+ tcx . associated_items ( trait_ref . def_id ) . in_definition_order ( ) . copied ( ) ,
330326 ) ;
331327 traits:: Obligation :: new ( cause, param_env, pred)
332328 } ) ;
0 commit comments