From 21047f1a1c0dc1dd36c5d5a0a85d76234dd4a263 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 11 Sep 2022 07:42:04 +0000
Subject: [PATCH 1/5] Support default-body trait functions with RPITIT

---
 .../rustc_hir_analysis/src/collect/type_of.rs |  5 +-
 .../src/traits/project.rs                     | 46 +++++++++++++++++--
 .../ui/impl-trait/in-trait/default-body.rs    | 15 ++++++
 3 files changed, 60 insertions(+), 6 deletions(-)
 create mode 100644 src/test/ui/impl-trait/in-trait/default-body.rs

diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index f8a62c84910..08a58f4fed8 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -340,10 +340,9 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     ..
                 }) => {
                     if in_trait {
-                        span_bug!(item.span, "impl-trait in trait has no default")
-                    } else {
-                        find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
+                        assert!(tcx.impl_defaultness(owner).has_value());
                     }
+                    find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
                 }
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 085045bcdcb..99953be4885 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -71,7 +71,15 @@ enum ProjectionCandidate<'tcx> {
     /// From an "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
 
-    ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
+    ImplTraitInTrait(ImplTraitInTraitCandidate<'tcx>),
+}
+
+#[derive(PartialEq, Eq, Debug)]
+enum ImplTraitInTraitCandidate<'tcx> {
+    // The `impl Trait` from a trait function's default body
+    Trait,
+    // A concrete type provided from a trait's `impl Trait` from an impl
+    Impl(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
 }
 
 enum ProjectionCandidateSet<'tcx> {
@@ -1317,6 +1325,17 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+        // If we are trying to project an RPITIT with the _identity_ substs,
+        // then we must be within a default trait body.
+        if obligation.predicate.substs
+            == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
+        {
+            candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
+                ImplTraitInTraitCandidate::Trait,
+            ));
+            return;
+        }
+
         let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
         let trait_def_id = tcx.parent(trait_fn_def_id);
         let trait_substs =
@@ -1329,7 +1348,9 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
         let _ =
             selcx.infcx().commit_if_ok(|_| match selcx.select(&obligation.with(trait_predicate)) {
                 Ok(Some(super::ImplSource::UserDefined(data))) => {
-                    candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
+                    candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
+                        ImplTraitInTraitCandidate::Impl(data),
+                    ));
                     Ok(())
                 }
                 Ok(None) => {
@@ -1792,9 +1813,18 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
-        ProjectionCandidate::ImplTraitInTrait(data) => {
+        ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Impl(data)) => {
             confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
         }
+        // If we're projecting an RPITIT for a default trait body, that's just
+        // the same def-id, but as an opaque type (with regular RPIT semantics).
+        ProjectionCandidate::ImplTraitInTrait(ImplTraitInTraitCandidate::Trait) => Progress {
+            term: selcx
+                .tcx()
+                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .into(),
+            obligations: vec![],
+        },
     };
 
     // When checking for cycle during evaluation, we compare predicates with
@@ -2212,6 +2242,16 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
         return Progress { term: tcx.ty_error().into(), obligations };
     }
 
+    // Use the default `impl Trait` for the trait, e.g., for a default trait body
+    if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
+        return Progress {
+            term: tcx
+                .mk_opaque(obligation.predicate.item_def_id, obligation.predicate.substs)
+                .into(),
+            obligations,
+        };
+    }
+
     let impl_fn_def_id = leaf_def.item.def_id;
     let impl_fn_substs = obligation.predicate.substs.rebase_onto(tcx, trait_fn_def_id, data.substs);
 
diff --git a/src/test/ui/impl-trait/in-trait/default-body.rs b/src/test/ui/impl-trait/in-trait/default-body.rs
new file mode 100644
index 00000000000..effc4b1d951
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body.rs
@@ -0,0 +1,15 @@
+// check-pass
+// edition:2021
+
+#![feature(return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait Foo {
+    async fn baz() -> impl Debug {
+        Self::baz().await
+    }
+}
+
+fn main() {}

From 79450360d279f169a40bc8fd55536830f5a939fe Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 5 Oct 2022 04:16:05 +0000
Subject: [PATCH 2/5] Fix test for default body with impl

