From 20a83144b2a8dacc2ce2d2b129959c827d58b2ce Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 3 May 2023 19:39:57 +0000
Subject: [PATCH 1/3] Support RTN on associated methods from supertraits

---
 compiler/rustc_hir_analysis/messages.ftl      |  2 +-
 .../rustc_hir_analysis/src/astconv/mod.rs     | 43 +++++++++++++--
 .../src/collect/resolve_bound_vars.rs         | 52 +++++++++++--------
 compiler/rustc_hir_analysis/src/errors.rs     |  2 +-
 compiler/rustc_middle/src/ty/context.rs       |  7 ++-
 .../return-type-notation/missing.rs           |  2 +-
 .../return-type-notation/missing.stderr       |  2 +-
 .../super-method-bound.rs                     | 25 +++++++++
 .../super-method-bound.stderr                 | 11 ++++
 9 files changed, 115 insertions(+), 31 deletions(-)
 create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound.rs
 create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound.stderr

diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index e4f225bdad7..703f168b766 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -192,7 +192,7 @@ hir_analysis_return_type_notation_equality_bound =
     return type notation is not allowed to use type equality
 
 hir_analysis_return_type_notation_missing_method =
-    cannot find associated function `{$assoc_name}` in trait `{$trait_name}`
+    cannot find associated function `{$assoc_name}` for `{$ty_name}`
 
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index def192f6e10..84c55f12887 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1118,11 +1118,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             ) {
                 trait_ref
             } else {
-                return Err(tcx.sess.emit_err(crate::errors::ReturnTypeNotationMissingMethod {
-                    span: binding.span,
-                    trait_name: tcx.item_name(trait_ref.def_id()),
-                    assoc_name: binding.item_name.name,
-                }));
+                self.one_bound_for_assoc_method(
+                    traits::supertraits(tcx, trait_ref),
+                    trait_ref.print_only_trait_path(),
+                    binding.item_name,
+                    path_span,
+                )?
             }
         } else if self.trait_defines_associated_item_named(
             trait_ref.def_id(),
@@ -2057,6 +2058,38 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         Ok(bound)
     }
 
