about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-03-17 08:42:40 +0100
committerGitHub <noreply@github.com>2023-03-17 08:42:40 +0100
commit246d989a30ad55e333a1870da96fab5066c5b8e9 (patch)
treee4381edef150657305d90f8a5c00d74da4467d8b
parentedd6b4256557ec2cd9aac0c4de46848cc26931e5 (diff)
parent8d922eba796a236dbfdd032d5e4c279519e02b60 (diff)
downloadrust-246d989a30ad55e333a1870da96fab5066c5b8e9.tar.gz
rust-246d989a30ad55e333a1870da96fab5066c5b8e9.zip
Rollup merge of #109198 - compiler-errors:new-rpitit-default-body, r=spastorino
Install projection from RPITIT to default trait method opaque correctly

1. For new lowering strategy `-Zlower-impl-trait-in-trait-to-assoc-ty`, install the correct default trait method projection predicates (RPITIT -> opaque). This makes default trait body tests pass!

2. Fix two WF-checking bugs -- first, we want to make sure that we're always looking for an opaque type in `check_return_position_impl_trait_in_trait_bounds`. That's because the RPITIT projections are normalized to opaques during wfcheck. Second, fix RPITIT's param-envs by not adding the projection predicates that we install on trait methods to make default RPITITs work -- I left a comment why.

3. Also, just a small drive-by for `rustc_on_unimplemented`. Not sure if it affects any tests, but can't hurt.

