about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_const_eval/src/check_consts/ops.rs2
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs17
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_feature/src/lib.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs1
-rw-r--r--compiler/rustc_interface/src/lib.rs1
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs10
-rw-r--r--compiler/rustc_session/src/lib.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs6
-rw-r--r--library/alloc/Cargo.toml4
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs66
-rw-r--r--library/alloc/tests/vec_deque_alloc_error.rs49
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/cell/lazy.rs20
-rw-r--r--library/core/src/ffi/mod.rs3
-rw-r--r--library/core/src/time.rs14
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sync/lazy_lock.rs41
-rw-r--r--library/std/src/sync/mod.rs2
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/tools/clippy/clippy_dev/src/lib.rs1
-rw-r--r--src/tools/clippy/src/driver.rs1
-rw-r--r--src/tools/clippy/tests/compile-test.rs1
-rw-r--r--src/tools/clippy/tests/dogfood.rs1
-rw-r--r--src/tools/clippy/tests/lint_message_convention.rs1
-rw-r--r--src/tools/clippy/tests/workspace.rs2
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs30
-rw-r--r--tests/ui/borrowck/issue-64453.stderr2
-rw-r--r--tests/ui/consts/issue-16538.stderr2
-rw-r--r--tests/ui/consts/issue-32829-2.stderr4
-rw-r--r--tests/ui/consts/mir_check_nonconst.stderr2
-rw-r--r--tests/ui/impl-trait/equality.rs13
-rw-r--r--tests/ui/impl-trait/equality.stderr15
-rw-r--r--tests/ui/impl-trait/nested_impl_trait.stderr16
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs2
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr12
-rw-r--r--tests/ui/impl-trait/unsize_adt.rs14
-rw-r--r--tests/ui/impl-trait/unsize_adt.stderr17
-rw-r--r--tests/ui/impl-trait/unsize_slice.rs12
-rw-r--r--tests/ui/impl-trait/unsize_slice.stderr17
-rw-r--r--tests/ui/impl-trait/unsize_tuple.rs14
-rw-r--r--tests/ui/impl-trait/unsize_tuple.stderr17
-rw-r--r--tests/ui/issues/issue-25901.stderr2
-rw-r--r--tests/ui/issues/issue-7364.stderr2
-rw-r--r--tests/ui/lint/suspicious-double-ref-op.rs1
-rw-r--r--tests/ui/lint/suspicious-double-ref-op.stderr10
-rw-r--r--tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs2
-rw-r--r--tests/ui/static/static-mut-not-constant.stderr2
-rw-r--r--tests/ui/static/static-vec-repeat-not-constant.stderr2
-rw-r--r--tests/ui/statics/check-values-constraints.stderr16
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs28
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.rs4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr12
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs22
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr17
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection.rs27
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.rs31
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr (renamed from tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr)2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr23
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.current.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.stderr12
76 files changed, 590 insertions, 222 deletions
diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs
index 8406e0f4876..90b622cae65 100644
--- a/compiler/rustc_const_eval/src/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/check_consts/ops.rs
@@ -309,7 +309,7 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
         }
 
         if let ConstContext::Static(_) = ccx.const_kind() {
-            err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
+            err.note("consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`");
         }
 
         err
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 85b5a3cdb7c..9781aae22eb 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -24,7 +24,6 @@
 #![feature(extend_one)]
 #![feature(hash_raw_entry)]
 #![feature(hasher_prefixfree_extras)]
-#![feature(lazy_cell)]
 #![feature(lint_reasons)]
 #![feature(macro_metavar_expr)]
 #![feature(map_try_insert)]
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 5532eff7be6..2bd58680eef 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -57,7 +57,7 @@ use std::process::{self, Command, Stdio};
 use std::str;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::{Arc, OnceLock};
-use std::time::{Instant, SystemTime};
+use std::time::{Duration, Instant, SystemTime};
 use time::OffsetDateTime;
 use tracing::trace;
 