+    #[instrument(level = "debug", skip(self, all_candidates, ty_name), ret)]
+    fn one_bound_for_assoc_method(
+        &self,
+        all_candidates: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
+        ty_name: impl Display,
+        assoc_name: Ident,
+        span: Span,
+    ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
+        let mut matching_candidates = all_candidates.filter(|r| {
+            self.trait_defines_associated_item_named(r.def_id(), ty::AssocKind::Fn, assoc_name)
+        });
+
+        let candidate = match matching_candidates.next() {
+            Some(candidate) => candidate,
+            None => {
+                return Err(self.tcx().sess.emit_err(
+                    crate::errors::ReturnTypeNotationMissingMethod {
+                        span,
+                        ty_name: ty_name.to_string(),
+                        assoc_name: assoc_name.name,
+                    },
+                ));
+            }
+        };
+
+        if let Some(_conflicting_candidate) = matching_candidates.next() {
+            todo!()
+        }
+
+        Ok(candidate)
+    }
+
     // Create a type from a path to an associated type or to an enum variant.
     // For a path `A::B::C::D`, `qself_ty` and `qself_def` are the type and def for `A::B::C`
     // and item_segment is the path segment for `D`. We return a type and a def for
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 2e5d058c6ed..44e4e65730e 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1652,17 +1652,16 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             if binding.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation {
                 let bound_vars = if let Some(type_def_id) = type_def_id
                     && self.tcx.def_kind(type_def_id) == DefKind::Trait
-                    // FIXME(return_type_notation): We could bound supertrait methods.
-                    && let Some(assoc_fn) = self
-                        .tcx
-                        .associated_items(type_def_id)
-                        .find_by_name_and_kind(self.tcx, binding.ident, ty::AssocKind::Fn, type_def_id)
+                    && let Some((mut bound_vars, assoc_fn)) =
+                        BoundVarContext::supertrait_hrtb_vars(
+                            self.tcx,
+                            type_def_id,
+                            binding.ident,
+                            ty::AssocKind::Fn,
+                        )
                 {
-                    self.tcx
-                        .generics_of(assoc_fn.def_id)
-                        .params
-                        .iter()
-                        .map(|param| match param.kind {
+                    bound_vars.extend(self.tcx.generics_of(assoc_fn.def_id).params.iter().map(
+                        |param| match param.kind {
                             ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
                                 ty::BoundRegionKind::BrNamed(param.def_id, param.name),
                             ),
@@ -1670,9 +1669,11 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                                 ty::BoundTyKind::Param(param.def_id, param.name),
                             ),
                             ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
-                        })
-                        .chain(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars())
-                        .collect()
+                        },
+                    ));
+                    bound_vars
+                        .extend(self.tcx.fn_sig(assoc_fn.def_id).subst_identity().bound_vars());
+                    bound_vars
                 } else {
                     self.tcx.sess.delay_span_bug(
                         binding.ident.span,
@@ -1689,8 +1690,13 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                     });
                 });
             } else if let Some(type_def_id) = type_def_id {
-                let bound_vars =
-                    BoundVarContext::supertrait_hrtb_vars(self.tcx, type_def_id, binding.ident);
+                let bound_vars = BoundVarContext::supertrait_hrtb_vars(
+                    self.tcx,
+                    type_def_id,
+                    binding.ident,
+                    ty::AssocKind::Type,
+                )
+                .map(|(bound_vars, _)| bound_vars);
                 self.with(scope, |this| {
                     let scope = Scope::Supertrait {
                         bound_vars: bound_vars.unwrap_or_default(),
@@ -1720,11 +1726,15 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         tcx: TyCtxt<'tcx>,
         def_id: DefId,
         assoc_name: Ident,
-    ) -> Option<Vec<ty::BoundVariableKind>> {
+        assoc_kind: ty::AssocKind,
+    ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
         let trait_defines_associated_type_named = |trait_def_id: DefId| {
-            tcx.associated_items(trait_def_id)
-                .find_by_name_and_kind(tcx, assoc_name, ty::AssocKind::Type, trait_def_id)
-                .is_some()
+            tcx.associated_items(trait_def_id).find_by_name_and_kind(
+                tcx,
+                assoc_name,
+                assoc_kind,
+                trait_def_id,
+            )
         };
 
         use smallvec::{smallvec, SmallVec};
@@ -1742,8 +1752,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 _ => break None,
             }
 
-            if trait_defines_associated_type_named(def_id) {
-                break Some(bound_vars.into_iter().collect());
+            if let Some(assoc_item) = trait_defines_associated_type_named(def_id) {
+                break Some((bound_vars.into_iter().collect(), assoc_item));
             }
             let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 25ad1bed763..48330a94255 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -512,7 +512,7 @@ pub(crate) struct ReturnTypeNotationEqualityBound {
 pub(crate) struct ReturnTypeNotationMissingMethod {
     #[primary_span]
     pub span: Span,
-    pub trait_name: Symbol,
+    pub ty_name: String,
     pub assoc_name: Symbol,
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index a309eaf048d..47972055ae9 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1570,7 +1570,12 @@ impl<'tcx> TyCtxt<'tcx> {
     pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
         self.super_traits_of(trait_def_id).any(|trait_did| {
             self.associated_items(trait_did)
-                .find_by_name_and_kind(self, assoc_name, ty::AssocKind::Type, trait_did)
+                .find_by_name_and_kinds(
+                    self,
+                    assoc_name,
+                    &[ty::AssocKind::Type, ty::AssocKind::Const, ty::AssocKind::Fn],
+                    trait_did,
+                )
                 .is_some()
         })
     }
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
index b84b5a717b7..a52562d78f8 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/missing.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
@@ -8,6 +8,6 @@ trait Trait {
 }
 
 fn bar<T: Trait<methid(): Send>>() {}
-//~^ ERROR cannot find associated function `methid` in trait `Trait`
+//~^ ERROR cannot find associated function `methid` for `Trait`
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
index 954d9f74767..5b1c4cb0b2c 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
@@ -7,7 +7,7 @@ LL | #![feature(return_type_notation, async_fn_in_trait)]
    = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: cannot find associated function `methid` in trait `Trait`
+error: cannot find associated function `methid` for `Trait`
   --> $DIR/missing.rs:10:17
    |
 LL | fn bar<T: Trait<methid(): Send>>() {}
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.rs b/tests/ui/async-await/return-type-notation/super-method-bound.rs
new file mode 100644
index 00000000000..58ea3578db6
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.rs
@@ -0,0 +1,25 @@
+// edition:2021
+// check-pass
+
+#![feature(async_fn_in_trait, return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Super<'a> {
+    async fn test();
+}
+impl Super<'_> for () {
+    async fn test() {}
+}
+
+trait Foo: for<'a> Super<'a> {}
+impl Foo for () {}
+
+fn test<T>()
+where
+    T: Foo<test(): Send>,
+{
+}
+
+fn main() {
+    test::<()>();
+}
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.stderr
new file mode 100644
index 00000000000..ac0668d3c44
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/super-method-bound.rs:4:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+

From fef2f5b815fd9cf48895063e35054e34c31562d9 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 3 May 2023 20:13:32 +0000
Subject: [PATCH 2/3] Rename things to reflect that they're not item specific

---
 compiler/rustc_hir_analysis/src/astconv/mod.rs        |  6 +++---
 compiler/rustc_hir_analysis/src/collect.rs            |  4 ++--
 .../rustc_hir_analysis/src/collect/predicates_of.rs   |  6 +++---
 .../src/collect/resolve_bound_vars.rs                 |  6 +++---
 compiler/rustc_infer/src/traits/util.rs               |  8 ++++----
 compiler/rustc_middle/src/query/mod.rs                |  2 +-
 compiler/rustc_middle/src/ty/context.rs               | 11 +++--------
 compiler/rustc_trait_selection/src/traits/mod.rs      |  2 +-
 8 files changed, 20 insertions(+), 25 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 84c55f12887..7880a248cb0 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1040,7 +1040,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
     /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type
     /// named `assoc_name` into ty::Bounds. Ignore the rest.
-    pub(crate) fn compute_bounds_that_match_assoc_type(
+    pub(crate) fn compute_bounds_that_match_assoc_item(
         &self,
         param_ty: Ty<'tcx>,
         ast_bounds: &[hir::GenericBound<'_>],
@@ -1051,7 +1051,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         for ast_bound in ast_bounds {
             if let Some(trait_ref) = ast_bound.trait_ref()
                 && let Some(trait_did) = trait_ref.trait_def_id()
-                && self.tcx().trait_may_define_assoc_type(trait_did, assoc_name)
+                && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
             {
                 result.push(ast_bound.clone());
             }
@@ -1923,7 +1923,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let param_name = tcx.hir().ty_param_name(ty_param_def_id);
         self.one_bound_for_assoc_type(
             || {
-                traits::transitive_bounds_that_define_assoc_type(
+                traits::transitive_bounds_that_define_assoc_item(
                     tcx,
                     predicates.iter().filter_map(|(p, _)| {
                         Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index 41547dd2a75..b65817ee95e 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -64,8 +64,8 @@ pub fn provide(providers: &mut Providers) {
         explicit_predicates_of: predicates_of::explicit_predicates_of,
         super_predicates_of: predicates_of::super_predicates_of,
         implied_predicates_of: predicates_of::implied_predicates_of,
-        super_predicates_that_define_assoc_type:
-            predicates_of::super_predicates_that_define_assoc_type,
+        super_predicates_that_define_assoc_item:
+            predicates_of::super_predicates_that_define_assoc_item,
         trait_explicit_predicates_and_bounds: predicates_of::trait_explicit_predicates_and_bounds,
         type_param_predicates: predicates_of::type_param_predicates,
         trait_def,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 83470342a76..6c06957d1ee 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -565,7 +565,7 @@ pub(super) fn super_predicates_of(
     implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
 }
 
-pub(super) fn super_predicates_that_define_assoc_type(
+pub(super) fn super_predicates_that_define_assoc_item(
     tcx: TyCtxt<'_>,
     (trait_def_id, assoc_name): (DefId, Ident),
 ) -> ty::GenericPredicates<'_> {
@@ -640,7 +640,7 @@ pub(super) fn implied_predicates_with_filter(
         ),
         PredicateFilter::SelfThatDefines(assoc_name) => (
             // Convert the bounds that follow the colon (or equal) that reference the associated name
-            icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
+            icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name),
             // Include where clause bounds for `Self` that reference the associated name
             icx.type_parameter_bounds_in_generics(
                 generics,
@@ -819,7 +819,7 @@ impl<'tcx> ItemCtxt<'tcx> {
             hir::GenericBound::Trait(poly_trait_ref, _) => {
                 let trait_ref = &poly_trait_ref.trait_ref;
                 if let Some(trait_did) = trait_ref.trait_def_id() {
-                    self.tcx.trait_may_define_assoc_type(trait_did, assoc_name)
+                    self.tcx.trait_may_define_assoc_item(trait_did, assoc_name)
                 } else {
                     false
                 }
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 44e4e65730e..ab0dd01ce3a 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -1728,7 +1728,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         assoc_name: Ident,
         assoc_kind: ty::AssocKind,
     ) -> Option<(Vec<ty::BoundVariableKind>, &'tcx ty::AssocItem)> {
-        let trait_defines_associated_type_named = |trait_def_id: DefId| {
+        let trait_defines_associated_item_named = |trait_def_id: DefId| {
             tcx.associated_items(trait_def_id).find_by_name_and_kind(
                 tcx,
                 assoc_name,
@@ -1752,10 +1752,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
                 _ => break None,
             }
 
-            if let Some(assoc_item) = trait_defines_associated_type_named(def_id) {
+            if let Some(assoc_item) = trait_defines_associated_item_named(def_id) {
                 break Some((bound_vars.into_iter().collect(), assoc_item));
             }
-            let predicates = tcx.super_predicates_that_define_assoc_type((def_id, assoc_name));
+            let predicates = tcx.super_predicates_that_define_assoc_item((def_id, assoc_name));
             let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| {
                 let bound_predicate = pred.kind();
                 match bound_predicate.skip_binder() {
diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs
index ef01d5d513b..1acefcef3b4 100644
--- a/compiler/rustc_infer/src/traits/util.rs
+++ b/compiler/rustc_infer/src/traits/util.rs
@@ -376,11 +376,11 @@ pub fn transitive_bounds<'tcx>(
 }
 
 /// A specialized variant of `elaborate` that only elaborates trait references that may
-/// define the given associated type `assoc_name`. It uses the
-/// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that
+/// define the given associated item with the name `assoc_name`. It uses the
+/// `super_predicates_that_define_assoc_item` query to avoid enumerating super-predicates that
 /// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
 /// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
-pub fn transitive_bounds_that_define_assoc_type<'tcx>(
+pub fn transitive_bounds_that_define_assoc_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     bounds: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
     assoc_name: Ident,
@@ -393,7 +393,7 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
             let anon_trait_ref = tcx.anonymize_bound_vars(trait_ref);
             if visited.insert(anon_trait_ref) {
                 let super_predicates =
-                    tcx.super_predicates_that_define_assoc_type((trait_ref.def_id(), assoc_name));
+                    tcx.super_predicates_that_define_assoc_item((trait_ref.def_id(), assoc_name));
                 for (super_predicate, _) in super_predicates.predicates {
                     let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
                     if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index be2657d25a6..b425c7600ac 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -569,7 +569,7 @@ rustc_queries! {
     /// returns the full set of predicates. If `Some<Ident>`, then the query returns only the
     /// subset of super-predicates that reference traits that define the given associated type.
     /// This is used to avoid cycles in resolving types like `T::Item`.
-    query super_predicates_that_define_assoc_type(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
+    query super_predicates_that_define_assoc_item(key: (DefId, rustc_span::symbol::Ident)) -> ty::GenericPredicates<'tcx> {
         desc { |tcx| "computing the super traits of `{}` with associated type name `{}`",
             tcx.def_path_str(key.0),
             key.1
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 47972055ae9..d57451a8b71 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1567,16 +1567,11 @@ impl<'tcx> TyCtxt<'tcx> {
 
     /// Given the def_id of a Trait `trait_def_id` and the name of an associated item `assoc_name`
     /// returns true if the `trait_def_id` defines an associated item of name `assoc_name`.
-    pub fn trait_may_define_assoc_type(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
+    pub fn trait_may_define_assoc_item(self, trait_def_id: DefId, assoc_name: Ident) -> bool {
         self.super_traits_of(trait_def_id).any(|trait_did| {
             self.associated_items(trait_did)
-                .find_by_name_and_kinds(
-                    self,
-                    assoc_name,
-                    &[ty::AssocKind::Type, ty::AssocKind::Const, ty::AssocKind::Fn],
-                    trait_did,
-                )
-                .is_some()
+                .filter_by_name_unhygienic(assoc_name.name)
+                .any(|item| self.hygienic_eq(assoc_name, item.ident(self), trait_did))
         })
     }
 
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 0e8c74a6765..25529f18545 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -62,7 +62,7 @@ pub use self::util::elaborate;
 pub use self::util::{expand_trait_aliases, TraitAliasExpander};
 pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices};
 pub use self::util::{
-    supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_type,
+    supertrait_def_ids, supertraits, transitive_bounds, transitive_bounds_that_define_assoc_item,
     SupertraitDefIds,
 };
 

From 76802e31a131d2ac5933b8283a292735b6ab8366 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 3 May 2023 21:09:50 +0000
Subject: [PATCH 3/3] Error message for ambiguous RTN from super bounds

---
 compiler/rustc_hir_analysis/messages.ftl      |  4 +++
 .../rustc_hir_analysis/src/astconv/mod.rs     | 12 +++++--
 compiler/rustc_hir_analysis/src/errors.rs     | 14 +++++++-
 compiler/rustc_middle/src/ty/print/pretty.rs  |  6 ++++
 .../super-method-bound-ambig.rs               | 32 +++++++++++++++++++
 .../super-method-bound-ambig.stderr           | 19 +++++++++++
 6 files changed, 84 insertions(+), 3 deletions(-)
 create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
 create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr

diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 703f168b766..2035b256daa 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -194,6 +194,10 @@ hir_analysis_return_type_notation_equality_bound =
 hir_analysis_return_type_notation_missing_method =
     cannot find associated function `{$assoc_name}` for `{$ty_name}`
 
+hir_analysis_return_type_notation_conflicting_bound =
+    ambiguous associated function `{$assoc_name}` for `{$ty_name}`
+    .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}`
+
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
 
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 7880a248cb0..9abb71d8b1a 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2083,8 +2083,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             }
         };
 
-        if let Some(_conflicting_candidate) = matching_candidates.next() {
-            todo!()
+        if let Some(conflicting_candidate) = matching_candidates.next() {
+            return Err(self.tcx().sess.emit_err(
+                crate::errors::ReturnTypeNotationConflictingBound {
+                    span,
+                    ty_name: ty_name.to_string(),
+                    assoc_name: assoc_name.name,
+                    first_bound: candidate.print_only_trait_path(),
+                    second_bound: conflicting_candidate.print_only_trait_path(),
+                },
+            ));
         }
 
         Ok(candidate)
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 48330a94255..32c66b16fb9 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     MultiSpan,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
-use rustc_middle::ty::Ty;
+use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(Diagnostic)]
@@ -516,6 +516,18 @@ pub(crate) struct ReturnTypeNotationMissingMethod {
     pub assoc_name: Symbol,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_return_type_notation_conflicting_bound)]
+#[note]
+pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> {
+    #[primary_span]
+    pub span: Span,
+    pub ty_name: String,
+    pub assoc_name: Symbol,
+    pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+    pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")]
 pub(crate) struct PlaceholderNotAllowedItemSignatures {
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2aced27f7bb..32403d9a5e6 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2633,6 +2633,12 @@ macro_rules! define_print_and_forward_display {
 #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
 
+impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> {
+    fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> {
+        self.to_string().into_diagnostic_arg()
+    }
+}
+
 impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Display::fmt(self, f)
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
new file mode 100644
index 00000000000..028e526b5f5
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
@@ -0,0 +1,32 @@
+// edition:2021
+
+#![feature(async_fn_in_trait, return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Super1<'a> {
+    async fn test();
+}
+impl Super1<'_> for () {
+    async fn test() {}
+}
+
+trait Super2 {
+    async fn test();
+}
+impl Super2 for () {
+    async fn test() {}
+}
+
+trait Foo: for<'a> Super1<'a> + Super2 {}
+impl Foo for () {}
+
+fn test<T>()
+where
+    T: Foo<test(): Send>,
+    //~^ ERROR ambiguous associated function `test` for `Foo`
+{
+}
+
+fn main() {
+    test::<()>();
+}
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr
new file mode 100644
index 00000000000..5bc8dbde4bc
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr
@@ -0,0 +1,19 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/super-method-bound-ambig.rs:3:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: ambiguous associated function `test` for `Foo`
+  --> $DIR/super-method-bound-ambig.rs:25:12
+   |
+LL |     T: Foo<test(): Send>,
+   |            ^^^^^^^^^^^^
+   |
+   = note: `test` is declared in two supertraits: `Super2` and `Super1<'a>`
+
+error: aborting due to previous error; 1 warning emitted
+