@@ -628,6 +628,7 @@ impl<T> Trait<T> for X {
628628 assoc_substs,
629629 ty,
630630 msg,
631+ false ,
631632 ) {
632633 return true ;
633634 }
@@ -646,6 +647,7 @@ impl<T> Trait<T> for X {
646647 assoc_substs,
647648 ty,
648649 msg,
650+ false ,
649651 ) ;
650652 }
651653 }
@@ -771,13 +773,24 @@ fn foo(&self) -> Self::T { String::new() }
771773 ) -> bool {
772774 let assoc = self . associated_item ( proj_ty. item_def_id ) ;
773775 if let ty:: Opaque ( def_id, _) = * proj_ty. self_ty ( ) . kind ( ) {
774- self . constrain_associated_type_structured_suggestion (
776+ let opaque_local_def_id = def_id. expect_local ( ) ;
777+ let opaque_hir_id = self . hir ( ) . local_def_id_to_hir_id ( opaque_local_def_id) ;
778+ let opaque_hir_ty = match & self . hir ( ) . expect_item ( opaque_hir_id) . kind {
779+ hir:: ItemKind :: OpaqueTy ( opaque_hir_ty) => opaque_hir_ty,
780+ _ => bug ! ( "The HirId comes from a `ty::Opaque`" ) ,
781+ } ;
782+
783+ let ( trait_ref, assoc_substs) = proj_ty. trait_ref_and_own_substs ( self ) ;
784+
785+ self . constrain_generic_bound_associated_type_structured_suggestion (
775786 db,
776- self . def_span ( def_id) ,
777- & assoc,
778- proj_ty. trait_ref_and_own_substs ( self ) . 1 ,
787+ & trait_ref,
788+ opaque_hir_ty. bounds ,
789+ assoc,
790+ assoc_substs,
779791 ty,
780- & msg,
792+ msg,
793+ true ,
781794 )
782795 } else {
783796 false
@@ -899,6 +912,11 @@ fn foo(&self) -> Self::T { String::new() }
899912
900913 /// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
901914 /// requirement, provide a structured suggestion to constrain it to a given type `ty`.
915+ ///
916+ /// `is_bound_surely_present` indicates whether we know the bound we're looking for is
917+ /// inside `bounds`. If that's the case then we can consider `bounds` containing only one
918+ /// trait bound as the one we're looking for. This can help in cases where the associated
919+ /// type is defined on a supertrait of the one present in the bounds.
902920 fn constrain_generic_bound_associated_type_structured_suggestion (
903921 self ,
904922 db : & mut DiagnosticBuilder < ' _ > ,
@@ -908,23 +926,30 @@ fn foo(&self) -> Self::T { String::new() }
908926 assoc_substs : & [ ty:: GenericArg < ' tcx > ] ,
909927 ty : Ty < ' tcx > ,
910928 msg : & str ,
929+ is_bound_surely_present : bool ,
911930 ) -> bool {
912931 // FIXME: we would want to call `resolve_vars_if_possible` on `ty` before suggesting.
913- bounds. iter ( ) . any ( |bound| match bound {
914- hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: None ) => {
915- // Relate the type param against `T` in `<A as T>::Foo`.
916- ptr. trait_ref . trait_def_id ( ) == Some ( trait_ref. def_id )
917- && self . constrain_associated_type_structured_suggestion (
918- db,
919- ptr. span ,
920- assoc,
921- assoc_substs,
922- ty,
923- msg,
924- )
925- }
926- _ => false ,
927- } )
932+
933+ let trait_bounds = bounds. iter ( ) . filter_map ( |bound| match bound {
934+ hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: None ) => Some ( ptr) ,
935+ _ => None ,
936+ } ) ;
937+
938+ let matching_trait_bounds = trait_bounds
939+ . clone ( )
940+ . filter ( |ptr| ptr. trait_ref . trait_def_id ( ) == Some ( trait_ref. def_id ) )
941+ . collect :: < Vec < _ > > ( ) ;
942+
943+ let span = match & matching_trait_bounds[ ..] {
944+ & [ ptr] => ptr. span ,
945+ & [ ] if is_bound_surely_present => match & trait_bounds. collect :: < Vec < _ > > ( ) [ ..] {
946+ & [ ptr] => ptr. span ,
947+ _ => return false ,
948+ } ,
949+ _ => return false ,
950+ } ;
951+
952+ self . constrain_associated_type_structured_suggestion ( db, span, assoc, assoc_substs, ty, msg)
928953 }
929954
930955 /// Given a span corresponding to a bound, provide a structured suggestion to set an
0 commit comments