diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 8d4f96639efbd..429e62c4a1c63 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1539,9 +1539,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         );
         debug!(?opaque_ty_def_id);
 
-        // Contains the new lifetime definitions created for the TAIT (if any).
-        let mut collected_lifetimes = Vec::new();
-
         // If this came from a TAIT (as opposed to a function that returns an RPIT), we only want
         // to capture the lifetimes that appear in the bounds. So visit the bounds to find out
         // exactly which ones those are.
@@ -1558,20 +1555,31 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         debug!(?lifetimes_to_remap);
 
-        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
-            let mut new_remapping = FxHashMap::default();
+        let mut new_remapping = FxHashMap::default();
 
-            // If this opaque type is only capturing a subset of the lifetimes (those that appear
-            // in bounds), then create the new lifetime parameters required and create a mapping
-            // from the old `'a` (on the function) to the new `'a` (on the opaque type).
-            collected_lifetimes = lctx.create_lifetime_defs(
-                opaque_ty_def_id,
-                &lifetimes_to_remap,
-                &mut new_remapping,
-            );
-            debug!(?collected_lifetimes);
-            debug!(?new_remapping);
+        // Contains the new lifetime definitions created for the TAIT (if any).
+        // If this opaque type is only capturing a subset of the lifetimes (those that appear in
+        // bounds), then create the new lifetime parameters required and create a mapping from the
+        // old `'a` (on the function) to the new `'a` (on the opaque type).
+        let collected_lifetimes =
+            self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping);
+        debug!(?collected_lifetimes);
+        debug!(?new_remapping);
+
+        // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
+        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
+        let collected_lifetime_mapping: Vec<_> = collected_lifetimes
+            .iter()
+            .map(|(node_id, lifetime)| {
+                let id = self.next_node_id();
+                let lifetime = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
+                let def_id = self.local_def_id(*node_id);
+                (lifetime, def_id)
+            })
+            .collect();
+        debug!(?collected_lifetime_mapping);
 
+        self.with_hir_id_owner(opaque_ty_node_id, |lctx| {
             // Install the remapping from old to new (if any):
             lctx.with_remapping(new_remapping, |lctx| {
                 // This creates HIR lifetime definitions as `hir::GenericParam`, in the given
@@ -1610,6 +1618,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 let hir_bounds = lctx.lower_param_bounds(bounds, itctx);
                 debug!(?hir_bounds);
 
+                let lifetime_mapping = if in_trait {
+                    self.arena.alloc_from_iter(
+                        collected_lifetime_mapping
+                            .iter()
+                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    )
+                } else {
+                    &mut []
+                };
+
                 let opaque_ty_item = hir::OpaqueTy {
                     generics: self.arena.alloc(hir::Generics {
                         params: lifetime_defs,
@@ -1620,6 +1638,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }),
                     bounds: hir_bounds,
                     origin,
+                    lifetime_mapping,
                     in_trait,
                 };
                 debug!(?opaque_ty_item);
@@ -1628,20 +1647,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             })
         });
 
-        // This creates HIR lifetime arguments as `hir::GenericArg`, in the given example `type
-        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing `&['x]`.
-        let lifetimes =
-            self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(|(_, lifetime)| {
-                let id = self.next_node_id();
-                let l = self.new_named_lifetime(lifetime.id, id, lifetime.ident);
-                hir::GenericArg::Lifetime(l)
-            }));
-        debug!(?lifetimes);
-
         // `impl Trait` now just becomes `Foo<'a, 'b, ..>`.
         hir::TyKind::OpaqueDef(
             hir::ItemId { owner_id: hir::OwnerId { def_id: opaque_ty_def_id } },
-            lifetimes,
+            self.arena.alloc_from_iter(
+                collected_lifetime_mapping
+                    .iter()
+                    .map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
+            ),
             in_trait,
         )
     }
@@ -1655,7 +1668,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         span: Span,
         opaque_ty_span: Span,
     ) -> hir::OwnerNode<'hir> {