r? ````@spastorino,```` based off of #109140
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs24
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs36
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs12
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs14
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs8
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs2
-rw-r--r--compiler/rustc_middle/src/query/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs20
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs2
-rw-r--r--compiler/rustc_privacy/src/lib.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs4
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs37
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs41
-rw-r--r--src/librustdoc/clean/mod.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr (renamed from tests/ui/async-await/in-trait/async-default-fn-overridden.stderr)2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr (renamed from tests/ui/async-await/in-trait/async-generics-and-bounds.stderr)12
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics.current.stderr (renamed from tests/ui/async-await/in-trait/async-generics.stderr)12
-rw-r--r--tests/ui/async-await/in-trait/async-generics.next.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr (renamed from tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-body-type-err.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/default-body.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr (renamed from tests/ui/impl-trait/in-trait/default-method-constraint.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.current.stderr (renamed from tests/ui/impl-trait/in-trait/issue-102571.stderr)2
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.next.stderr14
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.current.stderr (renamed from tests/ui/impl-trait/in-trait/specialization-broken.stderr)6
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.next.stderr31
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.current.stderr (renamed from tests/ui/impl-trait/in-trait/wf-bounds.stderr)6
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.next.stderr30
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.rs2
50 files changed, 419 insertions, 107 deletions
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 14dc9d89180..872fec3954b 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -557,7 +557,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
             check_opaque(tcx, id);
         }
         DefKind::ImplTraitPlaceholder => {
-            let parent = tcx.impl_trait_in_trait_parent(id.owner_id.to_def_id());
+            let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_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(_)),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 71050864ce0..4120ad45f6a 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1,7 +1,6 @@
 use crate::autoderef::Autoderef;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
 
-use hir::def::DefKind;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -1548,16 +1547,27 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
     if let Some(assoc_item) = tcx.opt_associated_item(fn_def_id.to_def_id())
         && assoc_item.container == ty::AssocItemContainer::TraitContainer
     {
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Even with the new lowering
+        // strategy, we can't just call `check_associated_item` on the new RPITITs,
+        // because tests like `tests/ui/async-await/in-trait/implied-bounds.rs` will fail.
+        // That's because we need to check that the bounds of the RPITIT hold using
+        // the special substs that we create during opaque type lowering, otherwise we're
+        // getting a bunch of early bound and free regions mixed up... Haven't looked too
+        // deep into this, though.
         for arg in fn_output.walk() {
             if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Alias(ty::Opaque, proj) = ty.kind()
-                && tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
-                && tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
+                // RPITITs are always eagerly normalized into opaques, so always look for an
+                // opaque here.
+                && let ty::Alias(ty::Opaque, opaque_ty) = ty.kind()
+                && let Some(opaque_def_id) = opaque_ty.def_id.as_local()
+                && let opaque = tcx.hir().expect_item(opaque_def_id).expect_opaque_ty()
+                && let hir::OpaqueTyOrigin::FnReturn(source) | hir::OpaqueTyOrigin::AsyncFn(source) = opaque.origin
+                && source == fn_def_id
             {
-                let span = tcx.def_span(proj.def_id);
-                let bounds = wfcx.tcx().explicit_item_bounds(proj.def_id);
+                let span = tcx.def_span(opaque_ty.def_id);
+                let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id);
                 let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| {
-                    let bound = ty::EarlyBinder(bound).subst(tcx, proj.substs);
+                    let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs);
                     let normalized_bound = wfcx.normalize(span, None, bound);
                     traits::wf::predicate_obligations(
                         wfcx.infcx,
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 7dce29cc0bb..df0258ff7a3 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -3,7 +3,7 @@ use crate::astconv::AstConv;
 use rustc_hir as hir;
 use rustc_infer::traits::util;
 use rustc_middle::ty::subst::InternalSubsts;
-use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
@@ -76,18 +76,26 @@ pub(super) fn explicit_item_bounds(
     tcx: TyCtxt<'_>,
     def_id: DefId,
 ) -> &'_ [(ty::Predicate<'_>, Span)] {
-    // If the def_id is about an RPITIT, delegate explicit_item_bounds to the opaque_def_id that
-    // generated the synthesized associate type.
-    let rpitit_info = if let Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) =
-        tcx.opt_rpitit_info(def_id)
-    {
-        Some(opaque_def_id)
-    } else {
-        None
-    };
+    match tcx.opt_rpitit_info(def_id) {
+        // RPITIT's bounds are the same as opaque type bounds, but with
+        // a projection self type.
+        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            let item = tcx.hir().get_by_def_id(opaque_def_id.expect_local()).expect_item();
+            let opaque_ty = item.expect_opaque_ty();
+            return opaque_type_bounds(
+                tcx,
+                opaque_def_id,
+                opaque_ty.bounds,
+                tcx.mk_projection(def_id, ty::InternalSubsts::identity_for_item(tcx, def_id)),
+                item.span,
+            );
+        }
+        // These should have been fed!
+        Some(ty::ImplTraitInTraitData::Impl { .. }) => unreachable!(),
+        None => {}
+    }
 
-    let bounds_def_id = rpitit_info.unwrap_or(def_id);
-    let hir_id = tcx.hir().local_def_id_to_hir_id(bounds_def_id.expect_local());
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
     match tcx.hir().get(hir_id) {
         hir::Node::TraitItem(hir::TraitItem {
             kind: hir::TraitItemKind::Type(bounds, _),
@@ -100,12 +108,12 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => {
             let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            let item_ty = if *in_trait || rpitit_info.is_some() {
+            let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
                 tcx.mk_projection(def_id, substs)
             } else {
                 tcx.mk_opaque(def_id, substs)
             };
-            opaque_type_bounds(tcx, bounds_def_id, bounds, item_ty, *span)
+            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
         _ => bug!("item_bounds called on {:?}", def_id),
     }
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index a8b7699b667..361e8948e85 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -112,10 +112,14 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
         fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             match t.kind() {
                 ty::Alias(_, ty::AliasTy { def_id, substs, .. })
-                    if matches!(
-                        self.tcx.def_kind(*def_id),
-                        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
-                    ) =>
+                    if matches!(self.tcx.def_kind(*def_id), DefKind::OpaqueTy) =>
+                {
+                    self.visit_opaque(*def_id, substs)
+                }
+                // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
+                // at all for RPITITs.
+                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                    if self.tcx.is_impl_trait_in_trait(*def_id) =>
                 {
                     self.visit_opaque(*def_id, substs)
                 }
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 6becf4892ac..ec391ea80f4 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -2,7 +2,6 @@
 
 use super::{check_fn, Expectation, FnCtxt, GeneratorTypes};
 
-use hir::def::DefKind;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
@@ -715,14 +714,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .subst_iter_copied(self.tcx, substs)
                 .find_map(|(p, s)| get_future_output(p, s))?,
             ty::Error(_) => return None,
-            ty::Alias(ty::Projection, proj)
-                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
-            {
-                self.tcx
-                    .bound_explicit_item_bounds(proj.def_id)
-                    .subst_iter_copied(self.tcx, proj.substs)
-                    .find_map(|(p, s)| get_future_output(p, s))?
-            }
+            ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self
+                .tcx
+                .bound_explicit_item_bounds(proj.def_id)
+                .subst_iter_copied(self.tcx, proj.substs)
+                .find_map(|(p, s)| get_future_output(p, s))?,
             _ => span_bug!(
                 self.tcx.def_span(expr_def_id),
                 "async fn generator return type not an inference variable: {ret_ty}"
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ac4986a577c..de1a2e6a577 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -359,10 +359,12 @@ impl<'tcx> InferCtxt<'tcx> {
     pub fn get_impl_future_output_ty(&self, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
         let (def_id, substs) = match *ty.kind() {
             ty::Alias(_, ty::AliasTy { def_id, substs, .. })
-                if matches!(
-                    self.tcx.def_kind(def_id),
-                    DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder
-                ) =>
+                if matches!(self.tcx.def_kind(def_id), DefKind::OpaqueTy) =>
+            {
+                (def_id, substs)
+            }
+            ty::Alias(_, ty::AliasTy { def_id, substs, .. })
+                if self.tcx.is_impl_trait_in_trait(def_id) =>
             {
                 (def_id, substs)
             }
@@ -1757,8 +1759,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                                 )
                             }
                             (true, ty::Alias(ty::Projection, proj))
-                                if self.tcx.def_kind(proj.def_id)
-                                    == DefKind::ImplTraitPlaceholder =>
+                                if self.tcx.is_impl_trait_in_trait(proj.def_id) =>
                             {
                                 let sm = self.tcx.sess.source_map();
                                 let pos = sm.lookup_char_pos(self.tcx.def_span(proj.def_id).lo());
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
index b33729d0be5..b38bbdfe7bb 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note_and_explain.rs
@@ -1,7 +1,7 @@
 use super::TypeErrCtxt;
 use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect};
 use rustc_errors::{pluralize, Diagnostic, MultiSpan};
-use rustc_hir::{self as hir, def::DefKind};
+use rustc_hir as hir;
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::ExpectedFound;
 use rustc_middle::ty::print::Printer;
@@ -75,7 +75,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                         diag.note("an associated type was expected, but a different one was found");
                     }
                     (ty::Param(p), ty::Alias(ty::Projection, proj)) | (ty::Alias(ty::Projection, proj), ty::Param(p))
-                        if tcx.def_kind(proj.def_id) != DefKind::ImplTraitPlaceholder =>
+                        if !tcx.is_impl_trait_in_trait(proj.def_id) =>
                     {
                         let p_def_id = tcx
                             .generics_of(body_owner_def_id)
@@ -222,7 +222,7 @@ impl<T> Trait<T> for X {
                             diag.span_label(p_span, "this type parameter");
                         }
                     }
-                    (ty::Alias(ty::Projection, proj_ty), _) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+                    (ty::Alias(ty::Projection, proj_ty), _) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
                         self.expected_projection(
                             diag,
                             proj_ty,
@@ -231,7 +231,7 @@ impl<T> Trait<T> for X {
                             cause.code(),
                         );
                     }
-                    (_, ty::Alias(ty::Projection, proj_ty)) if tcx.def_kind(proj_ty.def_id) != DefKind::ImplTraitPlaceholder => {
+                    (_, ty::Alias(ty::Projection, proj_ty)) if !tcx.is_impl_trait_in_trait(proj_ty.def_id) => {
                         let msg = format!(
                             "consider constraining the associated type `{}` to `{}`",
                             values.found, values.expected,
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index ed4bc594d1a..49f823a47b8 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -3,7 +3,6 @@ use super::{DefineOpaqueTypes, InferResult};
 use crate::errors::OpaqueHiddenTypeDiag;
 use crate::infer::{DefiningAnchor, InferCtxt, InferOk};
 use crate::traits;
-use hir::def::DefKind;
 use hir::def_id::{DefId, LocalDefId};
 use hir::OpaqueTyOrigin;
 use rustc_data_structures::sync::Lrc;
@@ -478,9 +477,7 @@ where
                 }
             }
 
-            ty::Alias(ty::Projection, proj)
-                if self.tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder =>
-            {
+            ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => {
                 // Skip lifetime parameters that are not captures.
                 let variances = self.tcx.variances_of(proj.def_id);
 
@@ -559,8 +556,7 @@ impl<'tcx> InferCtxt<'tcx> {
                     // FIXME(RPITIT): Don't replace RPITITs with inference vars.
                     ty::Alias(ty::Projection, projection_ty)
                         if !projection_ty.has_escaping_bound_vars()
-                            && tcx.def_kind(projection_ty.def_id)
-                                != DefKind::ImplTraitPlaceholder =>
+                            && !tcx.is_impl_trait_in_trait(projection_ty.def_id) =>
                     {
                         self.infer_projection(
                             param_env,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 9649ce2c5a7..c778574b2c5 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1028,7 +1028,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
         | DefKind::InlineConst => true,
 
         DefKind::ImplTraitPlaceholder => {
-            let parent_def_id = tcx.impl_trait_in_trait_parent(def_id.to_def_id());
+            let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
             let assoc_item = tcx.associated_item(parent_def_id);
             match assoc_item.container {
                 // Always encode an RPIT in an impl fn, since it always has a body
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 2cd79157441..c8860cc55f6 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -191,6 +191,7 @@ rustc_queries! {
     {
         desc { "determine whether the opaque is a type-alias impl trait" }
         separate_provide_extern
+        feedable
     }
 
     query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 04d7de531c2..6ef8384d010 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2552,12 +2552,18 @@ impl<'tcx> TyCtxt<'tcx> {
         matches!(self.trait_of_item(def_id), Some(trait_id) if self.has_attr(trait_id, sym::const_trait))
     }
 
-    pub fn impl_trait_in_trait_parent(self, mut def_id: DefId) -> DefId {
-        while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
-            debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
-            def_id = self.parent(def_id);
+    pub fn impl_trait_in_trait_parent_fn(self, mut def_id: DefId) -> DefId {
+        match self.opt_rpitit_info(def_id) {
+            Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
+            | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
+            None => {
+                while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
+                    debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
+                    def_id = self.parent(def_id);
+                }
+                def_id
+            }
         }
-        def_id
     }
 
     pub fn impl_method_has_trait_impl_trait_tys(self, def_id: DefId) -> bool {
@@ -2572,6 +2578,10 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
 
+        if self.lower_impl_trait_in_trait_to_assoc_ty() {
+            return !self.associated_items_for_impl_trait_in_trait(trait_item_def_id).is_empty();
+        }
+
         // FIXME(RPITIT): This does a somewhat manual walk through the signature
         // of the trait fn to look for any RPITITs, but that's kinda doing a lot
         // of work. We can probably remove this when we refactor RPITITs to be
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b3139d23d36..fffdbfc9660 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -728,7 +728,7 @@ pub trait PrettyPrinter<'tcx>:
             }
             ty::Alias(ty::Projection, ref data) => {
                 if !(self.should_print_verbose() || NO_QUERIES.with(|q| q.get()))
-                    && self.tcx().def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
+                    && self.tcx().is_impl_trait_in_trait(data.def_id)
                 {
                     return self.pretty_print_opaque_impl_type(data.def_id, data.substs);
                 } else {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 52d114bae30..4c606b939b2 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1288,7 +1288,7 @@ impl<'tcx> AliasTy<'tcx> {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
             DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent(self.def_id))
+                tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
             }
             kind => bug!("expected a projection AliasTy; found {kind:?}"),
         }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index ef7c68c1a33..cd676445898 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -132,7 +132,7 @@ where
                 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.def_id);
+                let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
                 let trait_generics = tcx.generics_of(def_id);
                 (
                     tcx.mk_trait_ref(def_id, projection.substs.truncate_to(tcx, trait_generics)),
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 277926688e2..a9c4e126816 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -144,18 +144,22 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
         trait_ref: ty::PolyTraitRef<'tcx>,
         obligation: &PredicateObligation<'tcx>,
     ) -> OnUnimplementedNote {
-        if self.tcx.opt_rpitit_info(obligation.cause.body_id.to_def_id()).is_some() {
-            return OnUnimplementedNote::default();
-        }
-
         let (def_id, substs) = self
             .impl_similar_to(trait_ref, obligation)
             .unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().substs));
         let trait_ref = trait_ref.skip_binder();
 
-        let body_hir = self.tcx.hir().local_def_id_to_hir_id(obligation.cause.body_id);
-        let mut flags =
-            vec![(sym::ItemContext, self.describe_enclosure(body_hir).map(|s| s.to_owned()))];
+        let mut flags = vec![];
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
+        // but I guess we could synthesize one here. We don't see any errors that rely on
+        // that yet, though.
+        let enclosure =
+            if let Some(body_hir) = self.tcx.opt_local_def_id_to_hir_id(obligation.cause.body_id) {
+                self.describe_enclosure(body_hir).map(|s| s.to_owned())
+            } else {
+                None
+            };
+        flags.push((sym::ItemContext, enclosure));
 
         match obligation.cause.code() {
             ObligationCauseCode::BuiltinDerivedObligation(..)
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 0f0cccea130..b8d9cff9c48 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1298,7 +1298,7 @@ fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
 ) {
     let tcx = selcx.tcx();
     if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
+        let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
 
         let trait_def_id = tcx.parent(trait_fn_def_id);
         let trait_substs =
@@ -2200,7 +2200,7 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>(
     let tcx = selcx.tcx();
     let mut obligations = data.nested;
 
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent(obligation.predicate.def_id);
+    let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
     let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
         Ok(assoc_ty) => assoc_ty,
         Err(guar) => return Progress::error(tcx, guar),
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index a2816124538..68b1086e8e3 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -244,7 +244,7 @@ fn associated_item_for_impl_trait_in_trait(
     tcx: TyCtxt<'_>,
     opaque_ty_def_id: LocalDefId,
 ) -> LocalDefId {
-    let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id());
+    let fn_def_id = tcx.impl_trait_in_trait_parent_fn(opaque_ty_def_id.to_def_id());
     let trait_def_id = tcx.parent(fn_def_id);
     assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
 
@@ -289,8 +289,39 @@ fn associated_item_for_impl_trait_in_trait(
         InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
     )));
 
-    // Copy generics_of of the opaque.
-    trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+    trait_assoc_ty.is_type_alias_impl_trait(false);
+
+    // Copy generics_of of the opaque type item but the trait is the parent.
+    trait_assoc_ty.generics_of({
+        let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
+        let opaque_ty_parent_count = opaque_ty_generics.parent_count;
+        let mut params = opaque_ty_generics.params.clone();
+
+        let parent_generics = tcx.generics_of(trait_def_id);
+        let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+        let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+
+        for param in &mut params {
+            param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
+                - opaque_ty_parent_count as u32;
+        }
+
+        trait_fn_params.extend(params);
+        params = trait_fn_params;
+
+        let param_def_id_to_index =
+            params.iter().map(|param| (param.def_id, param.index)).collect();
+
+        ty::Generics {
+            parent: Some(trait_def_id),
+            parent_count,
+            params,
+            param_def_id_to_index,
+            has_self: false,
+            has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+        }
+    });
 
     // There are no predicates for the synthesized associated type.
     trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index d41bf603983..9fed1e57c92 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -117,16 +117,22 @@ fn adt_sized_constraint(tcx: TyCtxt<'_>, def_id: DefId) -> &[Ty<'_>] {
 
 /// See `ParamEnv` struct definition for details.
 fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
-    // When computing the param_env of an RPITIT, copy param_env of the containing function. The
-    // synthesized associated type doesn't have extra predicates to assume.
-    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
-        return tcx.param_env(fn_def_id);
-    }
-
     // Compute the bounds on Self and the type parameters.
     let ty::InstantiatedPredicates { mut predicates, .. } =
         tcx.predicates_of(def_id).instantiate_identity(tcx);
 
+    // When computing the param_env of an RPITIT, use predicates of the containing function,
+    // *except* for the additional assumption that the RPITIT normalizes to the trait method's
+    // default opaque type. This is needed to properly check the item bounds of the assoc
+    // type hold (`check_type_bounds`), since that method already installs a similar projection
+    // bound, so they will conflict.
+    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): I don't like this, we should
+    // at least be making sure that the generics in RPITITs and their parent fn don't
+    // get out of alignment, or else we do actually need to substitute these predicates.
+    if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id) {
+        predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+    }
+
     // Finally, we have to normalize the bounds in the environment, in
     // case they contain any associated type projections. This process
     // can yield errors if the put in illegal associated types, like
@@ -160,7 +166,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     }
 
     let local_did = def_id.as_local();
-    let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
+    // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This isn't correct for
+    // RPITITs in const trait fn.
+    let hir_id = local_did.and_then(|def_id| tcx.opt_local_def_id_to_hir_id(def_id));
 
     // FIXME(consts): This is not exactly in line with the constness query.
     let constness = match hir_id {
@@ -268,8 +276,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
 
     fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
         if let ty::Alias(ty::Projection, alias_ty) = *ty.kind()
-            && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder
-            && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id
+            && self.tcx.is_impl_trait_in_trait(alias_ty.def_id)
+            && self.tcx.impl_trait_in_trait_parent_fn(alias_ty.def_id) == self.fn_def_id
             && self.seen.insert(alias_ty.def_id)
         {
             // We have entered some binders as we've walked into the
@@ -282,11 +290,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
                     re
                 }
             });
+
+            // If we're lowering to associated item, install the opaque type which is just
+            // the `type_of` of the trait's associated item. If we're using the old lowering
+            // strategy, then just reinterpret the associated type like an opaque :^)
+            let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+                self
+                    .tcx
+                    .type_of(alias_ty.def_id)
+                    .subst(self.tcx, alias_ty.substs)
+            } else {
+                self.tcx.mk_alias(ty::Opaque, alias_ty)
+            };
+
             self.predicates.push(
                 ty::Binder::bind_with_vars(
                     ty::ProjectionPredicate {
                         projection_ty: alias_ty,
-                        term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(),
+                        term: default_ty.into(),
                     },
                     self.bound_vars,
                 )
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 29c3afe0d95..989e091a0d2 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -426,7 +426,7 @@ fn clean_projection<'tcx>(
     cx: &mut DocContext<'tcx>,
     def_id: Option<DefId>,
 ) -> Type {
-    if cx.tcx.def_kind(ty.skip_binder().def_id) == DefKind::ImplTraitPlaceholder {
+    if cx.tcx.is_impl_trait_in_trait(ty.skip_binder().def_id) {
         let bounds = cx
             .tcx
             .explicit_item_bounds(ty.skip_binder().def_id)
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
index 61a826258d0..2142ee232ca 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.stderr
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/async-default-fn-overridden.rs:4:12
+  --> $DIR/async-default-fn-overridden.rs:6:12
    |
 LL | #![feature(async_fn_in_trait)]
    |            ^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
new file mode 100644
index 00000000000..2142ee232ca
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `async_fn_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/async-default-fn-overridden.rs:6:12
+   |
+LL | #![feature(async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 0fd1a2703db..dd1af93d706 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -1,5 +1,7 @@
 // run-pass
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 //~^ WARN the feature `async_fn_in_trait` is incomplete and may not be safe to use
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr
index f1f0d7e5907..780da068962 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.current.stderr
@@ -1,33 +1,33 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics-and-bounds.rs:12:18
+  --> $DIR/async-generics-and-bounds.rs:14:18
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics-and-bounds.rs:12:18
+  --> $DIR/async-generics-and-bounds.rs:14:18
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics-and-bounds.rs:12:28
+  --> $DIR/async-generics-and-bounds.rs:14:28
    |
 LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
    |                            ^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr
new file mode 100644
index 00000000000..780da068962
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.next.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:14:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:14:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:14:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
index a73d55adfec..146e74ec2d0 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -1,6 +1,8 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.current.stderr
index 2f05564564c..04e1ab6d769 100644
--- a/tests/ui/async-await/in-trait/async-generics.stderr
+++ b/tests/ui/async-await/in-trait/async-generics.current.stderr
@@ -1,33 +1,33 @@
 error[E0311]: the parameter type `U` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
    |
 note: the parameter type `U` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics.rs:9:18
+  --> $DIR/async-generics.rs:11:18
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
 
 error[E0311]: the parameter type `T` may not live long enough
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
    |
 note: the parameter type `T` must be valid for the anonymous lifetime defined here...
-  --> $DIR/async-generics.rs:9:18
+  --> $DIR/async-generics.rs:11:18
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                  ^^^^^
 note: ...so that the reference type `&(T, U)` does not outlive the data it points at
-  --> $DIR/async-generics.rs:9:28
+  --> $DIR/async-generics.rs:11:28
    |
 LL |     async fn foo(&self) -> &(T, U);
    |                            ^^^^^^^
diff --git a/tests/ui/async-await/in-trait/async-generics.next.stderr b/tests/ui/async-await/in-trait/async-generics.next.stderr
new file mode 100644
index 00000000000..04e1ab6d769
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.next.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:11:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:11:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:11:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs
index 67000e5770e..507500abf4e 100644
--- a/tests/ui/async-await/in-trait/async-generics.rs
+++ b/tests/ui/async-await/in-trait/async-generics.rs
@@ -1,6 +1,8 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr
index d681ecf25e8..05c025cc169 100644
--- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.stderr
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/box-coerce-span-in-default.rs:3:12
+  --> $DIR/box-coerce-span-in-default.rs:5:12
    |
 LL | #![feature(return_position_impl_trait_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr
new file mode 100644
index 00000000000..05c025cc169
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/box-coerce-span-in-default.rs:5:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
index a4d483dee7a..163bb4fcf77 100644
--- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 //~^ WARN the feature `return_position_impl_trait_in_trait` is incomplete
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr
index cc3bdf0e571..85450e3b0a0 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/default-body-type-err-2.rs:8:9
+  --> $DIR/default-body-type-err-2.rs:10:9
    |
 LL |         42
    |         ^^- help: try using a conversion method: `.to_string()`
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr
new file mode 100644
index 00000000000..85450e3b0a0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.next.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/default-body-type-err-2.rs:10:9
+   |
+LL |         42
+   |         ^^- help: try using a conversion method: `.to_string()`
+   |         |
+   |         expected `String`, found integer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
index 45ae2b8ad3a..62323776310 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
@@ -1,4 +1,6 @@
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![allow(incomplete_features)]
 #![feature(async_fn_in_trait)]
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr
index 4742eb37d3e..c949168a377 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.current.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
-  --> $DIR/default-body-type-err.rs:7:22
+  --> $DIR/default-body-type-err.rs:10:22
    |
 LL |     fn lol(&self) -> impl Deref<Target = String> {
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr
new file mode 100644
index 00000000000..c949168a377
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.next.stderr
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
+  --> $DIR/default-body-type-err.rs:10:22
+   |
+LL |     fn lol(&self) -> impl Deref<Target = String> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
+LL |
+LL |         &1i32
+   |         ----- return type was inferred to be `&i32` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
index ac9baf91cae..9bd5b777989 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![allow(incomplete_features)]
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs
index b0baf5bb10d..ab6a51c6bcb 100644
--- a/tests/ui/impl-trait/in-trait/default-body.rs
+++ b/tests/ui/impl-trait/in-trait/default-body.rs
@@ -1,5 +1,7 @@
 // check-pass
 // edition:2021
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
index 5e18605aa4c..7bb79911f56 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.stderr
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/default-method-constraint.rs:5:12
+  --> $DIR/default-method-constraint.rs:7:12
    |
 LL | #![feature(return_position_impl_trait_in_trait)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
new file mode 100644
index 00000000000..7bb79911f56
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_position_impl_trait_in_trait` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default-method-constraint.rs:7:12
+   |
+LL | #![feature(return_position_impl_trait_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
index 8c50cc29586..e85fe3c8626 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
@@ -1,4 +1,6 @@
 // check-pass
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 // This didn't work in the previous default RPITIT method hack attempt
 
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.current.stderr
index 87219941d91..cac9a29f644 100644
--- a/tests/ui/impl-trait/in-trait/issue-102571.stderr
+++ b/tests/ui/impl-trait/in-trait/issue-102571.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-102571.rs:20:9
+  --> $DIR/issue-102571.rs:23:9
    |
 LL |     let () = t.bar();
    |         ^^   ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.next.stderr b/tests/ui/impl-trait/in-trait/issue-102571.next.stderr
new file mode 100644
index 00000000000..cac9a29f644
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/issue-102571.next.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-102571.rs:23:9
+   |
+LL |     let () = t.bar();
+   |         ^^   ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+   |         |
+   |         expected associated type, found `()`
+   |
+   = note: expected associated type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+                    found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs
index 61c91e64417..f0ddab5e7f2 100644
--- a/tests/ui/impl-trait/in-trait/issue-102571.rs
+++ b/tests/ui/impl-trait/in-trait/issue-102571.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.current.stderr
index dc621d6b8a8..f48e7a1ed14 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.current.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `bar` has an incompatible type for trait
-  --> $DIR/specialization-broken.rs:16:22
+  --> $DIR/specialization-broken.rs:19:22
    |
 LL | default impl<U> Foo for U
    |              - this type parameter
@@ -11,7 +11,7 @@ LL |     fn bar(&self) -> U {
    |                      help: change the output type to match the trait: `impl Sized`
    |
 note: type in trait
-  --> $DIR/specialization-broken.rs:9:22
+  --> $DIR/specialization-broken.rs:12:22
    |
 LL |     fn bar(&self) -> impl Sized;
    |                      ^^^^^^^^^^
@@ -19,7 +19,7 @@ LL |     fn bar(&self) -> impl Sized;
               found signature `fn(&U) -> U`
 
 error: method with return-position `impl Trait` in trait cannot be specialized
-  --> $DIR/specialization-broken.rs:16:5
+  --> $DIR/specialization-broken.rs:19:5
    |
 LL |     fn bar(&self) -> U {
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr
new file mode 100644
index 00000000000..f48e7a1ed14
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.next.stderr
@@ -0,0 +1,31 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/specialization-broken.rs:19:22
+   |
+LL | default impl<U> Foo for U
+   |              - this type parameter
+...
+LL |     fn bar(&self) -> U {
+   |                      ^
+   |                      |
+   |                      expected associated type, found type parameter `U`
+   |                      help: change the output type to match the trait: `impl Sized`
+   |
+note: type in trait
+  --> $DIR/specialization-broken.rs:12:22
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |                      ^^^^^^^^^^
+   = note: expected signature `fn(&U) -> impl Sized`
+              found signature `fn(&U) -> U`
+
+error: method with return-position `impl Trait` in trait cannot be specialized
+  --> $DIR/specialization-broken.rs:19:5
+   |
+LL |     fn bar(&self) -> U {
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs
index 2fcffdf3f9a..658d0709717 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs
@@ -1,3 +1,6 @@
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
+
 // FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
 // But we fixed an ICE anyways.
 
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
index 03cc4c2b93b..8392f26e7c8 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.stderr
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:9:22
+  --> $DIR/wf-bounds.rs:11:22
    |
 LL |     fn nya() -> impl Wf<Vec<[u8]>>;
    |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -9,14 +9,14 @@ note: required by a bound in `Vec`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 
 error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/wf-bounds.rs:12:23
+  --> $DIR/wf-bounds.rs:14:23
    |
 LL |     fn nya2() -> impl Wf<[u8]>;
    |                       ^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
 note: required by a bound in `Wf`
-  --> $DIR/wf-bounds.rs:6:10
+  --> $DIR/wf-bounds.rs:8:10
    |
 LL | trait Wf<T> {}
    |          ^ required by this bound in `Wf`
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
new file mode 100644
index 00000000000..8392f26e7c8
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.next.stderr
@@ -0,0 +1,30 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:11:22
+   |
+LL |     fn nya() -> impl Wf<Vec<[u8]>>;
+   |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:14:23
+   |
+LL |     fn nya2() -> impl Wf<[u8]>;
+   |                       ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Wf`
+  --> $DIR/wf-bounds.rs:8:10
+   |
+LL | trait Wf<T> {}
+   |          ^ required by this bound in `Wf`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Wf<T: ?Sized> {}
+   |           ++++++++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs
index 2c71583b312..39f41275315 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs
@@ -1,4 +1,6 @@
 // issue #101663
+// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]