@@ -1502,14 +1502,13 @@ pub fn init_logger(early_dcx: &EarlyDiagCtxt, cfg: rustc_log::LoggerConfig) {
 pub fn install_ctrlc_handler() {
     #[cfg(not(target_family = "wasm"))]
     ctrlc::set_handler(move || {
-        // Indicate that we have been signaled to stop. If we were already signaled, exit
-        // immediately. In our interpreter loop we try to consult this value often, but if for
-        // whatever reason we don't get to that check or the cleanup we do upon finding that
-        // this bool has become true takes a long time, the exit here will promptly exit the
-        // process on the second Ctrl-C.
-        if CTRL_C_RECEIVED.swap(true, Ordering::Relaxed) {
-            std::process::exit(1);
-        }
+        // Indicate that we have been signaled to stop, then give the rest of the compiler a bit of
+        // time to check CTRL_C_RECEIVED and run its own shutdown logic, but after a short amount
+        // of time exit the process. This sleep+exit ensures that even if nobody is checking
+        // CTRL_C_RECEIVED, the compiler exits reasonably promptly.
+        CTRL_C_RECEIVED.store(true, Ordering::Relaxed);
+        std::thread::sleep(Duration::from_millis(100));
+        std::process::exit(1);
     })
     .expect("Unable to install ctrlc handler");
 }
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 2a8f4222064..08388c5a58e 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -1,6 +1,5 @@
 #![doc(rust_logo)]
 #![feature(rustdoc_internals)]
-#![feature(lazy_cell)]
 #![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 #![allow(internal_features)]
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 36ef8fe7816..9cbf836ec76 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -14,7 +14,6 @@
 #![allow(internal_features)]
 #![feature(rustdoc_internals)]
 #![doc(rust_logo)]
-#![feature(lazy_cell)]
 
 mod accepted;
 mod builtin_attrs;
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index d1e50e13894..8fe81851f93 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -68,7 +68,6 @@ This API is completely unstable and subject to change.
 #![feature(iter_intersperse)]
 #![feature(let_chains)]
 #![feature(never_type)]
-#![feature(lazy_cell)]
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
 
diff --git a/compiler/rustc_interface/src/lib.rs b/compiler/rustc_interface/src/lib.rs
index c1d460ddd08..8b1d9b706ca 100644
--- a/compiler/rustc_interface/src/lib.rs
+++ b/compiler/rustc_interface/src/lib.rs
@@ -1,5 +1,4 @@
 #![feature(decl_macro)]
-#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(thread_spawn_unchecked)]
 #![feature(try_blocks)]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 617fe99ef6a..747b7292a19 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -1316,10 +1316,8 @@ declare_lint! {
     /// * If you are trying to perform a one-time initialization of a global:
     ///     * If the value can be computed at compile-time, consider using
     ///       const-compatible values (see [Constant Evaluation]).
-    ///     * For more complex single-initialization cases, consider using a
-    ///       third-party crate, such as [`lazy_static`] or [`once_cell`].
-    ///     * If you are using the [nightly channel], consider the new
-    ///       [`lazy`] module in the standard library.
+    ///     * For more complex single-initialization cases, consider using
+    ///       [`std::sync::LazyLock`].
     /// * If you truly need a mutable global, consider using a [`static`],
     ///   which has a variety of options:
     ///   * Simple data types can be directly defined and mutated with an
@@ -1334,9 +1332,7 @@ declare_lint! {
     /// [Constant Evaluation]: https://doc.rust-lang.org/reference/const_eval.html
     /// [`static`]: https://doc.rust-lang.org/reference/items/static-items.html
     /// [mutable `static`]: https://doc.rust-lang.org/reference/items/static-items.html#mutable-statics
-    /// [`lazy`]: https://doc.rust-lang.org/nightly/std/lazy/index.html
-    /// [`lazy_static`]: https://crates.io/crates/lazy_static
-    /// [`once_cell`]: https://crates.io/crates/once_cell
+    /// [`std::sync::LazyLock`]: https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html
     /// [`atomic`]: https://doc.rust-lang.org/std/sync/atomic/index.html
     /// [`Mutex`]: https://doc.rust-lang.org/std/sync/struct.Mutex.html
     pub CONST_ITEM_MUTATION,
diff --git a/compiler/rustc_session/src/lib.rs b/compiler/rustc_session/src/lib.rs
index ce866906e1e..cb02fbdfee9 100644
--- a/compiler/rustc_session/src/lib.rs
+++ b/compiler/rustc_session/src/lib.rs
@@ -1,5 +1,4 @@
 #![feature(let_chains)]
-#![feature(lazy_cell)]
 #![feature(option_get_or_insert_default)]
 #![feature(rustc_attrs)]
 #![feature(map_many_mut)]
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 4a94643d908..696b1c15115 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2539,7 +2539,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
         let InferOk { obligations, .. } = self
             .infcx
             .at(&cause, obligation.param_env)
-            .eq(DefineOpaqueTypes::No, placeholder_obligation_trait_ref, impl_trait_ref)
+            .eq(DefineOpaqueTypes::Yes, placeholder_obligation_trait_ref, impl_trait_ref)
             .map_err(|e| {
                 debug!("match_impl: failed eq_trait_refs due to `{}`", e.to_string(self.tcx()))
             })?;
@@ -2594,7 +2594,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                         self.infcx
                             .at(&obligation.cause, obligation.param_env)
                             .eq(
-                                DefineOpaqueTypes::No,
+                                DefineOpaqueTypes::Yes,
                                 upcast_principal.map_bound(|trait_ref| {
                                     ty::ExistentialTraitRef::erase_self_ty(tcx, trait_ref)
                                 }),
@@ -2631,7 +2631,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                     nested.extend(
                         self.infcx
                             .at(&obligation.cause, obligation.param_env)
-                            .eq(DefineOpaqueTypes::No, source_projection, target_projection)
+                            .eq(DefineOpaqueTypes::Yes, source_projection, target_projection)
                             .map_err(|_| SelectionError::Unimplemented)?
                             .into_obligations(),
                     );
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 4646eaced01..024b92790e9 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -20,6 +20,10 @@ rand_xorshift = "0.3.0"
 name = "alloctests"
 path = "tests/lib.rs"
 
+[[test]]
+name = "vec_deque_alloc_error"
+path = "tests/vec_deque_alloc_error.rs"
+
 [[bench]]
 name = "allocbenches"
 path = "benches/lib.rs"
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 4643a6bbe2e..61d05afccfd 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -982,6 +982,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
         // `head` and `len` are at most `isize::MAX` and `target_cap < self.capacity()`, so nothing can
         // overflow.
         let tail_outside = (target_cap + 1..=self.capacity()).contains(&(self.head + self.len));
+        // Used in the drop guard below.
+        let old_head = self.head;
 
         if self.len == 0 {
             self.head = 0;
@@ -1034,12 +1036,74 @@ impl<T, A: Allocator> VecDeque<T, A> {
             }
             self.head = new_head;
         }
-        self.buf.shrink_to_fit(target_cap);
+
+        struct Guard<'a, T, A: Allocator> {
+            deque: &'a mut VecDeque<T, A>,
+            old_head: usize,
+            target_cap: usize,
+        }
+
+        impl<T, A: Allocator> Drop for Guard<'_, T, A> {
+            #[cold]
+            fn drop(&mut self) {
+                unsafe {
+                    // SAFETY: This is only called if `buf.shrink_to_fit` unwinds,
+                    // which is the only time it's safe to call `abort_shrink`.
+                    self.deque.abort_shrink(self.old_head, self.target_cap)
+                }
+            }
+        }
+
+        let guard = Guard { deque: self, old_head, target_cap };
+
+        guard.deque.buf.shrink_to_fit(target_cap);
+
+        // Don't drop the guard if we didn't unwind.
+        mem::forget(guard);
 
         debug_assert!(self.head < self.capacity() || self.capacity() == 0);
         debug_assert!(self.len <= self.capacity());
     }
 