-        let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(opaque_ty_item);
+        let opaque_ty_item_kind = hir::ItemKind::OpaqueTy(self.arena.alloc(opaque_ty_item));
         // Generate an `type Foo = impl Trait;` declaration.
         trace!("registering opaque type with id {:#?}", opaque_ty_id);
         let opaque_ty_item = hir::Item {
@@ -1983,7 +1996,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             let lifetime = Lifetime { id: outer_node_id, ident };
             collected_lifetimes.push((inner_node_id, lifetime, Some(inner_res)));
         }
-
         debug!(?collected_lifetimes);
 
         // We only want to capture the lifetimes that appear in the bounds. So visit the bounds to
@@ -1993,22 +2005,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let lifetimes_to_remap = lifetime_collector::lifetimes_in_ret_ty(&self.resolver, output);
         debug!(?lifetimes_to_remap);
 
-        self.with_hir_id_owner(opaque_ty_node_id, |this| {
-            // If this opaque type is only capturing a subset of the lifetimes (those that appear
-            // in bounds), then create the new lifetime parameters required and create a mapping
-            // from the old `'a` (on the function) to the new `'a` (on the opaque type).
-            collected_lifetimes.extend(
-                this.create_lifetime_defs(
-                    opaque_ty_def_id,
-                    &lifetimes_to_remap,
-                    &mut new_remapping,
-                )
+        // If this opaque type is only capturing a subset of the lifetimes (those that appear in
+        // bounds), then create the new lifetime parameters required and create a mapping from the
+        // old `'a` (on the function) to the new `'a` (on the opaque type).
+        collected_lifetimes.extend(
+            self.create_lifetime_defs(opaque_ty_def_id, &lifetimes_to_remap, &mut new_remapping)
                 .into_iter()
                 .map(|(new_node_id, lifetime)| (new_node_id, lifetime, None)),
-            );
-            debug!(?collected_lifetimes);
-            debug!(?new_remapping);
+        );
+        debug!(?collected_lifetimes);
+        debug!(?new_remapping);
+
+        // This creates pairs of HIR lifetimes and def_ids. In the given example `type
+        // TestReturn<'a, T, 'x> = impl Debug + 'x`, it creates a collection containing the
+        // new lifetime of the RPIT 'x and the def_id of the lifetime 'x corresponding to
+        // `TestReturn`.
+        let collected_lifetime_mapping: Vec<_> = collected_lifetimes
+            .iter()
+            .map(|(node_id, lifetime, res)| {
+                let id = self.next_node_id();
+                let res = res.unwrap_or(
+                    self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
+                );
+                let lifetime = self.new_named_lifetime_with_res(id, lifetime.ident, res);
+                let def_id = self.local_def_id(*node_id);
+                (lifetime, def_id)
+            })
+            .collect();
+        debug!(?collected_lifetime_mapping);
 
+        self.with_hir_id_owner(opaque_ty_node_id, |this| {
             // Install the remapping from old to new (if any):
             this.with_remapping(new_remapping, |this| {
                 // We have to be careful to get elision right here. The
@@ -2063,6 +2089,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 ));
                 debug!("lower_async_fn_ret_ty: generic_params={:#?}", generic_params);
 
+                let lifetime_mapping = if in_trait {
+                    self.arena.alloc_from_iter(
+                        collected_lifetime_mapping
+                            .iter()
+                            .map(|(lifetime, def_id)| (**lifetime, *def_id)),
+                    )
+                } else {
+                    &mut []
+                };
+
                 let opaque_ty_item = hir::OpaqueTy {
                     generics: this.arena.alloc(hir::Generics {
                         params: generic_params,
@@ -2073,6 +2109,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }),
                     bounds: arena_vec![this; future_bound],
                     origin: hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
+                    lifetime_mapping,
                     in_trait,
                 };
 
@@ -2096,15 +2133,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         //
         // For the "output" lifetime parameters, we just want to
         // generate `'_`.
-        let generic_args = self.arena.alloc_from_iter(collected_lifetimes.into_iter().map(
-            |(_, lifetime, res)| {
-                let id = self.next_node_id();
-                let res = res.unwrap_or(
-                    self.resolver.get_lifetime_res(lifetime.id).unwrap_or(LifetimeRes::Error),
-                );
-                hir::GenericArg::Lifetime(self.new_named_lifetime_with_res(id, lifetime.ident, res))
-            },
-        ));
+        let generic_args = self.arena.alloc_from_iter(
+            collected_lifetime_mapping
+                .iter()
+                .map(|(lifetime, _)| hir::GenericArg::Lifetime(*lifetime)),
+        );
 
         // Create the `Foo<...>` reference itself. Note that the `type
         // Foo = impl Trait` is, internally, created as a child of the
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 591831b59a1a4..6c419471de1b4 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -2664,6 +2664,10 @@ pub struct OpaqueTy<'hir> {
     pub generics: &'hir Generics<'hir>,
     pub bounds: GenericBounds<'hir>,
     pub origin: OpaqueTyOrigin,
+    // Opaques have duplicated lifetimes, this mapping connects the original lifetime with the copy
+    // so we can later generate bidirectional outlives predicates to enforce that these lifetimes
+    // stay in sync.
+    pub lifetime_mapping: &'hir [(Lifetime, LocalDefId)],
     pub in_trait: bool,
 }
 
@@ -3315,7 +3319,7 @@ pub enum ItemKind<'hir> {
     /// A type alias, e.g., `type Foo = Bar<u8>`.
     TyAlias(&'hir Ty<'hir>, &'hir Generics<'hir>),
     /// An opaque `impl Trait` type alias, e.g., `type Foo = impl Bar;`.
-    OpaqueTy(OpaqueTy<'hir>),
+    OpaqueTy(&'hir OpaqueTy<'hir>),
     /// An enum definition, e.g., `enum Foo<A, B> {C<A>, D<B>}`.
     Enum(EnumDef<'hir>, &'hir Generics<'hir>),
     /// A struct definition, e.g., `struct Foo<A> {x: A}`.
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 1886a91bda838..347c1f4637f17 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -502,7 +502,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
             visitor.visit_ty(ty);
             visitor.visit_generics(generics)
         }
-        ItemKind::OpaqueTy(OpaqueTy { ref generics, bounds, .. }) => {
+        ItemKind::OpaqueTy(&OpaqueTy { generics, bounds, .. }) => {
             visitor.visit_id(item.hir_id());
             walk_generics(visitor, generics);
             walk_list!(visitor, visit_param_bound, bounds);
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 5032378923b79..924f6e723e843 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2809,7 +2809,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 let opaque_ty = tcx.hir().item(item_id);
 
                 match opaque_ty.kind {
-                    hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => {
+                    hir::ItemKind::OpaqueTy(&hir::OpaqueTy { origin, .. }) => {
                         let local_def_id = item_id.owner_id.def_id;
                         // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
                         // generate the def_id of an associated type for the trait and return as
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index a7e81f41c6996..346e153a69d02 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -299,7 +299,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
         }
     }
 
-    if let ItemKind::OpaqueTy(hir::OpaqueTy {
+    if let ItemKind::OpaqueTy(&hir::OpaqueTy {
         origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
         in_trait,
         ..
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index e92a0dcc1fb1f..2206f640529ca 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -144,7 +144,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
             Some(tcx.typeck_root_def_id(def_id.to_def_id()))
         }
         Node::Item(item) => match item.kind {
-            ItemKind::OpaqueTy(hir::OpaqueTy {
+            ItemKind::OpaqueTy(&hir::OpaqueTy {
                 origin:
                     hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
                 in_trait,
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index d9b2aacab9d66..b9e71aaa00402 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -2,7 +2,7 @@ use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
 use crate::bounds::Bounds;
 use crate::collect::ItemCtxt;
 use crate::constrained_generic_params as cgp;
-use hir::{HirId, Node};
+use hir::{HirId, Lifetime, Node};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -10,9 +10,9 @@ use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_middle::ty::subst::InternalSubsts;
 use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_middle::ty::{GenericPredicates, ToPredicate};
+use rustc_middle::ty::{GenericPredicates, Generics, ImplTraitInTraitData, ToPredicate};
 use rustc_span::symbol::{sym, Ident};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::{Span, Symbol, DUMMY_SP};
 
 /// Returns a list of all type predicates (explicit and implicit) for the definition with
 /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus
@@ -62,6 +62,54 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
 fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
     use rustc_hir::*;
 
+    match tcx.opt_rpitit_info(def_id.to_def_id()) {
+        Some(ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
+            let opaque_ty_id = tcx.hir().local_def_id_to_hir_id(opaque_def_id.expect_local());
+            let opaque_ty_node = tcx.hir().get(opaque_ty_id);
+            let Node::Item(&Item { kind: ItemKind::OpaqueTy(OpaqueTy { lifetime_mapping, .. }), .. }) = opaque_ty_node else {
+                bug!("unexpected {opaque_ty_node:?}")
+            };
+
+            let mut predicates = Vec::new();
+            compute_bidirectional_outlives_predicates(
+                tcx,
+                def_id,
+                lifetime_mapping.iter().map(|(lifetime, def_id)| {
+                    (*lifetime, (*def_id, lifetime.ident.name, lifetime.ident.span))
+                }),
+                tcx.generics_of(def_id.to_def_id()),
+                &mut predicates,
+            );
+
+            return ty::GenericPredicates {
+                parent: Some(tcx.parent(def_id.to_def_id())),
+                predicates: tcx.arena.alloc_from_iter(predicates),
+            };
+        }
+
+        Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
+            let assoc_item = tcx.associated_item(def_id);
+            let trait_assoc_predicates = tcx.predicates_of(assoc_item.trait_item_def_id.unwrap());
+
+            let impl_assoc_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
+            let impl_def_id = tcx.parent(fn_def_id);
+            let impl_trait_ref_substs =
+                tcx.impl_trait_ref(impl_def_id).unwrap().skip_binder().substs;
+
+            let impl_assoc_substs =
+                impl_assoc_identity_substs.rebase_onto(tcx, impl_def_id, impl_trait_ref_substs);
+
+            let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_substs);
+
+            return ty::GenericPredicates {
+                parent: Some(impl_def_id),
+                predicates: tcx.arena.alloc_from_iter(impl_predicates),
+            };
+        }
+
+        None => {}
+    }
+
     let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
     let node = tcx.hir().get(hir_id);
 
@@ -289,38 +337,22 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
             bug!("unexpected {opaque_ty_node:?}")
         };
         debug!(?lifetimes);
-        for (arg, duplicate) in std::iter::zip(lifetimes, ast_generics.params) {
-            let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
-            let orig_region = icx.astconv().ast_region_to_region(&arg, None);
-            if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
-                // Only early-bound regions can point to the original generic parameter.
-                continue;
-            }
-
-            let hir::GenericParamKind::Lifetime { .. } = duplicate.kind else { continue };
-            let dup_def = duplicate.def_id.to_def_id();
 
-            let Some(dup_index) = generics.param_def_id_to_index(tcx, dup_def) else { bug!() };
+        let lifetime_mapping = std::iter::zip(lifetimes, ast_generics.params)
+            .map(|(arg, dup)| {
+                let hir::GenericArg::Lifetime(arg) = arg else { bug!() };
+                (**arg, dup)
+            })
+            .filter(|(_, dup)| matches!(dup.kind, hir::GenericParamKind::Lifetime { .. }))
+            .map(|(lifetime, dup)| (lifetime, (dup.def_id, dup.name.ident().name, dup.span)));
 
-            let dup_region = ty::Region::new_early_bound(
-                tcx,
-                ty::EarlyBoundRegion {
-                    def_id: dup_def,
-                    index: dup_index,
-                    name: duplicate.name.ident().name,
-                },
-            );
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-            predicates.push((
-                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
-                    .to_predicate(icx.tcx),
-                duplicate.span,
-            ));
-        }
+        compute_bidirectional_outlives_predicates(
+            tcx,
+            def_id,
+            lifetime_mapping,
+            generics,
+            &mut predicates,
+        );
         debug!(?predicates);
     }
 
@@ -330,6 +362,46 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     }
 }
 
+/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
+/// enforce that these lifetimes stay in sync.
+fn compute_bidirectional_outlives_predicates<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item_def_id: LocalDefId,
+    lifetime_mapping: impl Iterator<Item = (Lifetime, (LocalDefId, Symbol, Span))>,
+    generics: &Generics,
+    predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
+) {
+    let icx = ItemCtxt::new(tcx, item_def_id);
+
+    for (arg, (dup_def, name, span)) in lifetime_mapping {
+        let orig_region = icx.astconv().ast_region_to_region(&arg, None);
+        if !matches!(orig_region.kind(), ty::ReEarlyBound(..)) {
+            // There is no late-bound lifetime to actually match up here, since the lifetime doesn't
+            // show up in the opaque's parent's substs.
+            continue;
+        }
+
+        let Some(dup_index) = generics.param_def_id_to_index(icx.tcx, dup_def.to_def_id()) else { bug!() };
+
+        let dup_region = ty::Region::new_early_bound(
+            tcx,
+            ty::EarlyBoundRegion { def_id: dup_def.to_def_id(), index: dup_index, name },
+        );
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_region, dup_region))
+                .to_predicate(tcx),
+            span,
+        ));
+
+        predicates.push((
+            ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_region, orig_region))
+                .to_predicate(tcx),
+            span,
+        ));
+    }
+}
+
 fn const_evaluatable_predicates_of(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
@@ -668,7 +740,7 @@ pub(super) fn type_param_predicates(
                 ItemKind::Fn(.., generics, _)
                 | ItemKind::Impl(&hir::Impl { generics, .. })
                 | ItemKind::TyAlias(_, generics)
-                | ItemKind::OpaqueTy(OpaqueTy {
+                | ItemKind::OpaqueTy(&OpaqueTy {
                     generics,
                     origin: hir::OpaqueTyOrigin::TyAlias { .. },
                     ..
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 3d75df8c69f07..c8b405228a56f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -556,7 +556,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     });
                 }
             }
-            hir::ItemKind::OpaqueTy(hir::OpaqueTy {
+            hir::ItemKind::OpaqueTy(&hir::OpaqueTy {
                 origin: hir::OpaqueTyOrigin::FnReturn(parent) | hir::OpaqueTyOrigin::AsyncFn(parent),
                 generics,
                 ..
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 318d0d0c22397..bd92ee4b550a3 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -435,7 +435,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<Ty
                     ..
                 }) => opaque::find_opaque_ty_constraints_for_tait(tcx, def_id),
                 // Opaque types desugared from `impl Trait`.
-                ItemKind::OpaqueTy(OpaqueTy {
+                ItemKind::OpaqueTy(&OpaqueTy {
                     origin:
                         hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner),
                     in_trait,
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 5b731641e9d53..b59458bbf35cc 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -340,12 +340,6 @@ fn associated_type_for_impl_trait_in_trait(
         }
     });
 
-    // There are no predicates for the synthesized associated type.
-    trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
-        parent: Some(trait_def_id.to_def_id()),
-        predicates: &[],
-    });
-
     // There are no inferred outlives for the synthesized associated type.
     trait_assoc_ty.inferred_outlives_of(&[]);
 
@@ -424,12 +418,6 @@ fn associated_type_for_impl_trait_in_impl(
         }
     });
 
-    // There are no predicates for the synthesized associated type.
-    impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
-        parent: Some(impl_local_def_id.to_def_id()),
-        predicates: &[],
-    });
-
     // There are no inferred outlives for the synthesized associated type.
     impl_assoc_ty.inferred_outlives_of(&[]);
 
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 2daab520a2f73..2b391f94a6335 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -131,7 +131,9 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
     if let Some(ImplTraitInTraitData::Trait { fn_def_id, .. })
     | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) = tcx.opt_rpitit_info(def_id)
     {
-        predicates = tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates;
+        // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): Should not need to add the predicates
+        // from the parent fn to our assumptions
+        predicates.extend(tcx.predicates_of(fn_def_id).instantiate_identity(tcx).predicates);
     }
 
     // Finally, we have to normalize the bounds in the environment, in
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
index d5481d277e40a..9869a8d71c278 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.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)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
index f298e45d2390b..ecbd1910ac4ba 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes.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)]
 #![allow(incomplete_features)]