@@ -2,9 +2,10 @@ use crate::hir;
2
2
use crate :: hir:: def_id:: DefId ;
3
3
use crate :: infer:: InferCtxt ;
4
4
use crate :: ty:: subst:: SubstsRef ;
5
- use crate :: traits;
5
+ use crate :: traits:: { self , AssocTypeBoundData } ;
6
6
use crate :: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable } ;
7
7
use std:: iter:: once;
8
+ use syntax:: symbol:: { kw, Ident } ;
8
9
use syntax_pos:: Span ;
9
10
use crate :: middle:: lang_items;
10
11
use crate :: mir:: interpret:: ConstValue ;
@@ -176,6 +177,23 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
176
177
pred : & ty:: Predicate < ' _ > ,
177
178
trait_assoc_items : ty:: AssocItemsIterator < ' _ > ,
178
179
| {
180
+ let trait_item = tcx. hir( ) . as_local_hir_id( trait_ref. def_id) . and_then( |trait_id| {
181
+ tcx. hir( ) . find( trait_id)
182
+ } ) ;
183
+ let ( trait_name, trait_generics) = match trait_item {
184
+ Some ( hir:: Node :: Item ( hir:: Item {
185
+ ident,
186
+ kind : hir:: ItemKind :: Trait ( .., generics, _, _) ,
187
+ ..
188
+ } ) ) |
189
+ Some ( hir:: Node :: Item ( hir:: Item {
190
+ ident,
191
+ kind : hir:: ItemKind :: TraitAlias ( generics, _) ,
192
+ ..
193
+ } ) ) => ( Some ( ident) , Some ( generics) ) ,
194
+ _ => ( None , None ) ,
195
+ } ;
196
+
179
197
let item_span = item. map( |i| tcx. sess. source_map( ) . def_span( i. span) ) ;
180
198
match pred {
181
199
ty : : Predicate :: Projection ( proj) => {
@@ -226,10 +244,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
226
244
item. ident == trait_assoc_item. ident
227
245
} ) . next ( ) {
228
246
cause. span = impl_item. span ;
229
- cause. code = traits:: AssocTypeBound (
230
- item_span,
231
- trait_assoc_item. ident . span ,
232
- ) ;
247
+ cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
248
+ impl_span : item_span,
249
+ original : trait_assoc_item. ident . span ,
250
+ bounds : vec ! [ ] ,
251
+ } ) ) ;
233
252
}
234
253
}
235
254
}
@@ -251,14 +270,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
251
270
// LL | type Assoc = bool;
252
271
// | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
253
272
//
254
- // FIXME: if the obligation comes from the where clause in the `trait`, we
255
- // should point at it:
273
+ // If the obligation comes from the where clause in the `trait`, we point at it:
256
274
//
257
275
// error[E0277]: the trait bound `bool: Bar` is not satisfied
258
276
// --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
259
277
// |
260
278
// | trait Foo where <Self as Foo>>::Assoc: Bar {
261
- // | -------------------------- obligation set here
279
+ // | -------------------------- restricted in this bound
262
280
// LL | type Assoc;
263
281
// | ----- associated type defined here
264
282
// ...
@@ -278,11 +296,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
278
296
. next ( )
279
297
. map ( |impl_item| ( impl_item, trait_assoc_item) ) )
280
298
{
299
+ let bounds = trait_generics. map ( |generics| get_generic_bound_spans (
300
+ & generics,
301
+ trait_name,
302
+ trait_assoc_item. ident ,
303
+ ) ) . unwrap_or_else ( Vec :: new) ;
281
304
cause. span = impl_item. span ;
282
- cause. code = traits:: AssocTypeBound (
283
- item_span,
284
- trait_assoc_item. ident . span ,
285
- ) ;
305
+ cause. code = traits:: AssocTypeBound ( Box :: new ( AssocTypeBoundData {
306
+ impl_span : item_span,
307
+ original : trait_assoc_item. ident . span ,
308
+ bounds,
309
+ } ) ) ;
286
310
}
287
311
}
288
312
}
@@ -666,3 +690,56 @@ pub fn object_region_bounds<'tcx>(
666
690
667
691
tcx. required_region_bounds ( open_ty, predicates)
668
692
}
693
+
694
+ /// Find the span of a generic bound affecting an associated type.
695
+ fn get_generic_bound_spans (
696
+ generics : & hir:: Generics ,
697
+ trait_name : Option < & Ident > ,
698
+ assoc_item_name : Ident ,
699
+ ) -> Vec < Span > {
700
+ let mut bounds = vec ! [ ] ;
701
+ for clause in generics. where_clause . predicates . iter ( ) {
702
+ if let hir:: WherePredicate :: BoundPredicate ( pred) = clause {
703
+ match & pred. bounded_ty . kind {
704
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( Some ( ty) , path) ) => {
705
+ let mut s = path. segments . iter ( ) ;
706
+ if let ( a, Some ( b) , None ) = ( s. next ( ) , s. next ( ) , s. next ( ) ) {
707
+ if a. map ( |s| & s. ident ) == trait_name
708
+ && b. ident == assoc_item_name
709
+ && is_self_path ( & ty. kind )
710
+ {
711
+ // `<Self as Foo>::Bar`
712
+ bounds. push ( pred. span ) ;
713
+ }
714
+ }
715
+ }
716
+ hir:: TyKind :: Path ( hir:: QPath :: TypeRelative ( ty, segment) ) => {
717
+ if segment. ident == assoc_item_name {
718
+ if is_self_path ( & ty. kind ) {
719
+ // `Self::Bar`
720
+ bounds. push ( pred. span ) ;
721
+ }
722
+ }
723
+ }
724
+ _ => { }
725
+ }
726
+ }
727
+ }
728
+ bounds
729
+ }
730
+
731
+ fn is_self_path ( kind : & hir:: TyKind ) -> bool {
732
+ match kind {
733
+ hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , path) ) => {
734
+ let mut s = path. segments . iter ( ) ;
735
+ if let ( Some ( segment) , None ) = ( s. next ( ) , s. next ( ) ) {
736
+ if segment. ident . name == kw:: SelfUpper {
737
+ // `type(Self)`
738
+ return true ;
739
+ }
740
+ }
741
+ }
742
+ _ => { }
743
+ }
744
+ false
745
+ }
0 commit comments