+    /// Reverts the deque back into a consistent state in case `shrink_to` failed.
+    /// This is necessary to prevent UB if the backing allocator returns an error
+    /// from `shrink` and `handle_alloc_error` subsequently unwinds (see #123369).
+    ///
+    /// `old_head` refers to the head index before `shrink_to` was called. `target_cap`
+    /// is the capacity that it was trying to shrink to.
+    unsafe fn abort_shrink(&mut self, old_head: usize, target_cap: usize) {
+        // Moral equivalent of self.head + self.len <= target_cap. Won't overflow
+        // because `self.len <= target_cap`.
+        if self.head <= target_cap - self.len {
+            // The deque's buffer is contiguous, so no need to copy anything around.
+            return;
+        }
+
+        // `shrink_to` already copied the head to fit into the new capacity, so this won't overflow.
+        let head_len = target_cap - self.head;
+        // `self.head > target_cap - self.len` => `self.len > target_cap - self.head =: head_len` so this must be positive.
+        let tail_len = self.len - head_len;
+
+        if tail_len <= cmp::min(head_len, self.capacity() - target_cap) {
+            // There's enough spare capacity to copy the tail to the back (because `tail_len < self.capacity() - target_cap`),
+            // and copying the tail should be cheaper than copying the head (because `tail_len <= head_len`).
+
+            unsafe {
+                // The old tail and the new tail can't overlap because the head slice lies between them. The
+                // head slice ends at `target_cap`, so that's where we copy to.
+                self.copy_nonoverlapping(0, target_cap, tail_len);
+            }
+        } else {
+            // Either there's not enough spare capacity to make the deque contiguous, or the head is shorter than the tail
+            // (and therefore hopefully cheaper to copy).
+            unsafe {
+                // The old and the new head slice can overlap, so we can't use `copy_nonoverlapping` here.
+                self.copy(self.head, old_head, head_len);
+                self.head = old_head;
+            }
+        }
+    }
+
     /// Shortens the deque, keeping the first `len` elements and dropping
     /// the rest.
     ///
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloc/tests/vec_deque_alloc_error.rs
new file mode 100644
index 00000000000..c11f4556da9
--- /dev/null
+++ b/library/alloc/tests/vec_deque_alloc_error.rs
@@ -0,0 +1,49 @@
+#![feature(alloc_error_hook, allocator_api)]
+
+use std::{
+    alloc::{set_alloc_error_hook, AllocError, Allocator, Layout, System},
+    collections::VecDeque,
+    panic::{catch_unwind, AssertUnwindSafe},
+    ptr::NonNull,
+};
+
+#[test]
+fn test_shrink_to_unwind() {
+    // This tests that `shrink_to` leaves the deque in a consistent state when
+    // the call to `RawVec::shrink_to_fit` unwinds. The code is adapted from #123369
+    // but changed to hopefully not have any UB even if the test fails.
+
+    struct BadAlloc;
+
+    unsafe impl Allocator for BadAlloc {
+        fn allocate(&self, l: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            // We allocate zeroed here so that the whole buffer of the deque
+            // is always initialized. That way, even if the deque is left in
+            // an inconsistent state, no uninitialized memory should be accessed.
+            System.allocate_zeroed(l)
+        }
+
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            unsafe { System.deallocate(ptr, layout) }
+        }
+
+        unsafe fn shrink(
+            &self,
+            _ptr: NonNull<u8>,
+            _old_layout: Layout,
+            _new_layout: Layout,
+        ) -> Result<NonNull<[u8]>, AllocError> {
+            Err(AllocError)
+        }
+    }
+
+    set_alloc_error_hook(|_| panic!("alloc error"));
+
+    let mut v = VecDeque::with_capacity_in(15, BadAlloc);
+    v.push_back(1);
+    v.push_front(2);
+    // This should unwind because it calls `BadAlloc::shrink` and then `handle_alloc_error` which unwinds.
+    assert!(catch_unwind(AssertUnwindSafe(|| v.shrink_to_fit())).is_err());
+    // This should only pass if the deque is left in a consistent state.
+    assert_eq!(v, [2, 1]);
+}
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 4b491ffdafa..ac026de95da 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -245,7 +245,7 @@ use crate::ptr::{self, NonNull};
 mod lazy;
 mod once;
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 pub use lazy::LazyCell;
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use once::OnceCell;
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 1b213f6a294..47eab6fd016 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -18,8 +18,6 @@ enum State<T, F> {
 /// # Examples
 ///
 /// ```
-/// #![feature(lazy_cell)]
-///
 /// use std::cell::LazyCell;
 ///
 /// let lazy: LazyCell<i32> = LazyCell::new(|| {
@@ -36,7 +34,7 @@ enum State<T, F> {
 /// //   92
 /// //   92
 /// ```
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 pub struct LazyCell<T, F = fn() -> T> {
     state: UnsafeCell<State<T, F>>,
 }
@@ -47,8 +45,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(lazy_cell)]
-    ///
     /// use std::cell::LazyCell;
     ///
     /// let hello = "Hello, World!".to_string();
@@ -58,7 +54,8 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, "HELLO, WORLD!");
     /// ```
     #[inline]
-    #[unstable(feature = "lazy_cell", issue = "109736")]
+    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new(f: F) -> LazyCell<T, F> {
         LazyCell { state: UnsafeCell::new(State::Uninit(f)) }
     }
@@ -70,7 +67,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(lazy_cell)]
     /// #![feature(lazy_cell_consume)]
     ///
     /// use std::cell::LazyCell;
@@ -99,8 +95,6 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(lazy_cell)]
-    ///
     /// use std::cell::LazyCell;
     ///
     /// let lazy = LazyCell::new(|| 92);
@@ -109,7 +103,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "lazy_cell", issue = "109736")]
+    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn force(this: &LazyCell<T, F>) -> &T {
         // SAFETY:
         // This invalidates any mutable references to the data. The resulting
@@ -173,7 +167,7 @@ impl<T, F> LazyCell<T, F> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     type Target = T;
     #[inline]
@@ -182,7 +176,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyCell<T, F> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Default> Default for LazyCell<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -191,7 +185,7 @@ impl<T: Default> Default for LazyCell<T> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyCell");
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 27dacbb23d9..618897b3aba 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -133,7 +133,8 @@ mod c_char_definition {
                 any(target_arch = "aarch64", target_arch = "riscv64")
             ),
             all(target_os = "nto", target_arch = "aarch64"),
-            target_os = "horizon"
+            target_os = "horizon",
+            target_os = "aix",
         ))] {
             pub type c_char = u8;
         } else {
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 88fe29c9997..89202e7bb8d 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1084,40 +1084,42 @@ impl Duration {
     ///
     /// # Examples
     /// ```
-    /// #![feature(div_duration)]
     /// use std::time::Duration;
     ///
     /// let dur1 = Duration::new(2, 700_000_000);
     /// let dur2 = Duration::new(5, 400_000_000);
     /// assert_eq!(dur1.div_duration_f64(dur2), 0.5);
     /// ```
-    #[unstable(feature = "div_duration", issue = "63139")]
+    #[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
     pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
-        self.as_secs_f64() / rhs.as_secs_f64()
+        let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64);
+        let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64);
+        self_nanos / rhs_nanos
     }
 
     /// Divide `Duration` by `Duration` and return `f32`.
     ///
     /// # Examples
     /// ```
-    /// #![feature(div_duration)]
     /// use std::time::Duration;
     ///
     /// let dur1 = Duration::new(2, 700_000_000);
     /// let dur2 = Duration::new(5, 400_000_000);
     /// assert_eq!(dur1.div_duration_f32(dur2), 0.5);
     /// ```
-    #[unstable(feature = "div_duration", issue = "63139")]
+    #[stable(feature = "div_duration", since = "CURRENT_RUSTC_VERSION")]
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
     #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")]
     pub const fn div_duration_f32(self, rhs: Duration) -> f32 {
-        self.as_secs_f32() / rhs.as_secs_f32()
+        let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32);
+        let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32);
+        self_nanos / rhs_nanos
     }
 }
 
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 797108a8425..e42cec304ef 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -29,7 +29,6 @@
 #![feature(core_private_bignum)]
 #![feature(core_private_diy_float)]
 #![feature(dec2flt)]
-#![feature(div_duration)]
 #![feature(duration_abs_diff)]
 #![feature(duration_consts_float)]
 #![feature(duration_constants)]
@@ -96,7 +95,6 @@
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
 #![feature(ptr_metadata)]
-#![feature(lazy_cell)]
 #![feature(unsized_tuple_coercion)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 4a18db3d5a3..9d6576fa841 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -395,7 +395,6 @@
 #![feature(edition_panic)]
 #![feature(format_args_nl)]
 #![feature(get_many_mut)]
