@@ -628,6 +628,7 @@ impl<T> Trait<T> for X {
628
628
assoc_substs,
629
629
ty,
630
630
msg,
631
+ false ,
631
632
) {
632
633
return true ;
633
634
}
@@ -646,6 +647,7 @@ impl<T> Trait<T> for X {
646
647
assoc_substs,
647
648
ty,
648
649
msg,
650
+ false ,
649
651
) ;
650
652
}
651
653
}
@@ -771,13 +773,24 @@ fn foo(&self) -> Self::T { String::new() }
771
773
) -> bool {
772
774
let assoc = self . associated_item ( proj_ty. item_def_id ) ;
773
775
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 (
775
786
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,
779
791
ty,
780
- & msg,
792
+ msg,
793
+ true ,
781
794
)
782
795
} else {
783
796
false
@@ -899,6 +912,11 @@ fn foo(&self) -> Self::T { String::new() }
899
912
900
913
/// Given a slice of `hir::GenericBound`s, if any of them corresponds to the `trait_ref`
901
914
/// 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.
902
920
fn constrain_generic_bound_associated_type_structured_suggestion (
903
921
self ,
904
922
db : & mut DiagnosticBuilder < ' _ > ,
@@ -908,23 +926,30 @@ fn foo(&self) -> Self::T { String::new() }
908
926
assoc_substs : & [ ty:: GenericArg < ' tcx > ] ,
909
927
ty : Ty < ' tcx > ,
910
928
msg : & str ,
929
+ is_bound_surely_present : bool ,
911
930
) -> bool {
912
931
// 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)
928
953
}
929
954
930
955
/// Given a span corresponding to a bound, provide a structured suggestion to set an
0 commit comments