@@ -2,9 +2,10 @@ use crate::hir;
22use crate :: hir:: def_id:: DefId ;
33use crate :: infer:: InferCtxt ;
44use crate :: ty:: subst:: SubstsRef ;
5- use crate :: traits;
5+ use crate :: traits:: { self , AssocTypeBoundData } ;
66use crate :: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable } ;
77use std:: iter:: once;
8+ use syntax:: symbol:: { kw, Ident } ;
89use syntax_pos:: Span ;
910use crate :: middle:: lang_items;
1011use crate :: mir:: interpret:: ConstValue ;
@@ -176,6 +177,23 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
176177 pred : & ty:: Predicate < ' _ > ,
177178 trait_assoc_items : ty:: AssocItemsIterator < ' _ > ,
178179 | {
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+
179197 let item_span = item. map( |i| tcx. sess. source_map( ) . def_span( i. span) ) ;
180198 match pred {
181199 ty : : Predicate :: Projection ( proj) => {
@@ -226,10 +244,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
226244 item. ident == trait_assoc_item. ident
227245 } ) . next ( ) {
228246 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+ } ) ) ;
233252 }
234253 }
235254 }
@@ -251,14 +270,13 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
251270 // LL | type Assoc = bool;
252271 // | ^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `bool`
253272 //
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:
256274 //
257275 // error[E0277]: the trait bound `bool: Bar` is not satisfied
258276 // --> $DIR/point-at-type-on-obligation-failure-2.rs:8:5
259277 // |
260278 // | trait Foo where <Self as Foo>>::Assoc: Bar {
261- // | -------------------------- obligation set here
279+ // | -------------------------- restricted in this bound
262280 // LL | type Assoc;
263281 // | ----- associated type defined here
264282 // ...
@@ -278,11 +296,17 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
278296 . next ( )
279297 . map ( |impl_item| ( impl_item, trait_assoc_item) ) )
280298 {
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) ;
281304 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+ } ) ) ;
286310 }
287311 }
288312 }
@@ -666,3 +690,56 @@ pub fn object_region_bounds<'tcx>(
666690
667691 tcx. required_region_bounds ( open_ty, predicates)
668692}
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