@@ -552,7 +552,7 @@ impl<T> Trait<T> for X {
552552 continue ;
553553 }
554554
555- if self . constrain_associated_type_structured_suggestion (
555+ if self . constrain_generic_bound_associated_type_structured_suggestion (
556556 db,
557557 & trait_ref,
558558 pred. bounds ,
@@ -569,7 +569,7 @@ impl<T> Trait<T> for X {
569569 == Some ( def_id)
570570 {
571571 // 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 (
573573 db,
574574 & trait_ref,
575575 param. bounds ,
@@ -629,15 +629,16 @@ impl<T> Trait<T> for X {
629629 | ObligationCauseCode :: CompareImplTypeObligation { .. }
630630 | ObligationCauseCode :: CompareImplConstObligation
631631 ) ;
632+ let assoc = self . associated_item ( proj_ty. item_def_id ) ;
632633 if !callable_scope || impl_comparison {
633634 // We do not want to suggest calling functions when the reason of the
634635 // type error is a comparison of an `impl` with its `trait` or when the
635636 // scope is outside of a `Body`.
636637 } else {
637- let assoc = self . associated_item ( proj_ty. item_def_id ) ;
638638 let items = self . associated_items ( assoc. container . id ( ) ) ;
639639 // Find all the methods in the trait that could be called to construct the
640640 // expected associated type.
641+ // FIXME: consider suggesting the use of associated `const`s.
641642 let methods: Vec < ( Span , String ) > = items
642643 . items
643644 . iter ( )
@@ -739,6 +740,18 @@ impl<T> Trait<T> for X {
739740 _ => { }
740741 }
741742 }
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+
742755 if !suggested && !impl_comparison {
743756 // Generic suggestion when we can't be more specific.
744757 if callable_scope {
@@ -771,7 +784,7 @@ fn foo(&self) -> Self::T { String::new() }
771784 }
772785 }
773786
774- fn constrain_associated_type_structured_suggestion (
787+ fn constrain_generic_bound_associated_type_structured_suggestion (
775788 & self ,
776789 db : & mut DiagnosticBuilder < ' _ > ,
777790 trait_ref : & ty:: TraitRef < ' tcx > ,
@@ -785,28 +798,41 @@ fn foo(&self) -> Self::T { String::new() }
785798 match bound {
786799 hir:: GenericBound :: Trait ( ptr, hir:: TraitBoundModifier :: None ) => {
787800 // 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 ;
805807 }
806808 }
807809 _ => { }
808810 }
809811 }
810812 false
811813 }
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+ }
812838}
0 commit comments