about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs10
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs70
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0657.md59
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs68
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs12
-rw-r--r--compiler/rustc_middle/src/traits/solve/inspect/format.rs47
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs2
-rw-r--r--library/core/src/ptr/const_ptr.rs13
-rw-r--r--library/core/src/ptr/mut_ptr.rs13
-rw-r--r--library/core/src/slice/mod.rs14
-rw-r--r--src/tools/miri/src/machine.rs15
-rw-r--r--tests/ui/error-codes/E0657.rs4
-rw-r--r--tests/ui/error-codes/E0657.stderr16
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds.rs6
-rw-r--r--tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr9
-rw-r--r--tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs2
-rw-r--r--tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr3
-rw-r--r--tests/ui/impl-trait/implicit-capture-late.stderr8
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs18
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr67
-rw-r--r--tests/ui/impl-trait/issues/issue-54895.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-54895.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-67830.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-67830.stderr3
-rw-r--r--tests/ui/impl-trait/issues/issue-88236-2.rs6
-rw-r--r--tests/ui/impl-trait/issues/issue-88236-2.stderr7
-rw-r--r--tests/ui/impl-trait/issues/issue-88236.rs2
-rw-r--r--tests/ui/impl-trait/issues/issue-88236.stderr3
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.rs8
-rw-r--r--tests/ui/impl-trait/nested-rpit-hrtb.stderr10
-rw-r--r--tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs26
-rw-r--r--tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/escaping-bound-var.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/escaping-bound-var.stderr7
-rw-r--r--tests/ui/type-alias-impl-trait/variance.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/variance.stderr16
47 files changed, 418 insertions, 214 deletions
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 16122e5557e..d1f32087908 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -260,35 +260,29 @@ pub unsafe fn create_module<'ll>(
     }
 
     if let Some(BranchProtection { bti, pac_ret }) = sess.opts.unstable_opts.branch_protection {
-        let behavior = if llvm_version >= (15, 0, 0) {
-            llvm::LLVMModFlagBehavior::Min
-        } else {
-            llvm::LLVMModFlagBehavior::Error
-        };
-
         if sess.target.arch == "aarch64" {
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"branch-target-enforcement".as_ptr().cast(),
                 bti.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address".as_ptr().cast(),
                 pac_ret.is_some().into(),
             );
             let pac_opts = pac_ret.unwrap_or(PacRet { leaf: false, key: PAuthKey::A });
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address-all".as_ptr().cast(),
                 pac_opts.leaf.into(),
             );
             llvm::LLVMRustAddModuleFlag(
                 llmod,
-                behavior,
+                llvm::LLVMModFlagBehavior::Min,
                 c"sign-return-address-with-bkey".as_ptr().cast(),
                 u32::from(pac_opts.key == PAuthKey::B),
             );
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 2161bf61daa..1a3c70cedd0 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -510,11 +510,13 @@ fn get_argc_argv<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         // Params for UEFI
         let param_handle = bx.get_param(0);
         let param_system_table = bx.get_param(1);
+        let ptr_size = bx.tcx().data_layout.pointer_size;
+        let ptr_align = bx.tcx().data_layout.pointer_align.abi;
         let arg_argc = bx.const_int(cx.type_isize(), 2);
-        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), Align::ONE);
-        bx.store(param_handle, arg_argv, Align::ONE);
-        let arg_argv_el1 = bx.gep(cx.type_ptr(), arg_argv, &[bx.const_int(cx.type_int(), 1)]);
-        bx.store(param_system_table, arg_argv_el1, Align::ONE);
+        let arg_argv = bx.alloca(cx.type_array(cx.type_ptr(), 2), ptr_align);
+        bx.store(param_handle, arg_argv, ptr_align);
+        let arg_argv_el1 = bx.inbounds_ptradd(arg_argv, bx.const_usize(ptr_size.bytes()));
+        bx.store(param_system_table, arg_argv_el1, ptr_align);
         (arg_argc, arg_argv)
     } else if cx.sess().target.main_needs_argc_argv {
         // Params from native `main()` used as args for rust start function
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 864241fbd4a..6736fc749c0 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -227,7 +227,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         if self.tcx.has_attr(def_id, sym::rustc_const_panic_str)
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
-            let args = self.copy_fn_args(args)?;
+            let args = self.copy_fn_args(args);
             // &str or &&str
             assert!(args.len() == 1);
 
@@ -254,7 +254,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
 
             return Ok(Some(new_instance));
         } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
-            let args = self.copy_fn_args(args)?;
+            let args = self.copy_fn_args(args);
             // For align_offset, we replace the function call if the pointer has no address.
             match self.align_offset(instance, &args, dest, ret)? {
                 ControlFlow::Continue(()) => return Ok(Some(instance)),
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index c798f1ce018..90a654a1229 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -472,11 +472,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// argument/return value was actually copied or passed in-place..
     fn protect_in_place_function_argument(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        place: &PlaceTy<'tcx, Self::Provenance>,
+        mplace: &MPlaceTy<'tcx, Self::Provenance>,
     ) -> InterpResult<'tcx> {
         // Without an aliasing model, all we can do is put `Uninit` into the place.
         // Conveniently this also ensures that the place actually points to suitable memory.
-        ecx.write_uninit(place)
+        ecx.write_uninit(mplace)
     }
 
     /// Called immediately before a new stack frame gets pushed.
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index f2b1ec42567..bafb8cb0018 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,5 +1,7 @@
 use std::borrow::Cow;
 