---
 compiler/rustc_middle/src/ty/sty.rs              |  1 +
 compiler/rustc_privacy/src/lib.rs                | 16 ++++++++++++++--
 .../rustc_trait_selection/src/traits/project.rs  |  5 +++--
 src/test/ui/impl-trait/in-trait/default-body.rs  | 14 ++++++++++----
 4 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 2f6ec836c3c..f8a169fc869 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1160,6 +1160,7 @@ impl<'tcx> ProjectionTy<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
+        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
         let def_id = tcx.parent(self.item_def_id);
         let trait_generics = tcx.generics_of(def_id);
         (
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 841e3ebb2a1..4ec9d0b0852 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -122,8 +122,20 @@ where
         &mut self,
         projection: ty::ProjectionTy<'tcx>,
     ) -> ControlFlow<V::BreakTy> {
-        let (trait_ref, assoc_substs) =
-            projection.trait_ref_and_own_substs(self.def_id_visitor.tcx());
+        let tcx = self.def_id_visitor.tcx();
+        let (trait_ref, assoc_substs) = if tcx.def_kind(projection.item_def_id)
+            != DefKind::ImplTraitPlaceholder
+        {
+            projection.trait_ref_and_own_substs(tcx)
+        } else {
+            // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
+            let def_id = tcx.impl_trait_in_trait_parent(projection.item_def_id);
+            let trait_generics = tcx.generics_of(def_id);
+            (
+                ty::TraitRef { def_id, substs: projection.substs.truncate_to(tcx, trait_generics) },
+                &projection.substs[trait_generics.count()..],
+            )
+        };
         self.visit_trait(trait_ref)?;
         if self.def_id_visitor.shallow() {
             ControlFlow::CONTINUE
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 99953be4885..6a4ea114b40 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1325,10 +1325,11 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
-        // If we are trying to project an RPITIT with the _identity_ substs,
+        // If we are trying to project an RPITIT with trait's default `Self` parameter,
         // then we must be within a default trait body.
-        if obligation.predicate.substs
+        if obligation.predicate.self_ty()
             == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
+                .type_at(0)
         {
             candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
                 ImplTraitInTraitCandidate::Trait,
diff --git a/src/test/ui/impl-trait/in-trait/default-body.rs b/src/test/ui/impl-trait/in-trait/default-body.rs
index effc4b1d951..b0baf5bb10d 100644
--- a/src/test/ui/impl-trait/in-trait/default-body.rs
+++ b/src/test/ui/impl-trait/in-trait/default-body.rs
@@ -1,15 +1,21 @@
 // check-pass
 // edition:2021
 
-#![feature(return_position_impl_trait_in_trait)]
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
 use std::fmt::Debug;
 
 trait Foo {
-    async fn baz() -> impl Debug {
-        Self::baz().await
+    async fn baz(&self) -> &str {
+        ""
     }
 }
 
-fn main() {}
+struct Bar;
+
+impl Foo for Bar {}
+
+fn main() {
+    let _ = Bar.baz();
+}

From 86734b04a7c36da0f84226f687f0da331b7f921f Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Sun, 11 Sep 2022 08:51:25 +0000
Subject: [PATCH 3/5] Bless tests

---
 src/test/ui/async-await/async-trait-fn.rs     |  3 -
 src/test/ui/async-await/async-trait-fn.stderr | 56 ++-----------------
 .../edition-deny-async-fns-2015.rs            |  1 -
 .../edition-deny-async-fns-2015.stderr        | 26 ++-------
 ...021-incompatible-closure-captures-93117.rs |  1 -
 ...incompatible-closure-captures-93117.stderr | 22 ++------
 6 files changed, 14 insertions(+), 95 deletions(-)

diff --git a/src/test/ui/async-await/async-trait-fn.rs b/src/test/ui/async-await/async-trait-fn.rs
index 0ea685986db..e2062e82725 100644
--- a/src/test/ui/async-await/async-trait-fn.rs
+++ b/src/test/ui/async-await/async-trait-fn.rs
@@ -1,11 +1,8 @@
 // edition:2018
 trait T {
     async fn foo() {} //~ ERROR functions in traits cannot be declared `async`
-    //~^ ERROR mismatched types
     async fn bar(&self) {} //~ ERROR functions in traits cannot be declared `async`
-    //~^ ERROR mismatched types
     async fn baz() { //~ ERROR functions in traits cannot be declared `async`
-        //~^ ERROR mismatched types
         // Nested item must not ICE.
         fn a() {}
     }
diff --git a/src/test/ui/async-await/async-trait-fn.stderr b/src/test/ui/async-await/async-trait-fn.stderr
index 4fa54c6e369..afbe25cf7ab 100644
--- a/src/test/ui/async-await/async-trait-fn.stderr
+++ b/src/test/ui/async-await/async-trait-fn.stderr
@@ -12,7 +12,7 @@ LL |     async fn foo() {}
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:5:5
+  --> $DIR/async-trait-fn.rs:4:5
    |
 LL |     async fn bar(&self) {}
    |     -----^^^^^^^^^^^^^^
@@ -25,7 +25,7 @@ LL |     async fn bar(&self) {}
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
 error[E0706]: functions in traits cannot be declared `async`
-  --> $DIR/async-trait-fn.rs:7:5
+  --> $DIR/async-trait-fn.rs:5:5
    |
 LL |     async fn baz() {
    |     -----^^^^^^^^^
@@ -37,54 +37,6 @@ LL |     async fn baz() {
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
-error[E0308]: mismatched types
-  --> $DIR/async-trait-fn.rs:3:20
-   |
-LL |     async fn foo() {}
-   |                    ^^ expected associated type, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
-   |
-   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:3:20>)
-                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+error: aborting due to 3 previous errors
 
-error[E0308]: mismatched types
-  --> $DIR/async-trait-fn.rs:5:25
-   |
-LL |     async fn bar(&self) {}
-   |                         ^^ expected associated type, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
-   |
-   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:5:25>)
-                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
-error[E0308]: mismatched types
-  --> $DIR/async-trait-fn.rs:7:20
-   |
-LL |       async fn baz() {
-   |  ____________________^
-LL | |
-LL | |         // Nested item must not ICE.
-LL | |         fn a() {}
-LL | |     }
-   | |_____^ expected associated type, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL |   pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                             ------------------------------- the found opaque type
-   |
-   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/async-trait-fn.rs:7:20>)
-                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
-error: aborting due to 6 previous errors
-
-Some errors have detailed explanations: E0308, E0706.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0706`.
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.rs b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
index 22a61dcd25f..6bd6d879a4a 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.rs
@@ -17,7 +17,6 @@ impl Foo {
 trait Bar {
     async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
     //~^ ERROR functions in traits cannot be declared `async`
-    //~| ERROR mismatched types
 }
 
 fn main() {
diff --git a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
index 62a243e69e7..ba918eb28de 100644
--- a/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
+++ b/src/test/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -53,7 +53,7 @@ LL |     async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:37:9
+  --> $DIR/edition-deny-async-fns-2015.rs:36:9
    |
 LL |         async fn bar() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -62,7 +62,7 @@ LL |         async fn bar() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:27:9
+  --> $DIR/edition-deny-async-fns-2015.rs:26:9
    |
 LL |         async fn foo() {}
    |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -71,7 +71,7 @@ LL |         async fn foo() {}
    = note: for more on editions, read https://doc.rust-lang.org/edition-guide
 
 error[E0670]: `async fn` is not permitted in Rust 2015
-  --> $DIR/edition-deny-async-fns-2015.rs:32:13
+  --> $DIR/edition-deny-async-fns-2015.rs:31:13
    |
 LL |             async fn bar() {}
    |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
@@ -92,21 +92,7 @@ LL |     async fn foo() {}
    = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
    = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
 
-error[E0308]: mismatched types
-  --> $DIR/edition-deny-async-fns-2015.rs:18:20
-   |
-LL |     async fn foo() {}
-   |                    ^^ expected associated type, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
-   |
-   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/edition-deny-async-fns-2015.rs:18:20>)
-                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
+error: aborting due to 10 previous errors
 
-error: aborting due to 11 previous errors
-
-Some errors have detailed explanations: E0308, E0670, E0706.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
index 94f578af209..4559da91e47 100644
--- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
+++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs
@@ -12,7 +12,6 @@ impl A {
 
 trait C{async fn new(val: T) {} //~ ERROR  `async fn` is not permitted in Rust 2015
 //~^ ERROR functions in traits cannot be declared `async`
-//~| ERROR mismatched types
 //~| ERROR cannot find type `T` in this scope
 //~| WARN changes to closure capture in Rust 2021 will affect drop order [rust_2021_incompatible_closure_captures]
 
diff --git a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
index ee72a0c65c8..f7109d406d5 100644
--- a/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
+++ b/src/test/ui/span/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.stderr
@@ -1,5 +1,5 @@
 error: this file contains an unclosed delimiter
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:19:53
+  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:18:53
    |
 LL | trait C{async fn new(val: T) {}
    |        - unclosed delimiter
@@ -74,20 +74,6 @@ help: add a dummy let to cause `path` to be fully captured
 LL |     async fn create(path: impl AsRef<std::path::Path>)  { let _ = &path;
    |                                                           ++++++++++++++
 
-error[E0308]: mismatched types
-  --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
-   |
-LL | trait C{async fn new(val: T) {}
-   |                              ^^ expected associated type, found opaque type
-   |
-  ::: $SRC_DIR/core/src/future/mod.rs:LL:COL
-   |
-LL | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
-   |                                           ------------------------------- the found opaque type
-   |
-   = note: expected associated type `impl Future<Output = ()>` (trait associated opaque type at <$DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30>)
-                  found opaque type `impl Future<Output = ()>` (opaque type at <$SRC_DIR/core/src/future/mod.rs:LL:COL>)
-
 warning: changes to closure capture in Rust 2021 will affect drop order
   --> $DIR/drop-location-span-error-rust-2021-incompatible-closure-captures-93117.rs:13:30
    |
@@ -103,7 +89,7 @@ help: add a dummy let to cause `val` to be fully captured
 LL | trait C{async fn new(val: T) { let _ = &val;}
    |                                +++++++++++++
 
-error: aborting due to 7 previous errors; 2 warnings emitted
+error: aborting due to 6 previous errors; 2 warnings emitted
 
-Some errors have detailed explanations: E0308, E0412, E0423, E0670, E0706.
-For more information about an error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0412, E0423, E0670, E0706.
+For more information about an error, try `rustc --explain E0412`.

From 9a5936b8144c412394ecd0d9dd931faeb4d2034d Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Fri, 30 Sep 2022 19:16:13 +0000
Subject: [PATCH 4/5] Validate opaques in default trait bodies, don't normalize
 unless a body is provided

---
 .../rustc_hir_analysis/src/check/check.rs     | 62 +++++++++++--------
 compiler/rustc_middle/src/ty/sty.rs           |  2 +-
 .../src/traits/project.rs                     |  3 +-
 3 files changed, 39 insertions(+), 28 deletions(-)

diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 824144aeac0..bf022286b82 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -525,23 +525,33 @@ fn check_static_inhabited<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) {
 
 /// Checks that an opaque type does not contain cycles and does not use `Self` or `T::Foo`
 /// projections that would result in "inheriting lifetimes".
-pub(super) fn check_opaque<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    def_id: LocalDefId,
-    substs: SubstsRef<'tcx>,
-    origin: &hir::OpaqueTyOrigin,
-) {
-    let span = tcx.def_span(def_id);
-    check_opaque_for_inheriting_lifetimes(tcx, def_id, span);
-    if tcx.type_of(def_id).references_error() {
+fn check_opaque<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
+    let item = tcx.hir().item(id);
+    let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
+        tcx.sess.delay_span_bug(tcx.hir().span(id.hir_id()), "expected opaque item");
         return;
-    }
-    if check_opaque_for_cycles(tcx, def_id, substs, span, origin).is_err() {
-        return;
-    }
-    check_opaque_meets_bounds(tcx, def_id, substs, span, origin);
-}
+    };
 
+    // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
+    // `async-std` (and `pub async fn` in general).
+    // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
+    // See https://github.com/rust-lang/rust/issues/75100
+    if tcx.sess.opts.actually_rustdoc {
+        return;
+    }
+
+    let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
+    let span = tcx.def_span(item.def_id.def_id);
+
+    check_opaque_for_inheriting_lifetimes(tcx, item.def_id.def_id, span);
+    if tcx.type_of(item.def_id.def_id).references_error() {
+        return;
+    }
+    if check_opaque_for_cycles(tcx, item.def_id.def_id, substs, span, &origin).is_err() {
+        return;
+    }
+    check_opaque_meets_bounds(tcx, item.def_id.def_id, substs, span, &origin);
+}
 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
 /// in "inheriting lifetimes".
 #[instrument(level = "debug", skip(tcx, span))]
@@ -858,17 +868,17 @@ fn check_item_type<'tcx>(tcx: TyCtxt<'tcx>, id: hir::ItemId) {
             check_union(tcx, id.def_id.def_id);
         }
         DefKind::OpaqueTy => {
-            let item = tcx.hir().item(id);
-            let hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) = item.kind else {
-                return;
-            };
-            // HACK(jynelson): trying to infer the type of `impl trait` breaks documenting
-            // `async-std` (and `pub async fn` in general).
-            // Since rustdoc doesn't care about the concrete type behind `impl Trait`, just don't look at it!
-            // See https://github.com/rust-lang/rust/issues/75100
-            if !tcx.sess.opts.actually_rustdoc {
-                let substs = InternalSubsts::identity_for_item(tcx, item.def_id.to_def_id());
-                check_opaque(tcx, item.def_id.def_id, substs, &origin);
+            check_opaque(tcx, id);
+        }
+        DefKind::ImplTraitPlaceholder => {
+            let parent = tcx.impl_trait_in_trait_parent(id.def_id.to_def_id());
+            // Only check the validity of this opaque type if the function has a default body
+            if let hir::Node::TraitItem(hir::TraitItem {
+                kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
+                ..
+            }) = tcx.hir().get_by_def_id(parent.expect_local())
+            {
+                check_opaque(tcx, id);
             }
         }
         DefKind::TyAlias => {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index f8a169fc869..64636963313 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1160,8 +1160,8 @@ impl<'tcx> ProjectionTy<'tcx> {
         &self,
         tcx: TyCtxt<'tcx>,
     ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) {
-        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
         let def_id = tcx.parent(self.item_def_id);
+        assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
         let trait_generics = tcx.generics_of(def_id);
         (
             ty::TraitRef { def_id, substs: self.substs.truncate_to(tcx, trait_generics) },
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 6a4ea114b40..8e2f1d5def3 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1325,11 +1325,13 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     if tcx.def_kind(obligation.predicate.item_def_id) == DefKind::ImplTraitPlaceholder {
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
         // If we are trying to project an RPITIT with trait's default `Self` parameter,
         // then we must be within a default trait body.
         if obligation.predicate.self_ty()
             == ty::InternalSubsts::identity_for_item(tcx, obligation.predicate.item_def_id)
                 .type_at(0)
+            && tcx.associated_item(trait_fn_def_id).defaultness(tcx).has_value()
         {
             candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(
                 ImplTraitInTraitCandidate::Trait,
@@ -1337,7 +1339,6 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
             return;
         }
 
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.item_def_id);
         let trait_def_id = tcx.parent(trait_fn_def_id);
         let trait_substs =
             obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));

From 0eeeea9414d0ee5b22f6a33601282b46eca67bd6 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 5 Oct 2022 03:52:38 +0000
Subject: [PATCH 5/5] Add broken test for AFIT with RPITIT

---
 .../in-trait/default-body-with-rpit.rs        | 21 +++++++++++++++++++
 .../in-trait/default-body-with-rpit.stderr    | 12 +++++++++++
 2 files changed, 33 insertions(+)
 create mode 100644 src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
 create mode 100644 src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr

diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
new file mode 100644
index 00000000000..f0d407cd527
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -0,0 +1,21 @@
+// known-bug: #102688
+// edition:2021
+
+#![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
+#![allow(incomplete_features)]
+
+use std::fmt::Debug;
+
+trait Foo {
+    async fn baz(&self) -> impl Debug {
+        ""
+    }
+}
+
+struct Bar;
+
+impl Foo for Bar {}
+
+fn main() {
+    let _ = Bar.baz();
+}
diff --git a/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr
new file mode 100644
index 00000000000..4529d301f9e
--- /dev/null
+++ b/src/test/ui/impl-trait/in-trait/default-body-with-rpit.stderr
@@ -0,0 +1,12 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/default-body-with-rpit.rs:10:28
+   |
+LL |     async fn baz(&self) -> impl Debug {
+   |                            ^^^^^^^^^^ cannot resolve opaque type
+   |
+   = note: these returned values have a concrete "never" type
+   = help: this error will resolve once the item's body returns a concrete type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.