1
1
use crate :: infer:: InferCtxt ;
2
2
use crate :: opaque_types:: required_region_bounds;
3
- use crate :: traits:: { self , AssocTypeBoundData } ;
3
+ use crate :: traits;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def_id:: DefId ;
6
6
use rustc_hir:: lang_items;
7
7
use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
8
8
use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable , WithConstness } ;
9
- use rustc_span:: symbol:: { kw, Ident } ;
10
9
use rustc_span:: Span ;
11
10
use std:: rc:: Rc ;
12
11
@@ -143,137 +142,57 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
143
142
pred : & ty:: Predicate < ' _ > ,
144
143
mut trait_assoc_items : impl Iterator < Item = ty:: AssocItem > ,
145
144
) {
146
- let trait_item =
147
- tcx. hir ( ) . as_local_hir_id ( trait_ref. def_id ) . and_then ( |trait_id| tcx. hir ( ) . find ( trait_id) ) ;
148
- let ( trait_name, trait_generics) = match trait_item {
149
- Some ( hir:: Node :: Item ( hir:: Item {
150
- ident,
151
- kind : hir:: ItemKind :: Trait ( .., generics, _, _) ,
152
- ..
153
- } ) )
154
- | Some ( hir:: Node :: Item ( hir:: Item {
155
- ident,
156
- kind : hir:: ItemKind :: TraitAlias ( generics, _) ,
157
- ..
158
- } ) ) => ( Some ( ident) , Some ( generics) ) ,
159
- _ => ( None , None ) ,
145
+ debug ! (
146
+ "extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}" ,
147
+ trait_ref, item, cause, pred
148
+ ) ;
149
+ let items = match item {
150
+ Some ( hir:: Item { kind : hir:: ItemKind :: Impl { items, .. } , .. } ) => items,
151
+ _ => return ,
160
152
} ;
161
-
162
- let item_span = item. map ( |i| tcx. sess . source_map ( ) . guess_head_span ( i. span ) ) ;
153
+ let fix_span =
154
+ |impl_item_ref : & hir:: ImplItemRef < ' _ > | match tcx. hir ( ) . impl_item ( impl_item_ref. id ) . kind {
155
+ hir:: ImplItemKind :: Const ( ty, _) | hir:: ImplItemKind :: TyAlias ( ty) => ty. span ,
156
+ _ => impl_item_ref. span ,
157
+ } ;
163
158
match pred {
164
159
ty:: Predicate :: Projection ( proj) => {
165
160
// The obligation comes not from the current `impl` nor the `trait` being
166
161
// implemented, but rather from a "second order" obligation, like in
167
- // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`:
168
- //
169
- // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
170
- // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
171
- // |
172
- // LL | type Ok;
173
- // | -- associated type defined here
174
- // ...
175
- // LL | impl Bar for Foo {
176
- // | ---------------- in this `impl` item
177
- // LL | type Ok = ();
178
- // | ^^^^^^^^^^^^^ expected `u32`, found `()`
179
- // |
180
- // = note: expected type `u32`
181
- // found type `()`
182
- //
183
- // FIXME: we would want to point a span to all places that contributed to this
184
- // obligation. In the case above, it should be closer to:
185
- //
186
- // error[E0271]: type mismatch resolving `<Foo2 as Bar2>::Ok == ()`
187
- // --> $DIR/point-at-type-on-obligation-failure.rs:13:5
188
- // |
189
- // LL | type Ok;
190
- // | -- associated type defined here
191
- // LL | type Sibling: Bar2<Ok=Self::Ok>;
192
- // | -------------------------------- obligation set here
193
- // ...
194
- // LL | impl Bar for Foo {
195
- // | ---------------- in this `impl` item
196
- // LL | type Ok = ();
197
- // | ^^^^^^^^^^^^^ expected `u32`, found `()`
198
- // ...
199
- // LL | impl Bar2 for Foo2 {
200
- // | ---------------- in this `impl` item
201
- // LL | type Ok = u32;
202
- // | -------------- obligation set here
203
- // |
204
- // = note: expected type `u32`
205
- // found type `()`
206
- if let Some ( hir:: ItemKind :: Impl { items, .. } ) = item. map ( |i| & i. kind ) {
207
- let trait_assoc_item = tcx. associated_item ( proj. projection_def_id ( ) ) ;
208
- if let Some ( impl_item) =
209
- items. iter ( ) . find ( |item| item. ident == trait_assoc_item. ident )
210
- {
211
- cause. span = impl_item. span ;
212
- cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
213
- impl_span : item_span,
214
- original : trait_assoc_item. ident . span ,
215
- bounds : vec ! [ ] ,
216
- } ) ) ;
162
+ // `src/test/ui/associated-types/point-at-type-on-obligation-failure.rs`.
163
+ let trait_assoc_item = tcx. associated_item ( proj. projection_def_id ( ) ) ;
164
+ if let Some ( impl_item_span) =
165
+ items. iter ( ) . find ( |item| item. ident == trait_assoc_item. ident ) . map ( fix_span)
166
+ {
167
+ cause. span = impl_item_span;
168
+ } else {
169
+ let kind = & proj. ty ( ) . skip_binder ( ) . kind ;
170
+ if let ty:: Projection ( projection_ty) = kind {
171
+ // This happens when an associated type has a projection coming from another
172
+ // associated type. See `traits-assoc-type-in-supertrait-bad.rs`.
173
+ let trait_assoc_item = tcx. associated_item ( projection_ty. item_def_id ) ;
174
+ if let Some ( impl_item_span) =
175
+ items. iter ( ) . find ( |item| item. ident == trait_assoc_item. ident ) . map ( fix_span)
176
+ {
177
+ cause. span = impl_item_span;
178
+ }
217
179
}
218
180
}
219
181
}
220
- ty:: Predicate :: Trait ( proj, _) => {
221
- // An associated item obligation born out of the `trait` failed to be met.
222
- // Point at the `impl` that failed the obligation, the associated item that
223
- // needed to meet the obligation, and the definition of that associated item,
224
- // which should hold the obligation in most cases. An example can be seen in
225
- // `src/test/ui/associated-types/point-at-type-on-obligation-failure-2.rs`:
226
- //
227
- // error[E0277]: the trait bound `bool: Bar` is not satisfied
228
- // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
229
- // |
230
- // LL | type Assoc: Bar;
231
- // | ----- associated type defined here
232
- // ...
233
- // LL | impl Foo for () {
234
- // | --------------- in this `impl` item
235
- // LL | type Assoc = bool;
236
- // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
237
- //
238
- // If the obligation comes from the where clause in the `trait`, we point at it:
239
- //
240
- // error[E0277]: the trait bound `bool: Bar` is not satisfied
241
- // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
242
- // |
243
- // | trait Foo where <Self as Foo>>::Assoc: Bar {
244
- // | -------------------------- restricted in this bound
245
- // LL | type Assoc;
246
- // | ----- associated type defined here
247
- // ...
248
- // LL | impl Foo for () {
249
- // | --------------- in this `impl` item
250
- // LL | type Assoc = bool;
251
- // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
252
- if let (
253
- ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) ,
254
- Some ( hir:: ItemKind :: Impl { items, .. } ) ,
255
- ) = ( & proj. skip_binder ( ) . self_ty ( ) . kind , item. map ( |i| & i. kind ) )
182
+ ty:: Predicate :: Trait ( pred, _) => {
183
+ // An associated item obligation born out of the `trait` failed to be met. An example
184
+ // can be seen in `ui/associated-types/point-at-type-on-obligation-failure-2.rs`.
185
+ debug ! ( "extended_cause_with_original_assoc_item_obligation trait proj {:?}" , pred) ;
186
+ if let ty:: Projection ( ty:: ProjectionTy { item_def_id, .. } ) =
187
+ & pred. skip_binder ( ) . self_ty ( ) . kind
256
188
{
257
- if let Some ( ( impl_item , trait_assoc_item ) ) = trait_assoc_items
189
+ if let Some ( impl_item_span ) = trait_assoc_items
258
190
. find ( |i| i. def_id == * item_def_id)
259
191
. and_then ( |trait_assoc_item| {
260
- items
261
- . iter ( )
262
- . find ( |i| i. ident == trait_assoc_item. ident )
263
- . map ( |impl_item| ( impl_item, trait_assoc_item) )
192
+ items. iter ( ) . find ( |i| i. ident == trait_assoc_item. ident ) . map ( fix_span)
264
193
} )
265
194
{
266
- let bounds = trait_generics
267
- . map ( |generics| {
268
- get_generic_bound_spans ( & generics, trait_name, trait_assoc_item. ident )
269
- } )
270
- . unwrap_or_else ( Vec :: new) ;
271
- cause. span = impl_item. span ;
272
- cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
273
- impl_span : item_span,
274
- original : trait_assoc_item. ident . span ,
275
- bounds,
276
- } ) ) ;
195
+ cause. span = impl_item_span;
277
196
}
278
197
}
279
198
}
@@ -307,6 +226,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
307
226
let tcx = self . infcx . tcx ;
308
227
let obligations = self . nominal_obligations ( trait_ref. def_id , trait_ref. substs ) ;
309
228
229
+ debug ! ( "compute_trait_ref obligations {:?}" , obligations) ;
310
230
let cause = self . cause ( traits:: MiscObligation ) ;
311
231
let param_env = self . param_env ;
312
232
@@ -315,16 +235,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
315
235
if let Elaborate :: All = elaborate {
316
236
let implied_obligations = traits:: util:: elaborate_obligations ( tcx, obligations. clone ( ) ) ;
317
237
let implied_obligations = implied_obligations. map ( |obligation| {
238
+ debug ! ( "compute_trait_ref implied_obligation {:?}" , obligation) ;
239
+ debug ! ( "compute_trait_ref implied_obligation cause {:?}" , obligation. cause) ;
318
240
let mut cause = cause. clone ( ) ;
319
- let parent_trait_ref = obligation
320
- . predicate
321
- . to_opt_poly_trait_ref ( )
322
- . unwrap_or_else ( || ty:: Binder :: dummy ( * trait_ref) ) ;
323
- let derived_cause = traits:: DerivedObligationCause {
324
- parent_trait_ref,
325
- parent_code : Rc :: new ( obligation. cause . code . clone ( ) ) ,
326
- } ;
327
- cause. code = traits:: ObligationCauseCode :: ImplDerivedObligation ( derived_cause) ;
241
+ if let Some ( parent_trait_ref) = obligation. predicate . to_opt_poly_trait_ref ( ) {
242
+ let derived_cause = traits:: DerivedObligationCause {
243
+ parent_trait_ref,
244
+ parent_code : Rc :: new ( obligation. cause . code . clone ( ) ) ,
245
+ } ;
246
+ cause. code = traits:: ObligationCauseCode :: ImplDerivedObligation ( derived_cause) ;
247
+ }
328
248
extend_cause_with_original_assoc_item_obligation (
329
249
tcx,
330
250
trait_ref,
@@ -333,6 +253,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
333
253
& obligation. predicate ,
334
254
tcx. associated_items ( trait_ref. def_id ) . in_definition_order ( ) . copied ( ) ,
335
255
) ;
256
+ debug ! ( "compute_trait_ref new cause {:?}" , cause) ;
336
257
traits:: Obligation :: new ( cause, param_env, obligation. predicate )
337
258
} ) ;
338
259
self . out . extend ( implied_obligations) ;
@@ -719,53 +640,3 @@ pub fn object_region_bounds<'tcx>(
719
640
720
641
required_region_bounds ( tcx, open_ty, predicates)
721
642
}
722
-
723
- /// Find the span of a generic bound affecting an associated type.
724
- fn get_generic_bound_spans (
725
- generics : & hir:: Generics < ' _ > ,
726
- trait_name : Option < & Ident > ,
727
- assoc_item_name : Ident ,
728
- ) -> Vec < Span > {
729
- let mut bounds = vec ! [ ] ;
730
- for clause in generics. where_clause . predicates . iter ( ) {
731
- if let hir:: WherePredicate :: BoundPredicate ( pred) = clause {
732
- match & pred. bounded_ty . kind {
733
- hir:: TyKind :: Path ( hir:: QPath :: Resolved ( Some ( ty) , path) ) => {
734
- let mut s = path. segments . iter ( ) ;
735
- if let ( a, Some ( b) , None ) = ( s. next ( ) , s. next ( ) , s. next ( ) ) {
736
- if a. map ( |s| & s. ident ) == trait_name
737
- && b. ident == assoc_item_name
738
- && is_self_path ( & ty. kind )
739
- {
740
- // `<Self as Foo>::Bar`
741
- bounds. push ( pred. span ) ;
742
- }
743
- }
744
- }
745
- hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( ty, segment) ) => {
746
- if segment. ident == assoc_item_name {
747
- if is_self_path ( & ty. kind ) {
748
- // `Self::Bar`
749
- bounds. push ( pred. span ) ;
750
- }
751
- }
752
- }
753
- _ => { }
754
- }
755
- }
756
- }
757
- bounds
758
- }
759
-
760
- fn is_self_path ( kind : & hir:: TyKind < ' _ > ) -> bool {
761
- if let hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) = kind {
762
- let mut s = path. segments . iter ( ) ;
763
- if let ( Some ( segment) , None ) = ( s. next ( ) , s. next ( ) ) {
764
- if segment. ident . name == kw:: SelfUpper {
765
- // `type(Self)`
766
- return true ;
767
- }
768
- }
769
- }
770
- false
771
- }
0 commit comments