+use either::Either;
+
 use rustc_middle::{
     mir,
     ty::{
@@ -29,14 +31,14 @@ pub enum FnArg<'tcx, Prov: Provenance = CtfeProvenance> {
     Copy(OpTy<'tcx, Prov>),
     /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
     /// make the place inaccessible for the duration of the function call.
-    InPlace(PlaceTy<'tcx, Prov>),
+    InPlace(MPlaceTy<'tcx, Prov>),
 }
 
 impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
     pub fn layout(&self) -> &TyAndLayout<'tcx> {
         match self {
             FnArg::Copy(op) => &op.layout,
-            FnArg::InPlace(place) => &place.layout,
+            FnArg::InPlace(mplace) => &mplace.layout,
         }
     }
 }
@@ -44,13 +46,10 @@ impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
     /// original memory occurs.
-    pub fn copy_fn_arg(
-        &self,
-        arg: &FnArg<'tcx, M::Provenance>,
-    ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
+    pub fn copy_fn_arg(&self, arg: &FnArg<'tcx, M::Provenance>) -> OpTy<'tcx, M::Provenance> {
         match arg {
-            FnArg::Copy(op) => Ok(op.clone()),
-            FnArg::InPlace(place) => self.place_to_op(place),
+            FnArg::Copy(op) => op.clone(),
+            FnArg::InPlace(mplace) => mplace.clone().into(),
         }
     }
 
@@ -59,7 +58,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     pub fn copy_fn_args(
         &self,
         args: &[FnArg<'tcx, M::Provenance>],
-    ) -> InterpResult<'tcx, Vec<OpTy<'tcx, M::Provenance>>> {
+    ) -> Vec<OpTy<'tcx, M::Provenance>> {
         args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
     }
 
@@ -70,7 +69,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
         Ok(match arg {
             FnArg::Copy(op) => FnArg::Copy(self.project_field(op, field)?),
-            FnArg::InPlace(place) => FnArg::InPlace(self.project_field(place, field)?),
+            FnArg::InPlace(mplace) => FnArg::InPlace(self.project_field(mplace, field)?),
         })
     }
 
@@ -238,10 +237,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, Vec<FnArg<'tcx, M::Provenance>>> {
         ops.iter()
             .map(|op| {
-                Ok(match &op.node {
-                    mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?),
-                    _ => FnArg::Copy(self.eval_operand(&op.node, None)?),
-                })
+                let arg = match &op.node {
+                    mir::Operand::Copy(_) | mir::Operand::Constant(_) => {
+                        // Make a regular copy.
+                        let op = self.eval_operand(&op.node, None)?;
+                        FnArg::Copy(op)
+                    }
+                    mir::Operand::Move(place) => {
+                        // If this place lives in memory, preserve its location.
+                        // We call `place_to_op` which will be an `MPlaceTy` whenever there exists
+                        // an mplace for this place. (This is in contrast to `PlaceTy::as_mplace_or_local`
+                        // which can return a local even if that has an mplace.)
+                        let place = self.eval_place(*place)?;
+                        let op = self.place_to_op(&place)?;
+
+                        match op.as_mplace_or_imm() {
+                            Either::Left(mplace) => FnArg::InPlace(mplace),
+                            Either::Right(_imm) => {
+                                // This argument doesn't live in memory, so there's no place
+                                // to make inaccessible during the call.
+                                // We rely on there not being any stray `PlaceTy` that would let the
+                                // caller directly access this local!
+                                // This is also crucial for tail calls, where we want the `FnArg` to
+                                // stay valid when the old stack frame gets popped.
+                                FnArg::Copy(op)
+                            }
+                        }
+                    }
+                };
+
+                Ok(arg)
             })
             .collect()
     }
@@ -451,7 +476,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // We work with a copy of the argument for now; if this is in-place argument passing, we
         // will later protect the source it comes from. This means the callee cannot observe if we
         // did in-place of by-copy argument passing, except for pointer equality tests.
-        let caller_arg_copy = self.copy_fn_arg(caller_arg)?;
+        let caller_arg_copy = self.copy_fn_arg(caller_arg);
         if !already_live {
             let local = callee_arg.as_local().unwrap();
             let meta = caller_arg_copy.meta();
@@ -469,8 +494,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // specifically.)
         self.copy_op_allow_transmute(&caller_arg_copy, &callee_arg)?;
         // If this was an in-place pass, protect the place it comes from for the duration of the call.
-        if let FnArg::InPlace(place) = caller_arg {
-            M::protect_in_place_function_argument(self, place)?;
+        if let FnArg::InPlace(mplace) = caller_arg {
+            M::protect_in_place_function_argument(self, mplace)?;
         }
         Ok(())
     }
@@ -517,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 M::call_intrinsic(
                     self,
                     instance,
-                    &self.copy_fn_args(args)?,
+                    &self.copy_fn_args(args),
                     destination,
                     target,
                     unwind,
@@ -594,8 +619,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             .map(|arg| (
                                 arg.layout().ty,
                                 match arg {
-                                    FnArg::Copy(op) => format!("copy({:?})", *op),
-                                    FnArg::InPlace(place) => format!("in-place({:?})", *place),
+                                    FnArg::Copy(op) => format!("copy({op:?})"),
+                                    FnArg::InPlace(mplace) => format!("in-place({mplace:?})"),
                                 }
                             ))
                             .collect::<Vec<_>>()
@@ -717,8 +742,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             callee_ty: callee_fn_abi.ret.layout.ty
                         });
                     }
+
                     // Protect return place for in-place return value passing.
-                    M::protect_in_place_function_argument(self, &destination.clone().into())?;
+                    M::protect_in_place_function_argument(self, &destination)?;
 
                     // Don't forget to mark "initially live" locals as live.
                     self.storage_live_for_always_live_locals()?;
@@ -741,7 +767,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // An `InPlace` does nothing here, we keep the original receiver intact. We can't
                 // really pass the argument in-place anyway, and we are constructing a new
                 // `Immediate` receiver.
