11use crate :: infer:: InferCtxt ;
22use crate :: opaque_types:: required_region_bounds;
3- use crate :: traits:: { self , AssocTypeBoundData } ;
3+ use crate :: traits;
44use rustc_hir as hir;
55use rustc_hir:: def_id:: DefId ;
66use rustc_hir:: lang_items;
77use rustc_middle:: ty:: subst:: { GenericArgKind , SubstsRef } ;
88use rustc_middle:: ty:: { self , ToPredicate , Ty , TyCtxt , TypeFoldable , WithConstness } ;
9- use rustc_span:: symbol:: { kw, Ident } ;
109use rustc_span:: Span ;
1110use std:: rc:: Rc ;
1211
@@ -143,137 +142,57 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
143142 pred : & ty:: Predicate < ' _ > ,
144143 mut trait_assoc_items : impl Iterator < Item = ty:: AssocItem > ,
145144) {
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 ,
160152 } ;
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+ } ;
163158 match pred {
164159 ty:: Predicate :: Projection ( proj) => {
165160 // The obligation comes not from the current `impl` nor the `trait` being
166161 // 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+ }
217179 }
218180 }
219181 }
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
256188 {
257- if let Some ( ( impl_item , trait_assoc_item ) ) = trait_assoc_items
189+ if let Some ( impl_item_span ) = trait_assoc_items
258190 . find ( |i| i. def_id == * item_def_id)
259191 . 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)
264193 } )
265194 {
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;
277196 }
278197 }
279198 }
@@ -307,6 +226,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
307226 let tcx = self . infcx . tcx ;
308227 let obligations = self . nominal_obligations ( trait_ref. def_id , trait_ref. substs ) ;
309228
229+ debug ! ( "compute_trait_ref obligations {:?}" , obligations) ;
310230 let cause = self . cause ( traits:: MiscObligation ) ;
311231 let param_env = self . param_env ;
312232
@@ -315,16 +235,16 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
315235 if let Elaborate :: All = elaborate {
316236 let implied_obligations = traits:: util:: elaborate_obligations ( tcx, obligations. clone ( ) ) ;
317237 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) ;
318240 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+ }
328248 extend_cause_with_original_assoc_item_obligation (
329249 tcx,
330250 trait_ref,
@@ -333,6 +253,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
333253 & obligation. predicate ,
334254 tcx. associated_items ( trait_ref. def_id ) . in_definition_order ( ) . copied ( ) ,
335255 ) ;
256+ debug ! ( "compute_trait_ref new cause {:?}" , cause) ;
336257 traits:: Obligation :: new ( cause, param_env, obligation. predicate )
337258 } ) ;
338259 self . out . extend ( implied_obligations) ;
@@ -719,53 +640,3 @@ pub fn object_region_bounds<'tcx>(
719640
720641 required_region_bounds ( tcx, open_ty, predicates)
721642}
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