-#![feature(lazy_cell)]
 #![feature(log_syntax)]
 #![feature(test)]
 #![feature(trace_macros)]
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 27b59cfc8c2..16d5dc30552 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -31,8 +31,6 @@ union Data<T, F> {
 /// Initialize static variables with `LazyLock`.
 ///
 /// ```
-/// #![feature(lazy_cell)]
-///
 /// use std::collections::HashMap;
 ///
 /// use std::sync::LazyLock;
@@ -61,8 +59,6 @@ union Data<T, F> {
 /// ```
 /// Initialize fields with `LazyLock`.
 /// ```
-/// #![feature(lazy_cell)]
-///
 /// use std::sync::LazyLock;
 ///
 /// #[derive(Debug)]
@@ -76,8 +72,7 @@ union Data<T, F> {
 ///     println!("{}", *data.number);
 /// }
 /// ```
-
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 pub struct LazyLock<T, F = fn() -> T> {
     once: Once,
     data: UnsafeCell<Data<T, F>>,
@@ -85,8 +80,21 @@ pub struct LazyLock<T, F = fn() -> T> {
 
 impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// Creates a new lazy value with the given initializing function.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::sync::LazyLock;
+    ///
+    /// let hello = "Hello, World!".to_string();
+    ///
+    /// let lazy = LazyLock::new(|| hello.to_uppercase());
+    ///
+    /// assert_eq!(&*lazy, "HELLO, WORLD!");
+    /// ```
     #[inline]
-    #[unstable(feature = "lazy_cell", issue = "109736")]
+    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
+    #[rustc_const_stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
     pub const fn new(f: F) -> LazyLock<T, F> {
         LazyLock { once: Once::new(), data: UnsafeCell::new(Data { f: ManuallyDrop::new(f) }) }
     }
@@ -107,7 +115,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(lazy_cell)]
     /// #![feature(lazy_cell_consume)]
     ///
     /// use std::sync::LazyLock;
@@ -145,8 +152,6 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(lazy_cell)]
-    ///
     /// use std::sync::LazyLock;
     ///
     /// let lazy = LazyLock::new(|| 92);
@@ -155,7 +160,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     /// assert_eq!(&*lazy, &92);
     /// ```
     #[inline]
-    #[unstable(feature = "lazy_cell", issue = "109736")]
+    #[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
     pub fn force(this: &LazyLock<T, F>) -> &T {
         this.once.call_once(|| {
             // SAFETY: `call_once` only runs this closure once, ever.
@@ -191,7 +196,7 @@ impl<T, F> LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T, F> Drop for LazyLock<T, F> {
     fn drop(&mut self) {
         match self.once.state() {
@@ -204,7 +209,7 @@ impl<T, F> Drop for LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     type Target = T;
 
@@ -219,7 +224,7 @@ impl<T, F: FnOnce() -> T> Deref for LazyLock<T, F> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: Default> Default for LazyLock<T> {
     /// Creates a new lazy value using `Default` as the initializing function.
     #[inline]
@@ -228,7 +233,7 @@ impl<T: Default> Default for LazyLock<T> {
     }
 }
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyLock");
@@ -242,13 +247,13 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
 
 // We never create a `&F` from a `&LazyLock<T, F>` so it is fine
 // to not impl `Sync` for `F`.
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 unsafe impl<T: Sync + Send, F: Send> Sync for LazyLock<T, F> {}
 // auto-derived `Send` impl is OK.
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: RefUnwindSafe + UnwindSafe, F: UnwindSafe> RefUnwindSafe for LazyLock<T, F> {}
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 impl<T: UnwindSafe, F: UnwindSafe> UnwindSafe for LazyLock<T, F> {}
 
 #[cfg(test)]
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index e8c35bd48a7..fb7d601b094 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -179,7 +179,7 @@ pub use self::rwlock::{MappedRwLockReadGuard, MappedRwLockWriteGuard};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
 
-#[unstable(feature = "lazy_cell", issue = "109736")]
+#[stable(feature = "lazy_cell", since = "CURRENT_RUSTC_VERSION")]
 pub use self::lazy_lock::LazyLock;
 #[stable(feature = "once_cell", since = "1.70.0")]
 pub use self::once_lock::OnceLock;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 0650afb90c7..55346c768b6 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -8,7 +8,6 @@
 #![feature(if_let_guard)]
 #![feature(impl_trait_in_assoc_type)]
 #![feature(iter_intersperse)]
-#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(never_type)]
 #![feature(round_char_boundary)]
diff --git a/src/tools/clippy/clippy_dev/src/lib.rs b/src/tools/clippy/clippy_dev/src/lib.rs
index 385191e0361..3aa43dbe23e 100644
--- a/src/tools/clippy/clippy_dev/src/lib.rs
+++ b/src/tools/clippy/clippy_dev/src/lib.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![feature(let_chains)]
 #![feature(rustc_private)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs
index 9e42abbc9aa..f79da26964f 100644
--- a/src/tools/clippy/src/driver.rs
+++ b/src/tools/clippy/src/driver.rs
@@ -2,7 +2,6 @@
 #![allow(rustc::untranslatable_diagnostic)]
 #![feature(rustc_private)]
 #![feature(let_chains)]
-#![feature(lazy_cell)]
 #![feature(lint_reasons)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 // warn on lints, that are included in `rust-lang/rust`s bootstrap
diff --git a/src/tools/clippy/tests/compile-test.rs b/src/tools/clippy/tests/compile-test.rs
index b06a11702ec..333a2ab5857 100644
--- a/src/tools/clippy/tests/compile-test.rs
+++ b/src/tools/clippy/tests/compile-test.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![feature(is_sorted)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
diff --git a/src/tools/clippy/tests/dogfood.rs b/src/tools/clippy/tests/dogfood.rs
index 3f16c180ea7..36a7a651c4d 100644
--- a/src/tools/clippy/tests/dogfood.rs
+++ b/src/tools/clippy/tests/dogfood.rs
@@ -3,7 +3,6 @@
 //!
 //! See [Eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) for context
 
-#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/lint_message_convention.rs b/src/tools/clippy/tests/lint_message_convention.rs
index 98019c75527..6ce7e44474d 100644
--- a/src/tools/clippy/tests/lint_message_convention.rs
+++ b/src/tools/clippy/tests/lint_message_convention.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![cfg_attr(feature = "deny-warnings", deny(warnings))]
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
diff --git a/src/tools/clippy/tests/workspace.rs b/src/tools/clippy/tests/workspace.rs
index 699ab2be199..19ccc7ae960 100644
--- a/src/tools/clippy/tests/workspace.rs
+++ b/src/tools/clippy/tests/workspace.rs
@@ -1,5 +1,3 @@
-#![feature(lazy_cell)]
-
 use std::path::PathBuf;
 use std::process::Command;
 use test_utils::{CARGO_CLIPPY_PATH, IS_RUSTC_TEST_SUITE};
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index c876aae494d..5a402f3cc60 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -10,6 +10,25 @@ use crate::walk::filter_not_rust;
 const LLVM_COMPONENTS_HEADER: &str = "needs-llvm-components:";
 const COMPILE_FLAGS_HEADER: &str = "compile-flags:";
 
+const KNOWN_LLVM_COMPONENTS: &[&str] = &[
+    "aarch64",
+    "arm",
+    "avr",
+    "bpf",
+    "hexagon",
+    "loongarch",
+    "m68k",
+    "mips",
+    "msp430",
+    "nvptx",
+    "powerpc",
+    "riscv",
+    "sparc",
+    "systemz",
+    "webassembly",
+    "x86",
+];
+
 #[derive(Default, Debug)]
 struct RevisionInfo<'a> {
     target_arch: Option<&'a str>,
@@ -68,6 +87,17 @@ pub fn check(path: &Path, bad: &mut bool) {
                     // gathered.
                 }
             }
+            if let Some(llvm_components) = llvm_components {
+                for component in llvm_components {
+                    if !KNOWN_LLVM_COMPONENTS.contains(component) {
+                        eprintln!(
+                            "{}: revision {} specifies unknown LLVM component `{}`",
+                            file, rev, component
+                        );
+                        *bad = true;
+                    }
+                }
+            }
         }
     });
 }
diff --git a/tests/ui/borrowck/issue-64453.stderr b/tests/ui/borrowck/issue-64453.stderr
index 0e4a8d42f6e..e671817633b 100644
--- a/tests/ui/borrowck/issue-64453.stderr
+++ b/tests/ui/borrowck/issue-64453.stderr
@@ -14,7 +14,7 @@ LL | static settings_dir: String = format!("");
    |                               ^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0507]: cannot move out of static item `settings_dir`
diff --git a/tests/ui/consts/issue-16538.stderr b/tests/ui/consts/issue-16538.stderr
index 3981b4ada49..c4f5364b4d7 100644
--- a/tests/ui/consts/issue-16538.stderr
+++ b/tests/ui/consts/issue-16538.stderr
@@ -5,7 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block
   --> $DIR/issue-16538.rs:11:22
diff --git a/tests/ui/consts/issue-32829-2.stderr b/tests/ui/consts/issue-32829-2.stderr
index 0fec3581873..bd0b8c15b55 100644
--- a/tests/ui/consts/issue-32829-2.stderr
+++ b/tests/ui/consts/issue-32829-2.stderr
@@ -13,7 +13,7 @@ LL |         invalid();
    |         ^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error[E0015]: cannot call non-const fn `invalid` in statics
   --> $DIR/issue-32829-2.rs:54:9
@@ -22,7 +22,7 @@ LL |         invalid();
    |         ^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/mir_check_nonconst.stderr b/tests/ui/consts/mir_check_nonconst.stderr
index ea6a8b8ee4a..95d64622ad7 100644
--- a/tests/ui/consts/mir_check_nonconst.stderr
+++ b/tests/ui/consts/mir_check_nonconst.stderr
@@ -5,7 +5,7 @@ LL | static foo: Foo = bar();
    |                   ^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/equality.rs b/tests/ui/impl-trait/equality.rs
index 828b5aac896..952f81f1978 100644
--- a/tests/ui/impl-trait/equality.rs
+++ b/tests/ui/impl-trait/equality.rs
@@ -22,7 +22,7 @@ fn sum_to(n: u32) -> impl Foo {
         0
     } else {
         n + sum_to(n - 1)
-        //~^ ERROR cannot add `impl Foo` to `u32`
+        //~^ ERROR cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
     }
 }
 
@@ -32,12 +32,15 @@ trait Leak: Sized {
 }
 impl<T> Leak for T {
     default type T = ();
-    default fn leak(self) -> Self::T { panic!() }
+    default fn leak(self) -> Self::T {
+        panic!()
+    }
 }
 impl Leak for i32 {
     type T = i32;
-    fn leak(self) -> i32 { self }
+    fn leak(self) -> i32 {
+        self
+    }
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/equality.stderr b/tests/ui/impl-trait/equality.stderr
index 69f4cbbbf42..c9ba1a5ba32 100644
--- a/tests/ui/impl-trait/equality.stderr
+++ b/tests/ui/impl-trait/equality.stderr
@@ -22,20 +22,13 @@ help: change the type of the numeric literal from `u32` to `i32`
 LL |     0_i32
    |       ~~~
 
-error[E0277]: cannot add `impl Foo` to `u32`
+error[E0284]: type annotations needed: cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
   --> $DIR/equality.rs:24:11
    |
 LL |         n + sum_to(n - 1)
-   |           ^ no implementation for `u32 + impl Foo`
-   |
-   = help: the trait `Add<impl Foo>` is not implemented for `u32`
-   = help: the following other types implement trait `Add<Rhs>`:
-             <&'a u32 as Add<u32>>
-             <&u32 as Add<&u32>>
-             <u32 as Add<&u32>>
-             <u32 as Add>
+   |           ^ cannot satisfy `<u32 as Add<impl Foo>>::Output == i32`
 
 error: aborting due to 2 previous errors; 1 warning emitted
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0284, E0308.
+For more information about an error, try `rustc --explain E0284`.
diff --git a/tests/ui/impl-trait/nested_impl_trait.stderr b/tests/ui/impl-trait/nested_impl_trait.stderr
index 1f9a2a5e9d6..f7c708a1dfa 100644
--- a/tests/ui/impl-trait/nested_impl_trait.stderr
+++ b/tests/ui/impl-trait/nested_impl_trait.stderr
@@ -46,19 +46,23 @@ error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfie
   --> $DIR/nested_impl_trait.rs:6:46
    |
 LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
    |
-   = help: the trait `Into<U>` is implemented for `T`
-   = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
+help: consider further restricting this bound
+   |
+LL | fn bad_in_ret_position(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                                          +++++++++++++++++
 
 error[E0277]: the trait bound `impl Into<u32>: Into<impl Debug>` is not satisfied
   --> $DIR/nested_impl_trait.rs:19:34
    |
 LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Into<u32>`, which is required by `impl Into<u32>: Into<impl Debug>`
+   |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `Debug` is not implemented for `impl Into<u32>`
+   |
+help: consider further restricting this bound
    |
-   = help: the trait `Into<U>` is implemented for `T`
-   = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
+LL |     fn bad(x: impl Into<u32> + std::fmt::Debug) -> impl Into<impl Debug> { x }
+   |                              +++++++++++++++++
 
 error: aborting due to 7 previous errors
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
index aab10be2de2..7874a21f3ae 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -11,7 +11,7 @@ impl PartialEq<(Bar, i32)> for Bar {
 }
 
 fn foo() -> Foo {
-    //~^ ERROR can't compare `Bar` with `(Foo, i32)`
+    //~^ ERROR overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
     Bar
 }
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
index bc810c0f88f..2d4707f8a27 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
@@ -1,15 +1,9 @@
-error[E0277]: can't compare `Bar` with `(Foo, i32)`
+error[E0275]: overflow evaluating the requirement `Bar: PartialEq<(Foo, i32)>`
   --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
    |
 LL | fn foo() -> Foo {
-   |             ^^^ no implementation for `Bar == (Foo, i32)`
-LL |
-LL |     Bar
-   |     --- return type was inferred to be `Bar` here
-   |
-   = help: the trait `PartialEq<(Foo, i32)>` is not implemented for `Bar`
-   = help: the trait `PartialEq<(Bar, i32)>` is implemented for `Bar`
+   |             ^^^
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/impl-trait/unsize_adt.rs b/tests/ui/impl-trait/unsize_adt.rs
new file mode 100644
index 00000000000..fce5094bd40
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_adt.rs
@@ -0,0 +1,14 @@
+//! Test that we do not allow unsizing `Foo<[Opaque; N]>` to `Foo<[Concrete]>`.
+
+struct Foo<T: ?Sized>(T);
+
+fn hello() -> Foo<[impl Sized; 2]> {
+    if false {
+        let x = hello();
+        let _: &Foo<[i32]> = &x;
+        //~^ ERROR: mismatched types
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsize_adt.stderr b/tests/ui/impl-trait/unsize_adt.stderr
new file mode 100644
index 00000000000..2b93b4a571b
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_adt.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/unsize_adt.rs:8:30
+   |
+LL | fn hello() -> Foo<[impl Sized; 2]> {
+   |                    ---------- the found opaque type
+...
+LL |         let _: &Foo<[i32]> = &x;
+   |                -----------   ^^ expected `&Foo<[i32]>`, found `&Foo<[impl Sized; 2]>`
+   |                |
+   |                expected due to this
+   |
+   = note: expected reference `&Foo<[i32]>`
+              found reference `&Foo<[impl Sized; 2]>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsize_slice.rs b/tests/ui/impl-trait/unsize_slice.rs
new file mode 100644
index 00000000000..ec0f1626564
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_slice.rs
@@ -0,0 +1,12 @@
+//! Test that we do not allow unsizing `[Opaque; N]` to `[Concrete]`.
+
+fn hello() -> [impl Sized; 2] {
+    if false {
+        let x = hello();
+        let _: &[i32] = &x;
+        //~^ ERROR: mismatched types
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsize_slice.stderr b/tests/ui/impl-trait/unsize_slice.stderr
new file mode 100644
index 00000000000..6a7fdb46163
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_slice.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/unsize_slice.rs:6:25
+   |
+LL | fn hello() -> [impl Sized; 2] {
+   |                ---------- the found opaque type
+...
+LL |         let _: &[i32] = &x;
+   |                ------   ^^ expected `&[i32]`, found `&[impl Sized; 2]`
+   |                |
+   |                expected due to this
+   |
+   = note: expected reference `&[i32]`
+              found reference `&[impl Sized; 2]`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/unsize_tuple.rs b/tests/ui/impl-trait/unsize_tuple.rs
new file mode 100644
index 00000000000..630b8fd430f
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_tuple.rs
@@ -0,0 +1,14 @@
+//! Test that we do not allow unsizing `([Opaque; N],)` to `([Concrete],)`.
+
+#![feature(unsized_tuple_coercion)]
+
+fn hello() -> ([impl Sized; 2],) {
+    if false {
+        let x = hello();
+        let _: &([i32],) = &x;
+        //~^ ERROR: mismatched types
+    }
+    todo!()
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/unsize_tuple.stderr b/tests/ui/impl-trait/unsize_tuple.stderr
new file mode 100644
index 00000000000..8d3cf15887c
--- /dev/null
+++ b/tests/ui/impl-trait/unsize_tuple.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/unsize_tuple.rs:8:28
+   |
+LL | fn hello() -> ([impl Sized; 2],) {
+   |                 ---------- the found opaque type
+...
+LL |         let _: &([i32],) = &x;
+   |                ---------   ^^ expected `&([i32],)`, found `&([impl Sized; 2],)`
+   |                |
+   |                expected due to this
+   |
+   = note: expected reference `&([i32],)`
+              found reference `&([impl Sized; 2],)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/issues/issue-25901.stderr b/tests/ui/issues/issue-25901.stderr
index 5c19abffa02..3fedfd96417 100644
--- a/tests/ui/issues/issue-25901.stderr
+++ b/tests/ui/issues/issue-25901.stderr
@@ -16,7 +16,7 @@ note: impl defined here, but it is not `const`
 LL | impl Deref for A {
    | ^^^^^^^^^^^^^^^^
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    |
 LL + #![feature(const_trait_impl)]
diff --git a/tests/ui/issues/issue-7364.stderr b/tests/ui/issues/issue-7364.stderr
index 3bf59a6d711..d5b6dde1f10 100644
--- a/tests/ui/issues/issue-7364.stderr
+++ b/tests/ui/issues/issue-7364.stderr
@@ -18,7 +18,7 @@ LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
    |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/suspicious-double-ref-op.rs b/tests/ui/lint/suspicious-double-ref-op.rs
index bc8c23c7b89..5aeb81dbd65 100644
--- a/tests/ui/lint/suspicious-double-ref-op.rs
+++ b/tests/ui/lint/suspicious-double-ref-op.rs
@@ -1,4 +1,3 @@
-#![feature(lazy_cell)]
 #![deny(suspicious_double_ref_op, noop_method_call)]
 
 use std::borrow::Borrow;
diff --git a/tests/ui/lint/suspicious-double-ref-op.stderr b/tests/ui/lint/suspicious-double-ref-op.stderr
index f5a71d40fc1..c956843c507 100644
--- a/tests/ui/lint/suspicious-double-ref-op.stderr
+++ b/tests/ui/lint/suspicious-double-ref-op.stderr
@@ -1,29 +1,29 @@
 error: using `.clone()` on a double reference, which returns `&Vec<i32>` instead of cloning the inner type
-  --> $DIR/suspicious-double-ref-op.rs:15:23
+  --> $DIR/suspicious-double-ref-op.rs:14:23
    |
 LL |     let z: &Vec<_> = y.clone();
    |                       ^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/suspicious-double-ref-op.rs:2:9
+  --> $DIR/suspicious-double-ref-op.rs:1:9
    |
 LL | #![deny(suspicious_double_ref_op, noop_method_call)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: using `.clone()` on a double reference, which returns `&CloneType<u32>` instead of cloning the inner type
-  --> $DIR/suspicious-double-ref-op.rs:33:63
+  --> $DIR/suspicious-double-ref-op.rs:32:63
    |
 LL |     let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone();
    |                                                               ^^^^^^^^
 
 error: using `.deref()` on a double reference, which returns `&PlainType<u32>` instead of dereferencing the inner type
-  --> $DIR/suspicious-double-ref-op.rs:37:63
+  --> $DIR/suspicious-double-ref-op.rs:36:63
    |
 LL |     let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref();
    |                                                               ^^^^^^^^
 
 error: using `.clone()` on a double reference, which returns `&str` instead of cloning the inner type
-  --> $DIR/suspicious-double-ref-op.rs:41:44
+  --> $DIR/suspicious-double-ref-op.rs:40:44
    |
 LL |     let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // could use `*x` instead
    |                                            ^^^^^^^^
diff --git a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
index 7b896ce1426..66b57c772d5 100644
--- a/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
+++ b/tests/ui/parser/issues/issue-35813-postfix-after-cast.stderr
@@ -352,7 +352,7 @@ LL | static bar: &[i32] = &(&[1,2,3] as &[i32][0..1]);
    |                                          ^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    |
 LL + #![feature(const_trait_impl)]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs
index d43fabcedec..7bd372c1695 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/nested-closure.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-#![feature(const_trait_impl, lazy_cell)]
+#![feature(const_trait_impl)]
 
 use std::sync::LazyLock;
 
diff --git a/tests/ui/static/static-mut-not-constant.stderr b/tests/ui/static/static-mut-not-constant.stderr
index d125bec5943..46dc175cb29 100644
--- a/tests/ui/static/static-mut-not-constant.stderr
+++ b/tests/ui/static/static-mut-not-constant.stderr
@@ -5,7 +5,7 @@ LL | static mut a: Box<isize> = Box::new(3);
    |                            ^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/static/static-vec-repeat-not-constant.stderr b/tests/ui/static/static-vec-repeat-not-constant.stderr
index db0c7eb8d35..a3b930323d5 100644
--- a/tests/ui/static/static-vec-repeat-not-constant.stderr
+++ b/tests/ui/static/static-vec-repeat-not-constant.stderr
@@ -5,7 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2];
    |                         ^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/statics/check-values-constraints.stderr b/tests/ui/statics/check-values-constraints.stderr
index 45a699f575f..24763c175fc 100644
--- a/tests/ui/statics/check-values-constraints.stderr
+++ b/tests/ui/statics/check-values-constraints.stderr
@@ -26,7 +26,7 @@ LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
    |                                 ^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0015]: cannot call non-const fn `<str as ToString>::to_string` in statics
@@ -36,7 +36,7 @@ LL |     field2: SafeEnum::Variant4("str".to_string()),
    |                                      ^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
 help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    |
 LL + #![feature(const_trait_impl)]
@@ -57,7 +57,7 @@ LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
@@ -75,7 +75,7 @@ LL |     vec![MyOwned],
    |     ^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
@@ -93,7 +93,7 @@ LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
@@ -111,7 +111,7 @@ LL |     &vec![MyOwned],
    |      ^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
@@ -129,7 +129,7 @@ LL | static STATIC19: Vec<isize> = vec![3];
    |                               ^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0010]: allocations are not allowed in statics
@@ -147,7 +147,7 @@ LL |         static x: Vec<isize> = vec![3];
    |                                ^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
-   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
+   = note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0507]: cannot move out of static item `x`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs
new file mode 100644
index 00000000000..5820e49a4e5
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs
@@ -0,0 +1,28 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[next] failure-status: 101
+//@[next] known-bug: unknown
+//@[next] normalize-stderr-test "note: .*\n\n" -> ""
+//@[next] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
+//@[next] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@[next] normalize-stderr-test "delayed at .*" -> ""
+//@[next] rustc-env:RUST_BACKTRACE=0
+//@ check-pass
+
+#![feature(trait_upcasting)]
+
+trait Super {
+    type Assoc;
+}
+
+trait Sub: Super {}
+
+impl<T: ?Sized> Super for T {
+    type Assoc = i32;
+}
+
+fn illegal(x: &dyn Sub<Assoc = i32>) -> &dyn Super<Assoc = impl Sized> {
+    x
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
index f40c48f0d12..01759ec7a93 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -11,6 +11,10 @@ fn test_correct(x: &dyn Foo<'static>) {
     let _ = x as &dyn Bar<'static, 'static>;
 }
 
+fn test_correct2<'a>(x: &dyn Foo<'a>) {
+    let _ = x as &dyn Bar<'_, '_>;
+}
+
 fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
     let _ = x as &dyn Bar<'static, 'a>; // Error
                                         //~^ ERROR lifetime may not live long enough
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index 8d506e5807e..ccced587577 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:15:13
+  --> $DIR/type-checking-test-4.rs:19:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -7,7 +7,7 @@ LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:20:13
+  --> $DIR/type-checking-test-4.rs:24:13
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -15,7 +15,7 @@ LL |     let _ = x as &dyn Bar<'a, 'static>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:26:5
+  --> $DIR/type-checking-test-4.rs:30:5
    |
 LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -24,7 +24,7 @@ LL |     y.get_b() // ERROR
    |     ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:31:5
+  --> $DIR/type-checking-test-4.rs:35:5
    |
 LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -32,7 +32,7 @@ LL |     <_ as Bar>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:36:5
+  --> $DIR/type-checking-test-4.rs:40:5
    |
 LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -40,7 +40,7 @@ LL |     <_ as Bar<'_, '_>>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:44:5
+  --> $DIR/type-checking-test-4.rs:48:5
    |
 LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
new file mode 100644
index 00000000000..a3a1ce29465
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
@@ -0,0 +1,22 @@
+#![feature(trait_upcasting, type_alias_impl_trait)]
+
+//@ check-pass
+
+type Tait = impl Sized;
+
+trait Foo<'a>: Bar<'a, 'a, Tait> {}
+trait Bar<'a, 'b, T> {}
+
+fn test_correct(x: &dyn Foo<'static>) {
+    let _ = x as &dyn Bar<'static, 'static, Tait>;
+}
+
+fn test_correct2<'a>(x: &dyn Foo<'a>) {
+    let _ = x as &dyn Bar<'_, '_, Tait>;
+}
+
+fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
+    let _ = x as &dyn Bar<'_, '_, ()>;
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr
deleted file mode 100644
index a259abb28ae..00000000000
--- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.current.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/upcast-defining-opaque.rs:21:5
-   |
-LL | type Foo = impl Sized;
-   |            ---------- the found opaque type
-LL |
-LL | fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-   |                                        ----------------------- expected `&dyn Super<Assoc = i32>` because of return type
-LL |     x
-   |     ^ expected trait `Super`, found trait `Sub`
-   |
-   = note: expected reference `&dyn Super<Assoc = i32>`
-              found reference `&dyn Sub<Assoc = Foo>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
index cb1501a94a2..07f1549e177 100644
--- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
@@ -1,7 +1,7 @@
 //@ revisions: current next
 //@[next] compile-flags: -Znext-solver
 //@ ignore-compare-mode-next-solver (explicit revisions)
-//@[next] check-pass
+//@check-pass
 
 #![feature(trait_upcasting, type_alias_impl_trait)]
 
@@ -18,7 +18,7 @@ impl<T: ?Sized> Super for T {
 type Foo = impl Sized;
 
 fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
-    x //[current]~ mismatched types
+    x
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs
new file mode 100644
index 00000000000..2a246900106
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs
@@ -0,0 +1,27 @@
+//! Check that projections will constrain opaque types while looking for
+//! matching impls.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Foo;
+
+type Bar = impl Sized;
+
+trait Trait<T> {
+    type Assoc: Default;
+}
+
+impl Trait<()> for Foo {
+    type Assoc = u32;
+}
+
+fn bop(_: Bar) {
+    let x = <Foo as Trait<Bar>>::Assoc::default();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
new file mode 100644
index 00000000000..0d6eac4216b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
@@ -0,0 +1,19 @@
+error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
+  --> $DIR/constrain_in_projection2.rs:27:14
+   |
+LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
+   |              ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
+   |
+note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
+  --> $DIR/constrain_in_projection2.rs:18:1
+   |
+LL | impl Trait<()> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Trait<u32> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
new file mode 100644
index 00000000000..0d6eac4216b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
@@ -0,0 +1,19 @@
+error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
+  --> $DIR/constrain_in_projection2.rs:27:14
+   |
+LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
+   |              ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
+   |
+note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
+  --> $DIR/constrain_in_projection2.rs:18:1
+   |
+LL | impl Trait<()> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Trait<u32> for Foo {
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
new file mode 100644
index 00000000000..0066131f015
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
@@ -0,0 +1,31 @@
+//! Check that projections will constrain opaque types while looking for
+//! matching impls and error if ambiguous.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![feature(type_alias_impl_trait)]
+
+struct Foo;
+
+type Bar = impl Sized;
+
+trait Trait<T> {
+    type Assoc: Default;
+}
+
+impl Trait<()> for Foo {
+    type Assoc = u32;
+}
+
+impl Trait<u32> for Foo {
+    type Assoc = u32;
+}
+
+fn bop(_: Bar) {
+    let x = <Foo as Trait<Bar>>::Assoc::default();
+    //~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr
index 461da20f37b..a7ff097e8bf 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
-  --> $DIR/issue-84660-unsoundness.rs:23:1
+  --> $DIR/issue-84660-unsoundness.rs:28:1
    |
 LL | impl<In, Out> Trait<Bar, In> for Out {
    | ------------------------------------ first implementation here
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
new file mode 100644
index 00000000000..607f0b062ab
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
@@ -0,0 +1,23 @@
+error[E0284]: type annotations needed: cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
+  --> $DIR/issue-84660-unsoundness.rs:22:37
+   |
+LL |       fn convert(_i: In) -> Self::Out {
+   |  _____________________________________^
+LL | |
+LL | |         unreachable!();
+LL | |     }
+   | |_____^ cannot satisfy `<Out as Trait<Bar, In>>::Out == ()`
+
+error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
+  --> $DIR/issue-84660-unsoundness.rs:28:1
+   |
+LL | impl<In, Out> Trait<Bar, In> for Out {
+   | ------------------------------------ first implementation here
+...
+LL | impl<In, Out> Trait<(), In> for Out {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0119, E0284.
+For more information about an error, try `rustc --explain E0119`.
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index 48d4b0c96ff..99a5d36066b 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -1,6 +1,10 @@
 // Another example from issue #84660, this time weaponized as a safe transmute: an opaque type in an
 // impl header being accepted was used to create unsoundness.
 
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 #![feature(type_alias_impl_trait)]
 
 trait Foo {}
@@ -16,11 +20,13 @@ trait Trait<T, In> {
 impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
     fn convert(_i: In) -> Self::Out {
+        //[next]~^ ERROR: type annotations needed
         unreachable!();
     }
 }
 
-impl<In, Out> Trait<(), In> for Out { //~ ERROR conflicting implementations of trait `Trait<Bar, _>`
+impl<In, Out> Trait<(), In> for Out {
+    //~^ ERROR conflicting implementations of trait `Trait<Bar, _>`
     type Out = In;
     fn convert(i: In) -> Self::Out {
         i
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
index 82248971692..70495c44706 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
@@ -1,18 +1,21 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@check-pass
+
 use std::fmt::Debug;
 
 type FooX = impl Debug;
 
-trait Foo<A> { }
+trait Foo<A> {}
 
-impl Foo<()> for () { }
+impl Foo<()> for () {}
 
 fn foo() -> impl Foo<FooX> {
-    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
-    // FIXME(type-alias-impl-trait): We could probably make this work.
     ()
 }
 
-fn main() { }
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
new file mode 100644
index 00000000000..c7b7af152ab
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
@@ -0,0 +1,17 @@
+error[E0283]: type annotations needed: cannot satisfy `(): Foo<FooX>`
+  --> $DIR/nested-tait-inference2.rs:17:13
+   |
+LL | fn foo() -> impl Foo<FooX> {
+   |             ^^^^^^^^^^^^^^
+   |
+note: multiple `impl`s satisfying `(): Foo<FooX>` found
+  --> $DIR/nested-tait-inference2.rs:14:1
+   |
+LL | impl Foo<()> for () {}
+   | ^^^^^^^^^^^^^^^^^^^
+LL | impl Foo<u32> for () {}
+   | ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
new file mode 100644
index 00000000000..9647d9e376e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
+  --> $DIR/nested-tait-inference2.rs:19:5
+   |
+LL |     ()
+   |     ^^ cannot satisfy `impl Foo<FooX> == ()`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
index 0d7f5bad25f..fe2f76e552a 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
@@ -1,6 +1,10 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 use std::fmt::Debug;
 
 type FooX = impl Debug;
@@ -11,8 +15,9 @@ impl Foo<()> for () {}
 impl Foo<u32> for () {}
 
 fn foo() -> impl Foo<FooX> {
-    //~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
+    //[current]~^ ERROR: cannot satisfy `(): Foo<FooX>`
     ()
+    //[next]~^ ERROR: cannot satisfy `impl Foo<FooX> == ()`
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr
deleted file mode 100644
index 241342b0509..00000000000
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
-  --> $DIR/nested-tait-inference2.rs:13:13
-   |
-LL | fn foo() -> impl Foo<FooX> {
-   |             ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
-LL |
-LL |     ()
-   |     -- return type was inferred to be `()` here
-   |
-   = help: the following other types implement trait `Foo<A>`:
-             <() as Foo<()>>
-             <() as Foo<u32>>
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
index a40dac06a01..eff29303bf1 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -22,21 +22,17 @@ note: previous use here
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                               ^^^^^^^^^^^^^^^^^
 
-error[E0308]: mismatched types
+error: concrete type differs from previous defining opaque type use
   --> $DIR/normalize-hidden-types.rs:43:25
    |
-LL |     type Opaque = impl Sized;
-   |                   ---------- the expected opaque type
-...
 LL |         let _: Opaque = dyn_hoops::<u8>(0);
-   |                ------   ^^^^^^^^^^^^^^^^^^ expected opaque type, found `*const dyn FnOnce(())`
-   |                |
-   |                expected due to this
-   |
-   = note: expected opaque type `typeck::Opaque`
-              found raw pointer `*const (dyn FnOnce(()) + 'static)`
-   = help: consider constraining the associated type `<u8 as Trait>::Gat<'_>` to `()` or calling a method that returns `<u8 as Trait>::Gat<'_>`
-   = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
+   |                         ^^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
+   |
+note: previous use here
+  --> $DIR/normalize-hidden-types.rs:44:9
+   |
+LL |         None
+   |         ^^^^
 
 error: concrete type differs from previous defining opaque type use
   --> $DIR/normalize-hidden-types.rs:52:25
@@ -52,4 +48,3 @@ LL |         None
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
deleted file mode 100644
index 3ae3590ca7f..00000000000
--- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0277]: can't compare `i32` with `Foo`
-  --> $DIR/self-referential-2.rs:10:13
-   |
-LL | fn bar() -> Bar {
-   |             ^^^ no implementation for `i32 == Foo`
-LL |     42_i32
-   |     ------ return type was inferred to be `i32` here
-   |
-   = help: the trait `PartialEq<Foo>` is not implemented for `i32`
-   = help: the trait `PartialEq` is implemented for `i32`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs
index f96364ccfcd..f4102f2e2cb 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs
@@ -1,14 +1,14 @@
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
-//@[next] check-pass
+//@ check-pass
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl std::fmt::Debug;
 type Bar = impl PartialEq<Foo>;
 
 fn bar() -> Bar {
-    42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
+    42_i32
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs
index b33051da2d7..3b015ab322a 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-3.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs
@@ -5,7 +5,7 @@
 type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
 
 fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
-    //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
+    //~^ ERROR overflow normalizing the type alias `Bar<'a, 'b>`
     i
 }
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
index 32eac622e51..caa9f9691dd 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
@@ -1,15 +1,11 @@
-error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
+error[E0275]: overflow normalizing the type alias `Bar<'a, 'b>`
   --> $DIR/self-referential-3.rs:7:31
    |
 LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
-   |                               ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
-LL |
-LL |     i
-   |     - return type was inferred to be `&i32` here
+   |                               ^^^^^^^^^^^
    |
-   = help: the trait `PartialEq<Bar<'a, 'b>>` is not implemented for `&i32`
-   = help: the trait `PartialEq` is implemented for `i32`
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0275`.