-                let mut receiver = self.copy_fn_arg(&args[0])?;
+                let mut receiver = self.copy_fn_arg(&args[0]);
                 let receiver_place = loop {
                     match receiver.layout.ty.kind() {
                         ty::Ref(..) | ty::RawPtr(..) => {
diff --git a/compiler/rustc_error_codes/src/error_codes/E0657.md b/compiler/rustc_error_codes/src/error_codes/E0657.md
index 7fe48c51147..477d8e8bb6d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0657.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0657.md
@@ -1,57 +1,26 @@
-A lifetime bound on a trait implementation was captured at an incorrect place.
+An `impl Trait` captured a higher-ranked lifetime, which is not supported.
+
+Currently, `impl Trait` types are only allowed to capture lifetimes from
+their parent items, and not from any `for<'a>` binders in scope.
 
 Erroneous code example:
 
 ```compile_fail,E0657
-trait Id<T> {}
-trait Lt<'a> {}
-
-impl<'a> Lt<'a> for () {}
-impl<T> Id<T> for T {}
-
-fn free_fn_capture_hrtb_in_impl_trait()
-    -> Box<for<'a> Id<impl Lt<'a>>> // error!
-{
-    Box::new(())
-}
+trait BorrowInto<'a> {
+    type Target;
 
-struct Foo;
-impl Foo {
-    fn impl_fn_capture_hrtb_in_impl_trait()
-        -> Box<for<'a> Id<impl Lt<'a>>> // error!
-    {
-        Box::new(())
-    }
+    fn borrow_into(&'a self) -> Self::Target;
 }
-```
 
-Here, you have used the inappropriate lifetime in the `impl Trait`,
-The `impl Trait` can only capture lifetimes bound at the fn or impl
-level.
+impl<'a> BorrowInto<'a> for () {
+    type Target = &'a ();
 
-To fix this we have to define the lifetime at the function or impl
-level and use that lifetime in the `impl Trait`. For example you can
-define the lifetime at the function:
-
-```
-trait Id<T> {}
-trait Lt<'a> {}
-
-impl<'a> Lt<'a> for () {}
-impl<T> Id<T> for T {}
-
-fn free_fn_capture_hrtb_in_impl_trait<'b>()
-    -> Box<for<'a> Id<impl Lt<'b>>> // ok!
-{
-    Box::new(())
+    fn borrow_into(&'a self) -> Self::Target {
+        self
+    }
 }
 
-struct Foo;
-impl Foo {
-    fn impl_fn_capture_hrtb_in_impl_trait<'b>()
-        -> Box<for<'a> Id<impl Lt<'b>>> // ok!
-    {
-        Box::new(())
-    }
+fn opaque() -> impl for<'a> BorrowInto<'a, Target = impl Sized + 'a> {
+    ()
 }
 ```
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index e376411cd95..bad472dcb5c 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -312,6 +312,10 @@ hir_analysis_only_current_traits_primitive = only traits defined in the current
 
 hir_analysis_only_current_traits_ty = `{$ty}` is not defined in the current crate
 
+hir_analysis_opaque_captures_higher_ranked_lifetime = `impl Trait` cannot capture {$bad_place}
+    .label = `impl Trait` implicitly captures all lifetimes in scope
+    .note = lifetime declared here
+
 hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a temporary means of controlling which traits can use parenthetical notation
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to use it
 
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index f708c66cfa4..ec9e928ce59 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -521,14 +521,6 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         )
         .fold_with(&mut collector);
 
-    if !unnormalized_trait_sig.output().references_error() {
-        debug_assert_ne!(
-            collector.types.len(),
-            0,
-            "expect >1 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
-        );
-    }
-
     let trait_sig = ocx.normalize(&misc_cause, param_env, unnormalized_trait_sig);
     trait_sig.error_reported()?;
     let trait_return_ty = trait_sig.output();
@@ -647,6 +639,13 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
         }
     }
 
+    if !unnormalized_trait_sig.output().references_error() {
+        debug_assert!(
+            !collector.types.is_empty(),
+            "expect >0 RPITITs in call to `collect_return_position_impl_trait_in_trait_tys`"
+        );
+    }
+
     // FIXME: This has the same issue as #108544, but since this isn't breaking
     // existing code, I'm not particularly inclined to do the same hack as above
     // where we process wf obligations manually. This can be fixed in a forward-
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 9464e3746e9..7936621c868 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -9,7 +9,6 @@
 use core::ops::ControlFlow;
 use rustc_ast::visit::walk_list;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
-use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
@@ -669,34 +668,47 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                     // and ban them. Type variables instantiated inside binders aren't
                     // well-supported at the moment, so this doesn't work.
                     // In the future, this should be fixed and this error should be removed.
-                    let def = self.map.defs.get(&lifetime.hir_id).cloned();
-                    let Some(ResolvedArg::LateBound(_, _, def_id)) = def else { continue };
-                    let Some(def_id) = def_id.as_local() else { continue };
-                    let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-                    // Ensure that the parent of the def is an item, not HRTB
-                    let parent_id = self.tcx.parent_hir_id(hir_id);
-                    if !parent_id.is_owner() {
-                        struct_span_code_err!(
-                            self.tcx.dcx(),
-                            lifetime.ident.span,
-                            E0657,
-                            "`impl Trait` can only capture lifetimes bound at the fn or impl level"
-                        )
-                        .emit();
-                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                    }
-                    if let hir::Node::Item(hir::Item {
-                        kind: hir::ItemKind::OpaqueTy { .. }, ..
-                    }) = self.tcx.hir_node(parent_id)
+                    let def = self.map.defs.get(&lifetime.hir_id).copied();
+                    let Some(ResolvedArg::LateBound(_, _, lifetime_def_id)) = def else { continue };
+                    let Some(lifetime_def_id) = lifetime_def_id.as_local() else { continue };
+                    let lifetime_hir_id = self.tcx.local_def_id_to_hir_id(lifetime_def_id);
+
+                    let bad_place = match self.tcx.hir_node(self.tcx.parent_hir_id(lifetime_hir_id))
                     {
-                        self.tcx.dcx().struct_span_err(
-                            lifetime.ident.span,
-                            "higher kinded lifetime bounds on nested opaque types are not supported yet",
-                        )
-                        .with_span_note(self.tcx.def_span(def_id), "lifetime declared here")
-                        .emit();
-                        self.uninsert_lifetime_on_error(lifetime, def.unwrap());
-                    }
+                        // Opaques do not declare their own lifetimes, so if a lifetime comes from an opaque
+                        // it must be a reified late-bound lifetime from a trait goal.
+                        hir::Node::Item(hir::Item {
+                            kind: hir::ItemKind::OpaqueTy { .. }, ..
+                        }) => "higher-ranked lifetime from outer `impl Trait`",
+                        // Other items are fine.
+                        hir::Node::Item(_) | hir::Node::TraitItem(_) | hir::Node::ImplItem(_) => {
+                            continue;
+                        }
+                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(_), .. }) => {
+                            "higher-ranked lifetime from function pointer"
+                        }
+                        hir::Node::Ty(hir::Ty { kind: hir::TyKind::TraitObject(..), .. }) => {
+                            "higher-ranked lifetime from `dyn` type"
+                        }
+                        _ => "higher-ranked lifetime",
+                    };
+
+                    let (span, label) = if lifetime.ident.span == self.tcx.def_span(lifetime_def_id)
+                    {
+                        let opaque_span = self.tcx.def_span(item_id.owner_id);
+                        (opaque_span, Some(opaque_span))
+                    } else {
+                        (lifetime.ident.span, None)
+                    };
+
+                    // Ensure that the parent of the def is an item, not HRTB
+                    self.tcx.dcx().emit_err(errors::OpaqueCapturesHigherRankedLifetime {
+                        span,
+                        label,
+                        decl_span: self.tcx.def_span(lifetime_def_id),
+                        bad_place,
+                    });
+                    self.uninsert_lifetime_on_error(lifetime, def.unwrap());
                 }
             }
             _ => intravisit::walk_ty(self, ty),
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 5330260fbf5..26349cd1c65 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1607,3 +1607,15 @@ pub struct UnnamedFieldsReprFieldDefined {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_opaque_captures_higher_ranked_lifetime, code = E0657)]
+pub struct OpaqueCapturesHigherRankedLifetime {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub label: Option<Span>,
+    #[note]
+    pub decl_span: Span,
+    pub bad_place: &'static str,
+}
diff --git a/compiler/rustc_middle/src/traits/solve/inspect/format.rs b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
index 89c5eb517e5..8d3109a7b28 100644
--- a/compiler/rustc_middle/src/traits/solve/inspect/format.rs
+++ b/compiler/rustc_middle/src/traits/solve/inspect/format.rs
@@ -4,22 +4,31 @@ pub(super) struct ProofTreeFormatter<'a, 'b> {
     f: &'a mut (dyn Write + 'b),
 }
 
