@@ -552,7 +552,7 @@ impl<T> Trait<T> for X {
552
552
continue ;
553
553
}
554
554
555
- if self . constrain_associated_type_structured_suggestion (
555
+ if self . constrain_generic_bound_associated_type_structured_suggestion (
556
556
db,
557
557
& trait_ref,
558
558
pred. bounds ,
@@ -569,7 +569,7 @@ impl<T> Trait<T> for X {
569
569
== Some ( def_id)
570
570
{
571
571
// This is type param `A` in `<A as T>::Foo`.
572
- return self . constrain_associated_type_structured_suggestion (
572
+ return self . constrain_generic_bound_associated_type_structured_suggestion (
573
573
db,
574
574
& trait_ref,
575
575
param. bounds ,
@@ -629,15 +629,16 @@ impl<T> Trait<T> for X {
629
629
| ObligationCauseCode :: CompareImplTypeObligation { .. }
630
630
| ObligationCauseCode :: CompareImplConstObligation
631
631
) ;
632
+ let assoc = self . associated_item ( proj_ty. item_def_id ) ;
632
633
if !callable_scope || impl_comparison {
633
634
// We do not want to suggest calling functions when the reason of the
634
635
// type error is a comparison of an `impl` with its `trait` or when the
635
636
// scope is outside of a `Body`.
636
637
} else {
637
- let assoc = self . associated_item ( proj_ty. item_def_id ) ;
638
638
let items = self . associated_items ( assoc. container . id ( ) ) ;
639
639
// Find all the methods in the trait that could be called to construct the
640
640
// expected associated type.
641
+ // FIXME: consider suggesting the use of associated `const`s.
641
642
let methods: Vec < ( Span , String ) > = items
642
643
. items
643
644
. iter ( )
@@ -739,6 +740,18 @@ impl<T> Trait<T> for X {
739
740
_ => { }
740
741
}
741
742
}
743
+ if let ty:: Opaque ( def_id, _) = proj_ty. self_ty ( ) . kind {
744
+ // When the expected `impl Trait` is not defined in the current item, it will come from
745
+ // a return type. This can occur when dealing with `TryStream` (#71035).
746
+ suggested |= self . constrain_associated_type_structured_suggestion (
747
+ db,
748
+ self . def_span ( def_id) ,
749
+ & assoc,
750
+ values. found ,
751
+ & msg,
752
+ ) ;
753
+ }
754
+
742
755
if !suggested && !impl_comparison {
743
756
// Generic suggestion when we can't be more specific.
744
757
if callable_scope {
@@ -771,7 +784,7 @@ fn foo(&self) -> Self::T { String::new() }
771
784
}
772
785
}
773
786
774
- fn constrain_associated_type_structured_suggestion (
787
+ fn constrain_generic_bound_associated_type_structured_suggestion (
775
788
& self ,
776
789
db : & mut DiagnosticBuilder < ' _ > ,
777
790
trait_ref : & ty:: TraitRef < ' tcx > ,
@@ -785,28 +798,41 @@ fn foo(&self) -> Self::T { String::new() }
785
798
match bound {
786
799
hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: None ) => {
787
800
// Relate the type param against `T` in `<A as T>::Foo`.
788
- if ptr. trait_ref . trait_def_id ( ) == Some ( trait_ref. def_id ) {
789
- if let Ok ( has_params) = self
790
- . sess
791
- . source_map ( )
792
- . span_to_snippet ( ptr. span )
793
- . map ( |snippet| snippet. ends_with ( '>' ) )
794
- {
795
- let ( span, sugg) = if has_params {
796
- let pos = ptr. span . hi ( ) - BytePos ( 1 ) ;
797
- let span = Span :: new ( pos, pos, ptr. span . ctxt ( ) ) ;
798
- ( span, format ! ( ", {} = {}" , assoc. ident, ty) )
799
- } else {
800
- ( ptr. span . shrink_to_hi ( ) , format ! ( "<{} = {}>" , assoc. ident, ty) )
801
- } ;
802
- db. span_suggestion_verbose ( span, msg, sugg, MaybeIncorrect ) ;
803
- return true ;
804
- }
801
+ if ptr. trait_ref . trait_def_id ( ) == Some ( trait_ref. def_id )
802
+ && self . constrain_associated_type_structured_suggestion (
803
+ db, ptr. span , assoc, ty, msg,
804
+ )
805
+ {
806
+ return true ;
805
807
}
806
808
}
807
809
_ => { }
808
810
}
809
811
}
810
812
false
811
813
}
814
+
815
+ fn constrain_associated_type_structured_suggestion (
816
+ & self ,
817
+ db : & mut DiagnosticBuilder < ' _ > ,
818
+ span : Span ,
819
+ assoc : & ty:: AssocItem ,
820
+ ty : Ty < ' tcx > ,
821
+ msg : & str ,
822
+ ) -> bool {
823
+ if let Ok ( has_params) =
824
+ self . sess . source_map ( ) . span_to_snippet ( span) . map ( |snippet| snippet. ends_with ( '>' ) )
825
+ {
826
+ let ( span, sugg) = if has_params {
827
+ let pos = span. hi ( ) - BytePos ( 1 ) ;
828
+ let span = Span :: new ( pos, pos, span. ctxt ( ) ) ;
829
+ ( span, format ! ( ", {} = {}" , assoc. ident, ty) )
830
+ } else {
831
+ ( span. shrink_to_hi ( ) , format ! ( "<{} = {}>" , assoc. ident, ty) )
832
+ } ;
833
+ db. span_suggestion_verbose ( span, msg, sugg, MaybeIncorrect ) ;
834
+ return true ;
835
+ }
836
+ false
837
+ }
812
838
}
0 commit comments