+enum IndentorState {
+    StartWithNewline,
+    OnNewline,
+    Inline,
+}
+
 /// A formatter which adds 4 spaces of indentation to its input before
 /// passing it on to its nested formatter.
 ///
 /// We can use this for arbitrary levels of indentation by nesting it.
 struct Indentor<'a, 'b> {
     f: &'a mut (dyn Write + 'b),
-    on_newline: bool,
+    state: IndentorState,
 }
 
 impl Write for Indentor<'_, '_> {
     fn write_str(&mut self, s: &str) -> std::fmt::Result {
         for line in s.split_inclusive('\n') {
-            if self.on_newline {
-                self.f.write_str("    ")?;
+            match self.state {
+                IndentorState::StartWithNewline => self.f.write_str("\n    ")?,
+                IndentorState::OnNewline => self.f.write_str("    ")?,
+                IndentorState::Inline => {}
             }
-            self.on_newline = line.ends_with('\n');
+            self.state =
+                if line.ends_with('\n') { IndentorState::OnNewline } else { IndentorState::Inline };
             self.f.write_str(line)?;
         }
 
@@ -32,11 +41,15 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
         ProofTreeFormatter { f }
     }
 
-    fn nested<F, R>(&mut self, func: F) -> R
+    fn nested<F>(&mut self, func: F) -> std::fmt::Result
     where
-        F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> R,
+        F: FnOnce(&mut ProofTreeFormatter<'_, '_>) -> std::fmt::Result,
     {
-        func(&mut ProofTreeFormatter { f: &mut Indentor { f: self.f, on_newline: true } })
+        write!(self.f, " {{")?;
+        func(&mut ProofTreeFormatter {
+            f: &mut Indentor { f: self.f, state: IndentorState::StartWithNewline },
+        })?;
+        writeln!(self.f, "}}")
     }
 
     pub(super) fn format_goal_evaluation(&mut self, eval: &GoalEvaluation<'_>) -> std::fmt::Result {
@@ -47,7 +60,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
                 IsNormalizesToHack::Yes => "NORMALIZES-TO HACK GOAL",
             },
         };
-        writeln!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
+        write!(self.f, "{}: {:?}", goal_text, eval.uncanonicalized_goal)?;
         self.nested(|this| this.format_canonical_goal_evaluation(&eval.evaluation))
     }
 
@@ -69,7 +82,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
             }
             CanonicalGoalEvaluationKind::Evaluation { revisions } => {
                 for (n, step) in revisions.iter().enumerate() {
-                    writeln!(self.f, "REVISION {n}")?;
+                    write!(self.f, "REVISION {n}")?;
                     self.nested(|this| this.format_evaluation_step(step))?;
                 }
                 writeln!(self.f, "RESULT: {:?}", eval.result)
@@ -88,25 +101,25 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
     pub(super) fn format_probe(&mut self, probe: &Probe<'_>) -> std::fmt::Result {
         match &probe.kind {
             ProbeKind::Root { result } => {
-                writeln!(self.f, "ROOT RESULT: {result:?}")
+                write!(self.f, "ROOT RESULT: {result:?}")
             }
             ProbeKind::NormalizedSelfTyAssembly => {
-                writeln!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
+                write!(self.f, "NORMALIZING SELF TY FOR ASSEMBLY:")
             }
             ProbeKind::UnsizeAssembly => {
-                writeln!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
+                write!(self.f, "ASSEMBLING CANDIDATES FOR UNSIZING:")
             }
             ProbeKind::UpcastProjectionCompatibility => {
-                writeln!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
+                write!(self.f, "PROBING FOR PROJECTION COMPATIBILITY FOR UPCASTING:")
             }
             ProbeKind::CommitIfOk => {
-                writeln!(self.f, "COMMIT_IF_OK:")
+                write!(self.f, "COMMIT_IF_OK:")
             }
             ProbeKind::MiscCandidate { name, result } => {
-                writeln!(self.f, "CANDIDATE {name}: {result:?}")
+                write!(self.f, "CANDIDATE {name}: {result:?}")
             }
             ProbeKind::TraitCandidate { source, result } => {
-                writeln!(self.f, "CANDIDATE {source:?}: {result:?}")
+                write!(self.f, "CANDIDATE {source:?}: {result:?}")
             }
         }?;
 
@@ -137,7 +150,7 @@ impl<'a, 'b> ProofTreeFormatter<'a, 'b> {
         writeln!(self.f, "TRY_EVALUATE_ADDED_GOALS: {:?}", added_goals_evaluation.result)?;
 
         for (n, iterations) in added_goals_evaluation.evaluations.iter().enumerate() {
-            writeln!(self.f, "ITERATION {n}")?;
+            write!(self.f, "ITERATION {n}")?;
             self.nested(|this| {
                 for goal_evaluation in iterations {
                     this.format_goal_evaluation(goal_evaluation)?;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 2e66d4d0ab0..3b6e15fad46 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -3253,6 +3253,7 @@ impl ToJson for Target {
         }
 
         target_val!(llvm_target);
+        target_val!(description);
         d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
         target_val!(arch);
         target_val!(data_layout);
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index 12eba149258..29c191fc9ab 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -7,7 +7,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
-        description: None,
+        description: Some("ARM64 Windows MSVC".into()),
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 28b2345874a..0ba486417ff 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -23,7 +23,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        description: None,
+        description: Some("32-bit MSVC (Windows 7+)".into()),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 1990c91bdcc..081b4c5364c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -23,7 +23,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        description: None,
+        description: Some("32-bit Windows 7 support".into()),
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
index 31a01f5cbff..bb2555bb1a5 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
@@ -13,7 +13,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
-        description: None,
+        description: Some("ARM32 Windows MSVC".into()),
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index c8d01a912cb..c066c453feb 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -10,7 +10,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        description: None,
+        description: Some("64-bit MSVC (Windows 7+)".into()),
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
index f0c1afcdce8..813802e2320 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
@@ -9,7 +9,7 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-win7-windows-msvc".into(),
-        description: None,
+        description: Some("64-bit Windows 7 support".into()),
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index f2566fe9bcc..0c69bf2aef9 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1326,9 +1326,7 @@ impl<T: ?Sized> *const T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::MAX`. It is permissible for the implementation to *always*
-    /// return `usize::MAX`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
+    /// `usize::MAX`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `wrapping_add` method.
@@ -1337,6 +1335,15 @@ impl<T: ?Sized> *const T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
+    /// When this is called during compile-time evaluation (which is unstable), the implementation
+    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
+    /// actual alignment of pointers is not known yet during compile-time, so an offset with
+    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
+    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
+    /// known, so the execution has to be correct for either choice. It is therefore impossible to
+    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
+    /// for unstable APIs.)
+    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 8b0b22a02f2..5ce3b1f298c 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1589,9 +1589,7 @@ impl<T: ?Sized> *mut T {
     /// `align`.
     ///
     /// If it is not possible to align the pointer, the implementation returns
-    /// `usize::MAX`. It is permissible for the implementation to *always*
-    /// return `usize::MAX`. Only your algorithm's performance can depend
-    /// on getting a usable offset here, not its correctness.
+    /// `usize::MAX`.
     ///
     /// The offset is expressed in number of `T` elements, and not bytes. The value returned can be
     /// used with the `wrapping_add` method.
@@ -1600,6 +1598,15 @@ impl<T: ?Sized> *mut T {
     /// beyond the allocation that the pointer points into. It is up to the caller to ensure that
     /// the returned offset is correct in all terms other than alignment.
     ///
+    /// When this is called during compile-time evaluation (which is unstable), the implementation
+    /// may return `usize::MAX` in cases where that can never happen at runtime. This is because the
+    /// actual alignment of pointers is not known yet during compile-time, so an offset with
+    /// guaranteed alignment can sometimes not be computed. For example, a buffer declared as `[u8;
+    /// N]` might be allocated at an odd or an even address, but at compile-time this is not yet
+    /// known, so the execution has to be correct for either choice. It is therefore impossible to
+    /// find an offset that is guaranteed to be 2-aligned. (This behavior is subject to change, as usual
+    /// for unstable APIs.)
+    ///
     /// # Panics
     ///
     /// The function panics if `align` is not a power-of-two.
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 643b7971a66..2d5e091feaa 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3786,11 +3786,8 @@ impl<T> [T] {
     /// maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
-    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
-    /// maximal middle part, that is because code is running in a context where performance does not
-    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
-    /// in a default (debug or release) execution *will* return a maximal middle part.
+    /// slice of a new type, and the suffix slice. The middle part will be as big as possible under
+    /// the given alignment constraint and element size.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
@@ -3854,11 +3851,8 @@ impl<T> [T] {
     /// types is maintained.
     ///
     /// This method splits the slice into three distinct slices: prefix, correctly aligned middle
-    /// slice of a new type, and the suffix slice. How exactly the slice is split up is not
-    /// specified; the middle part may be smaller than necessary. However, if this fails to return a
-    /// maximal middle part, that is because code is running in a context where performance does not
-    /// matter, such as a sanitizer attempting to find alignment bugs. Regular code running
-    /// in a default (debug or release) execution *will* return a maximal middle part.
+    /// slice of a new type, and the suffix slice. The middle part will be as big as possible under
+    /// the given alignment constraint and element size.
     ///
     /// This method has no purpose when either input element `T` or output element `U` are
     /// zero-sized and will return the original slice without splitting anything.
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index c3c3a815856..19d02c6f746 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -8,7 +8,6 @@ use std::fmt;
 use std::path::Path;
 use std::process;
 
-use either::Either;
 use rand::rngs::StdRng;
 use rand::Rng;
 use rand::SeedableRng;
@@ -962,7 +961,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
             // foreign function
             // Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
-            let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+            let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit?
             let link_name = ecx.item_link_name(instance.def_id());
             return ecx.emulate_foreign_item(link_name, abi, &args, dest, ret, unwind);
         }
@@ -981,7 +980,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
-        let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+        let args = ecx.copy_fn_args(args); // FIXME: Should `InPlace` arguments be reset to uninit?
         ecx.emulate_dyn_sym(fn_val, abi, &args, dest, ret, unwind)
     }
 
@@ -1334,18 +1333,12 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
 
     fn protect_in_place_function_argument(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        place: &PlaceTy<'tcx, Provenance>,
+        place: &MPlaceTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         // If we have a borrow tracker, we also have it set up protection so that all reads *and
         // writes* during this call are insta-UB.
         let protected_place = if ecx.machine.borrow_tracker.is_some() {
-            // Have to do `to_op` first because a `Place::Local` doesn't imply the local doesn't have an address.
-            if let Either::Left(place) = ecx.place_to_op(place)?.as_mplace_or_imm() {
-                ecx.protect_place(&place)?.into()
-            } else {
-                // Locals that don't have their address taken are as protected as they can ever be.
-                place.clone()
-            }
+            ecx.protect_place(&place)?.into()
         } else {
             // No borrow tracker.
             place.clone()
diff --git a/tests/ui/error-codes/E0657.rs b/tests/ui/error-codes/E0657.rs
index cb11de13f73..212c1d9e581 100644
--- a/tests/ui/error-codes/E0657.rs
+++ b/tests/ui/error-codes/E0657.rs
@@ -8,7 +8,7 @@ impl<T> Id<T> for T {}
 
 fn free_fn_capture_hrtb_in_impl_trait()
     -> Box<for<'a> Id<impl Lt<'a>>>
-        //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level [E0657]
+        //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 {
     Box::new(())
 }
@@ -17,7 +17,7 @@ struct Foo;
 impl Foo {
     fn impl_fn_capture_hrtb_in_impl_trait()
         -> Box<for<'a> Id<impl Lt<'a>>>
-            //~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+            //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
     {
         Box::new(())
     }
diff --git a/tests/ui/error-codes/E0657.stderr b/tests/ui/error-codes/E0657.stderr
index df76b45a589..c539007cdcf 100644
--- a/tests/ui/error-codes/E0657.stderr
+++ b/tests/ui/error-codes/E0657.stderr
@@ -1,14 +1,26 @@
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
   --> $DIR/E0657.rs:10:31
    |
 LL |     -> Box<for<'a> Id<impl Lt<'a>>>
    |                               ^^
+   |
+note: lifetime declared here
+  --> $DIR/E0657.rs:10:16
+   |
+LL |     -> Box<for<'a> Id<impl Lt<'a>>>
+   |                ^^
 
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
   --> $DIR/E0657.rs:19:35
    |
 LL |         -> Box<for<'a> Id<impl Lt<'a>>>
    |                                   ^^
+   |
+note: lifetime declared here
+  --> $DIR/E0657.rs:19:20
+   |
+LL |         -> Box<for<'a> Id<impl Lt<'a>>>
+   |                    ^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
index 06c3d9ad434..a9ea657f10e 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.rs
@@ -2,19 +2,19 @@
 use std::fmt::Debug;
 
 fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
 
 fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
 
 fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
diff --git a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
index 959d6577d9a..bdb099619b7 100644
--- a/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
+++ b/tests/ui/impl-trait/impl-fn-hrtb-bounds.stderr
@@ -10,7 +10,7 @@ help: consider using the `'static` lifetime, but this is uncommon unless you're
 LL | fn d() -> impl Fn() -> (impl Debug + 'static) {
    |                                      ~~~~~~~
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:4:41
    |
 LL | fn a() -> impl Fn(&u8) -> (impl Debug + '_) {
@@ -31,7 +31,7 @@ LL |     |x| x
    |      |return type of closure is impl Debug + '2
    |      has type `&'1 u8`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:10:52
    |
 LL | fn b() -> impl for<'a> Fn(&'a u8) -> (impl Debug + 'a) {
@@ -52,7 +52,7 @@ LL |     |x| x
    |      |return type of closure is impl Debug + '2
    |      has type `&'1 u8`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-hrtb-bounds.rs:16:52
    |
 LL | fn c() -> impl for<'a> Fn(&'a u8) -> (impl Debug + '_) {
@@ -75,4 +75,5 @@ LL |     |x| x
 
 error: aborting due to 7 previous errors
 
-For more information about this error, try `rustc --explain E0106`.
+Some errors have detailed explanations: E0106, E0657.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
index a4a1f1dcee1..ef9d8733509 100644
--- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
+++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.rs
@@ -3,7 +3,7 @@ use std::fmt::Debug;
 
 fn a() -> impl Fn(&u8) -> impl Debug + '_ {
     //~^ ERROR ambiguous `+` in a type
-    //~| ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~| ERROR cannot capture higher-ranked lifetime from outer `impl Trait`
     |x| x
     //~^ ERROR lifetime may not live long enough
 }
diff --git a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
index e18e89700b4..3881b37a0cb 100644
--- a/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
+++ b/tests/ui/impl-trait/impl-fn-parsing-ambiguities.stderr
@@ -10,7 +10,7 @@ error: ambiguous `+` in a type
 LL | fn b() -> impl Fn() -> impl Debug + Send {
    |                        ^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(impl Debug + Send)`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/impl-fn-parsing-ambiguities.rs:4:40
    |
 LL | fn a() -> impl Fn(&u8) -> impl Debug + '_ {
@@ -33,3 +33,4 @@ LL |     |x| x
 
 error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr
index 2fb5ebb6541..080750f8497 100644
--- a/tests/ui/impl-trait/implicit-capture-late.stderr
+++ b/tests/ui/impl-trait/implicit-capture-late.stderr
@@ -1,4 +1,10 @@
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/implicit-capture-late.rs:10:55
+   |
+LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
+   |                                                       ^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
   --> $DIR/implicit-capture-late.rs:10:36
    |
 LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
new file mode 100644
index 00000000000..6f0dbd752b0
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.rs
@@ -0,0 +1,18 @@
+struct Wrapper<'rom>(T);
+//~^ ERROR cannot find type `T` in this scope
+
+trait Foo {
+    fn bar() -> Wrapper<impl Sized>;
+    //~^ ERROR missing lifetime specifier
+    //~| ERROR struct takes 0 generic arguments but 1 generic argument was supplied
+}
+
+impl Foo for () {
+    fn bar() -> i32 {
+        //~^ ERROR method `bar` has an incompatible type for trait
+        //~| ERROR method `bar` has an incompatible return type for trait
+        0
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
new file mode 100644
index 00000000000..d30557c8a7b
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/opaque-and-lifetime-mismatch.stderr
@@ -0,0 +1,67 @@
+error[E0106]: missing lifetime specifier
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:24
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                        ^ expected named lifetime parameter
+   |
+   = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values
+   |
+LL |     fn bar() -> Wrapper<'static, impl Sized>;
+   |                         ++++++++
+
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/opaque-and-lifetime-mismatch.rs:1:22
+   |
+LL | struct Wrapper<'rom>(T);
+   |                      ^ not found in this scope
+   |
+help: you might be missing a type parameter
+   |
+LL | struct Wrapper<'rom, T>(T);
+   |                    +++
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:17
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                 ^^^^^^^ ---------- help: remove this generic argument
+   |                 |
+   |                 expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/opaque-and-lifetime-mismatch.rs:1:8
+   |
+LL | struct Wrapper<'rom>(T);
+   |        ^^^^^^^
+
+error[E0053]: method `bar` has an incompatible return type for trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:11:17
+   |
+LL |     fn bar() -> i32 {
+   |                 ^^^
+   |                 |
+   |                 expected `Wrapper<'static>`, found `i32`
+   |                 return type in trait
+
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:11:17
+   |
+LL |     fn bar() -> i32 {
+   |                 ^^^
+   |                 |
+   |                 expected `Wrapper<'static>`, found `i32`
+   |                 help: change the output type to match the trait: `Wrapper<'static>`
+   |
+note: type in trait
+  --> $DIR/opaque-and-lifetime-mismatch.rs:5:17
+   |
+LL |     fn bar() -> Wrapper<impl Sized>;
+   |                 ^^^^^^^^^^^^^^^^^^^
+   = note: expected signature `fn() -> Wrapper<'static>`
+              found signature `fn() -> i32`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0053, E0106, E0107, E0412.
+For more information about an error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/issues/issue-54895.rs b/tests/ui/impl-trait/issues/issue-54895.rs
index 8d7a1d56f83..13c0038ce43 100644
--- a/tests/ui/impl-trait/issues/issue-54895.rs
+++ b/tests/ui/impl-trait/issues/issue-54895.rs
@@ -13,7 +13,7 @@ impl<'a> Trait<'a> for X {
 }
 
 fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     X(())
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-54895.stderr b/tests/ui/impl-trait/issues/issue-54895.stderr
index 999ffd52141..64b425328e3 100644
--- a/tests/ui/impl-trait/issues/issue-54895.stderr
+++ b/tests/ui/impl-trait/issues/issue-54895.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-54895.rs:15:53
    |
 LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
@@ -12,3 +12,4 @@ LL | fn f() -> impl for<'a> Trait<'a, Out = impl Sized + 'a> {
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-67830.rs b/tests/ui/impl-trait/issues/issue-67830.rs
index 6dc8935c777..939eca82a8f 100644
--- a/tests/ui/impl-trait/issues/issue-67830.rs
+++ b/tests/ui/impl-trait/issues/issue-67830.rs
@@ -19,7 +19,7 @@ where
 
 struct A;
 fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     Wrap(|a| Some(a).into_iter())
     //~^ ERROR implementation of `FnOnce` is not general enough
     //~| ERROR implementation of `FnOnce` is not general enough
diff --git a/tests/ui/impl-trait/issues/issue-67830.stderr b/tests/ui/impl-trait/issues/issue-67830.stderr
index 546198b8a10..ef513a40cf3 100644
--- a/tests/ui/impl-trait/issues/issue-67830.stderr
+++ b/tests/ui/impl-trait/issues/issue-67830.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-67830.rs:21:62
    |
 LL | fn test() -> impl for<'a> MyFn<&'a A, Output=impl Iterator + 'a> {
@@ -31,3 +31,4 @@ LL |     Wrap(|a| Some(a).into_iter())
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.rs b/tests/ui/impl-trait/issues/issue-88236-2.rs
index f4354d1b2ae..7ff08d8174f 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.rs
+++ b/tests/ui/impl-trait/issues/issue-88236-2.rs
@@ -13,17 +13,17 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     &()
     //~^ ERROR implementation of `Hrtb` is not general enough
     //~| ERROR implementation of `Hrtb` is not general enough
 }
 
 fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
-    //~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+    //~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
     x
     //~^ ERROR implementation of `Hrtb` is not general enough
     //~| ERROR implementation of `Hrtb` is not general enough
diff --git a/tests/ui/impl-trait/issues/issue-88236-2.stderr b/tests/ui/impl-trait/issues/issue-88236-2.stderr
index 1f5029f9d9f..09fd58056a5 100644
--- a/tests/ui/impl-trait/issues/issue-88236-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-88236-2.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236-2.rs:15:61
    |
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
@@ -10,7 +10,7 @@ note: lifetime declared here
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
    |                            ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236-2.rs:18:80
    |
 LL | fn make_weird_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
@@ -40,7 +40,7 @@ LL |     &()
    = note: `Hrtb<'a>` would have to be implemented for the type `&()`
    = note: ...but `Hrtb<'0>` is actually implemented for the type `&'0 ()`, for some specific lifetime `'0`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236-2.rs:25:78
    |
 LL | fn make_bad_impl<'b>(x: &'b ()) -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {
@@ -90,3 +90,4 @@ LL |     x
 
 error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/issues/issue-88236.rs b/tests/ui/impl-trait/issues/issue-88236.rs
index 36d12417354..e782a876573 100644
--- a/tests/ui/impl-trait/issues/issue-88236.rs
+++ b/tests/ui/impl-trait/issues/issue-88236.rs
@@ -13,6 +13,6 @@ impl<'a> Hrtb<'a> for &'a () {
 }
 
 fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-88236.stderr b/tests/ui/impl-trait/issues/issue-88236.stderr
index 6cf1a42d6a9..5dee5f88c89 100644
--- a/tests/ui/impl-trait/issues/issue-88236.stderr
+++ b/tests/ui/impl-trait/issues/issue-88236.stderr
@@ -1,4 +1,4 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/issue-88236.rs:15:61
    |
 LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
@@ -12,3 +12,4 @@ LL | fn make_impl() -> impl for<'a> Hrtb<'a, Assoc = impl Send + 'a> {}
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.rs b/tests/ui/impl-trait/nested-rpit-hrtb.rs
index a3eca741daa..c10bfbfe4dc 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.rs
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.rs
@@ -23,18 +23,18 @@ impl Qux<'_> for () {}
 
 // This is not supported.
 fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 // This is not supported.
 fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 //~| ERROR implementation of `Bar` is not general enough
 
 fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 //~| ERROR: the trait bound `for<'a> &'a (): Qux<'_>` is not satisfied
 
 // This should resolve.
diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
index 4fc22712de6..2779694a517 100644
--- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr
+++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr
@@ -29,7 +29,7 @@ help: consider introducing lifetime `'b` here
 LL | fn two_htrb_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Sized + 'b> {}
    |                          ++++
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:25:69
    |
 LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
@@ -41,7 +41,7 @@ note: lifetime declared here
 LL | fn one_hrtb_outlives() -> impl for<'a> Foo<'a, Assoc = impl Sized + 'a> {}
    |                                    ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:29:68
    |
 LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
@@ -53,7 +53,7 @@ note: lifetime declared here
 LL | fn one_hrtb_trait_param() -> impl for<'a> Foo<'a, Assoc = impl Qux<'a>> {}
    |                                       ^^
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:32:74
    |
 LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a> {}
@@ -74,7 +74,7 @@ LL | fn one_hrtb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl Sized + 'a
    = note: `()` must implement `Bar<'a>`
    = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0`
 
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
   --> $DIR/nested-rpit-hrtb.rs:36:73
    |
 LL | fn one_hrtb_trait_param_uses() -> impl for<'a> Bar<'a, Assoc = impl Qux<'a>> {}
@@ -133,5 +133,5 @@ LL | fn two_htrb_outlives_uses() -> impl for<'a> Bar<'a, Assoc = impl for<'b> Si
 
 error: aborting due to 12 previous errors
 
-Some errors have detailed explanations: E0261, E0277.
+Some errors have detailed explanations: E0261, E0277, E0657.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs
new file mode 100644
index 00000000000..ddda1a71d7e
--- /dev/null
+++ b/tests/ui/traits/next-solver/assembly/param-env-alias-bound-conflict.rs
@@ -0,0 +1,26 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for #119607.
+
+pub trait IntoFoo {
+    type Item;
+    type IntoIter: Foo<Item = Self::Item>;
+
+    fn into_iter(self) -> Self::IntoIter;
+}
+
+pub trait Foo {
+    type Item;
+
+    fn next(self) -> Option<Self::Item>;
+}
+
+pub fn foo<'a, Iter1, Elem1>(a: &'a Iter1)
+where
+    &'a Iter1: IntoFoo<Item = Elem1>,
+{
+    a.into_iter().next();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs
new file mode 100644
index 00000000000..1b9e9866cd6
--- /dev/null
+++ b/tests/ui/traits/next-solver/env-shadows-impls/param-env-impl-conflict.rs
@@ -0,0 +1,23 @@
+//@ compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for #119608.
+
+pub trait Foo {}
+
+pub trait Bar {
+    type Assoc;
+}
+
+impl<T: Foo> Bar for T {
+    type Assoc = T;
+}
+
+pub fn foo<I>(_input: <I as Bar>::Assoc)
+where
+    I: Bar,
+    <I as Bar>::Assoc: Foo,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
index b030ce39d1d..1ff200680be 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
@@ -7,7 +7,7 @@ pub trait Trait<'a> {
 trait Test<'a> {}
 
 pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
-//~^ ERROR higher kinded lifetime bounds on nested opaque types are not supported yet
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
 
 impl Trait<'_> for () {
     type Assoc = ();
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
index 706de37e9f3..09f6fba79cf 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.stderr
@@ -1,8 +1,8 @@
-error: higher kinded lifetime bounds on nested opaque types are not supported yet
-  --> $DIR/escaping-bound-var.rs:9:25
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait`
+  --> $DIR/escaping-bound-var.rs:9:47
    |
 LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
-   |                         ^^
+   |                                               ^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
    |
 note: lifetime declared here
   --> $DIR/escaping-bound-var.rs:9:25
@@ -12,3 +12,4 @@ LL | pub type Foo = impl for<'a> Trait<'a, Assoc = impl Test<'a>>;
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs
index 457c4affb9d..4b9fa67fd64 100644
--- a/tests/ui/type-alias-impl-trait/variance.rs
+++ b/tests/ui/type-alias-impl-trait/variance.rs
@@ -12,11 +12,11 @@ type CapturedEarly<'a> = impl Sized + Captures<'a>; //~ [*, o]
 //~^ ERROR: unconstrained opaque type
 
 type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>; //~ [*, o, o]
-//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 //~| ERROR: unconstrained opaque type
 
 type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>; //~ [*, o, o]
-//~^ ERROR `impl Trait` can only capture lifetimes bound at the fn or impl level
+//~^ ERROR `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
 //~| ERROR: unconstrained opaque type
 
 type Bar<'a, 'b: 'b, T> = impl Sized; //~ ERROR [*, *, o, o, o]
diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr
index eafe583e89c..1aaf36223b7 100644
--- a/tests/ui/type-alias-impl-trait/variance.stderr
+++ b/tests/ui/type-alias-impl-trait/variance.stderr
@@ -1,10 +1,22 @@
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/variance.rs:14:56
+   |
+LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
+   |                                                        ^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
   --> $DIR/variance.rs:14:36
    |
 LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
    |                                    ^^
 
-error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
+  --> $DIR/variance.rs:18:49
+   |
+LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^ `impl Trait` implicitly captures all lifetimes in scope
+   |
+note: lifetime declared here
   --> $DIR/variance.rs:18:29
    |
 LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;