about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-05-07 01:16:08 +0000
committerbors <bors@rust-lang.org>2025-05-07 01:16:08 +0000
commit891b8525477f5c41a9e56d7b70d64b41e7c344e3 (patch)
treed185493baa3410ef79143ebbdc0f8bdb189b1bb0
parent669c1ab9677ae8dc1d7db30b75fd173d06c0c75a (diff)
parent3d8ef7afcab3dd91b6234065b954ce83daa37f40 (diff)
downloadrust-891b8525477f5c41a9e56d7b70d64b41e7c344e3.tar.gz
rust-891b8525477f5c41a9e56d7b70d64b41e7c344e3.zip
Auto merge of #140726 - jhpratt:rollup-b6oxopx, r=jhpratt
Rollup of 9 pull requests

Successful merges:

 - #134273 (de-stabilize bench attribute)
 - #139534 (Added support for `apxf` target feature)
 - #140419 (Move `in_external_macro` to `SyntaxContext`)
 - #140483 (Comment on `Rc` abort-guard strategy without naming unrelated fn)
 - #140607 (support duplicate entries in the opaque_type_storage)
 - #140656 (collect all Fuchsia bindings into the `fuchsia` module)
 - #140668 (Implement `VecDeque::truncate_front()`)
 - #140709 (rustdoc: remove unportable markdown lint and old parser)
 - #140713 (Structurally resolve in `check_ref_cast` in new solver)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--Cargo.lock17
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs49
-rw-r--r--compiler/rustc_feature/src/unstable.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/_match.rs3
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs15
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs26
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs25
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/table.rs76
-rw-r--r--compiler/rustc_infer/src/infer/snapshot/undo_log.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs32
-rw-r--r--compiler/rustc_next_trait_solver/src/delegate.rs11
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs44
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs36
-rw-r--r--compiler/rustc_span/src/hygiene.rs25
-rw-r--r--compiler/rustc_span/src/lib.rs21
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/target_features.rs1
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml1
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs37
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs67
-rw-r--r--library/alloc/src/rc.rs10
-rw-r--r--library/alloctests/tests/lib.rs1
-rw-r--r--library/alloctests/tests/vec_deque.rs69
-rw-r--r--library/core/src/macros/mod.rs1
-rw-r--r--library/std/src/sys/pal/unix/fuchsia.rs321
-rw-r--r--library/std/src/sys/pal/unix/futex.rs54
-rw-r--r--library/std/src/sys/pal/unix/thread.rs19
-rw-r--r--library/std/src/sys/process/unix/fuchsia.rs4
-rw-r--r--library/std/src/sys/sync/mutex/fuchsia.rs6
-rw-r--r--src/librustdoc/Cargo.toml1
-rw-r--r--src/librustdoc/lint.rs10
-rw-r--r--src/librustdoc/passes/lint.rs4
-rw-r--r--src/librustdoc/passes/lint/unportable_markdown.rs145
-rw-r--r--src/tools/lint-docs/src/lib.rs1
-rw-r--r--tests/rustdoc-ui/unportable-markdown.rs62
-rw-r--r--tests/rustdoc-ui/unportable-markdown.stderr23
-rw-r--r--tests/ui/cast/cast-alias-of-array-to-element.rs22
-rw-r--r--tests/ui/check-cfg/target_feature.stderr1
-rw-r--r--tests/ui/feature-gates/bench.rs2
-rw-r--r--tests/ui/feature-gates/bench.stderr40
-rw-r--r--tests/ui/feature-gates/feature-gate-apx-target-feature.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-apx-target-feature.stderr13
-rw-r--r--tests/ui/lint/expansion-time.rs7
-rw-r--r--tests/ui/lint/expansion-time.stderr33
-rw-r--r--tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs25
46 files changed, 602 insertions, 770 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 98b90a47e39..83d7a6a9ab1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -558,7 +558,7 @@ dependencies = [
  "if_chain",
  "itertools",
  "parking_lot",
- "pulldown-cmark 0.11.3",
+ "pulldown-cmark",
  "quote",
  "regex",
  "rustc_tools_util 0.4.2",
@@ -2851,17 +2851,6 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.9.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
-dependencies = [
- "bitflags",
- "memchr",
- "unicase",
-]
-
-[[package]]
-name = "pulldown-cmark"
 version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "679341d22c78c6c649893cbd6c3278dcbe9fc4faa62fea3a9296ae2b50c14625"
@@ -4337,7 +4326,7 @@ version = "0.0.0"
 dependencies = [
  "bitflags",
  "itertools",
- "pulldown-cmark 0.11.3",
+ "pulldown-cmark",
  "rustc_arena",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -4516,7 +4505,6 @@ dependencies = [
  "rustc_session",
  "rustc_span",
  "rustc_transmute",
- "rustc_type_ir",
  "smallvec",
  "thin-vec",
  "tracing",
@@ -4622,7 +4610,6 @@ dependencies = [
  "indexmap",
  "itertools",
  "minifier",
- "pulldown-cmark 0.9.6",
  "pulldown-cmark-escape",
  "regex",
  "rustdoc-json-types",
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 264510285a5..8f57f0983ab 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -19,6 +19,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
 use rustc_span::Symbol;
 use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
 use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
+use smallvec::{SmallVec, smallvec};
 
 use crate::back::write::create_informational_target_machine;
 use crate::errors::{
@@ -180,27 +181,27 @@ impl<'a> TargetFeatureFoldStrength<'a> {
 
 pub(crate) struct LLVMFeature<'a> {
     llvm_feature_name: &'a str,
-    dependency: Option<TargetFeatureFoldStrength<'a>>,
+    dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
 }
 
 impl<'a> LLVMFeature<'a> {
     fn new(llvm_feature_name: &'a str) -> Self {
-        Self { llvm_feature_name, dependency: None }
+        Self { llvm_feature_name, dependencies: SmallVec::new() }
     }
 
-    fn with_dependency(
+    fn with_dependencies(
         llvm_feature_name: &'a str,
-        dependency: TargetFeatureFoldStrength<'a>,
+        dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
     ) -> Self {
-        Self { llvm_feature_name, dependency: Some(dependency) }
+        Self { llvm_feature_name, dependencies }
     }
 
-    fn contains(&self, feat: &str) -> bool {
+    fn contains(&'a self, feat: &str) -> bool {
         self.iter().any(|dep| dep == feat)
     }
 
     fn iter(&'a self) -> impl Iterator<Item = &'a str> {
-        let dependencies = self.dependency.iter().map(|feat| feat.as_str());
+        let dependencies = self.dependencies.iter().map(|feat| feat.as_str());
         std::iter::once(self.llvm_feature_name).chain(dependencies)
     }
 }
@@ -210,7 +211,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
     type IntoIter = impl Iterator<Item = &'a str>;
 
     fn into_iter(self) -> Self::IntoIter {
-        let dependencies = self.dependency.into_iter().map(|feat| feat.as_str());
+        let dependencies = self.dependencies.into_iter().map(|feat| feat.as_str());
         std::iter::once(self.llvm_feature_name).chain(dependencies)
     }
 }
@@ -240,9 +241,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         &*sess.target.arch
     };
     match (arch, s) {
-        ("x86", "sse4.2") => Some(LLVMFeature::with_dependency(
+        ("x86", "sse4.2") => Some(LLVMFeature::with_dependencies(
             "sse4.2",
-            TargetFeatureFoldStrength::EnableOnly("crc32"),
+            smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")],
         )),
         ("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")),
         ("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")),
@@ -262,9 +263,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
         ("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
         // Rust ties fp and neon together.
-        ("aarch64", "neon") => {
-            Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")))
-        }
+        ("aarch64", "neon") => Some(LLVMFeature::with_dependencies(
+            "neon",
+            smallvec![TargetFeatureFoldStrength::Both("fp-armv8")],
+        )),
         // In LLVM neon implicitly enables fp, but we manually enable
         // neon when a feature only implicitly enables fp
         ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")),
@@ -281,9 +283,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         // Filter out features that are not supported by the current LLVM version
         ("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
         // Enable the evex512 target feature if an avx512 target feature is enabled.
-        ("x86", s) if s.starts_with("avx512") => {
-            Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")))
-        }
+        ("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
+            s,
+            smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
+        )),
         // Support for `wide-arithmetic` will first land in LLVM 20 as part of
         // llvm/llvm-project#111598
         ("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
@@ -304,6 +307,18 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")),
         ("x86", "avx10.2") if get_version().0 < 20 => None,
         ("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")),
+        ("x86", "apxf") => Some(LLVMFeature::with_dependencies(
+            "egpr",
+            smallvec![
+                TargetFeatureFoldStrength::Both("push2pop2"),
+                TargetFeatureFoldStrength::Both("ppx"),
+                TargetFeatureFoldStrength::Both("ndd"),
+                TargetFeatureFoldStrength::Both("ccmp"),
+                TargetFeatureFoldStrength::Both("cf"),
+                TargetFeatureFoldStrength::Both("nf"),
+                TargetFeatureFoldStrength::Both("zu"),
+            ],
+        )),
         (_, s) => Some(LLVMFeature::new(s)),
     }
 }
@@ -853,7 +868,7 @@ pub(crate) fn global_llvm_features(
                         "{}{}",
                         enable_disable, llvm_feature.llvm_feature_name
                     ))
-                    .chain(llvm_feature.dependency.into_iter().filter_map(
+                    .chain(llvm_feature.dependencies.into_iter().filter_map(
                         move |feat| match (enable, feat) {
                             (_, TargetFeatureFoldStrength::Both(f))
                             | (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index f3412159a8a..a5f89b7a076 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -316,6 +316,7 @@ declare_features! (
     // Unstable `#[target_feature]` directives.
     (unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
     (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
+    (unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)),
     (unstable, arm_target_feature, "1.27.0", Some(44839)),
     (unstable, avx512_target_feature, "1.27.0", Some(44839)),
     (unstable, bpf_target_feature, "1.54.0", Some(44839)),
diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs
index 2e7831f16ae..61dd8c57307 100644
--- a/compiler/rustc_hir_typeck/src/_match.rs
+++ b/compiler/rustc_hir_typeck/src/_match.rs
@@ -603,7 +603,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
             ty::Infer(ty::TyVar(_)) => self
                 .inner
-                .borrow()
+                .borrow_mut()
+                .opaque_types()
                 .iter_opaque_types()
                 .find(|(_, v)| v.ty == expected_ty)
                 .map(|(k, _)| (k.def_id, k.args))?,
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index caf36ba47bd..5bfc3e810d9 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -1051,20 +1051,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     fn check_ref_cast(
         &self,
         fcx: &FnCtxt<'a, 'tcx>,
-        m_expr: ty::TypeAndMut<'tcx>,
-        m_cast: ty::TypeAndMut<'tcx>,
+        mut m_expr: ty::TypeAndMut<'tcx>,
+        mut m_cast: ty::TypeAndMut<'tcx>,
     ) -> Result<CastKind, CastError<'tcx>> {
         // array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
+        m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty);
+        m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty);
+
         if m_expr.mutbl >= m_cast.mutbl
             && let ty::Array(ety, _) = m_expr.ty.kind()
             && fcx.can_eq(fcx.param_env, *ety, m_cast.ty)
         {
-            // Due to the limitations of LLVM global constants,
-            // region pointers end up pointing at copies of
-            // vector elements instead of the original values.
-            // To allow raw pointers to work correctly, we
-            // need to special-case obtaining a raw pointer
-            // from a region pointer to a vector.
+            // Due to historical reasons we allow directly casting references of
+            // arrays into raw pointers of their element type.
 
             // Coerce to a raw pointer so that we generate RawPtr in MIR.
             let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 5220071c500..1ae864c454f 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -132,7 +132,13 @@ impl<'tcx> InferCtxt<'tcx> {
 
         let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };
 
-        let opaque_types = self.take_opaque_types_for_query_response();
+        let opaque_types = self
+            .inner
+            .borrow_mut()
+            .opaque_type_storage
+            .take_opaque_types()
+            .map(|(k, v)| (k, v.ty))
+            .collect();
 
         Ok(QueryResponse {
             var_values: inference_vars,
@@ -143,24 +149,6 @@ impl<'tcx> InferCtxt<'tcx> {
         })
     }
 
-    /// Used by the new solver as that one takes the opaque types at the end of a probe
-    /// to deal with multiple candidates without having to recompute them.
-    pub fn clone_opaque_types_for_query_response(
-        &self,
-    ) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
-        self.inner
-            .borrow()
-            .opaque_type_storage
-            .opaque_types
-            .iter()
-            .map(|(k, v)| (*k, v.ty))
-            .collect()
-    }
-
-    fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
-        self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
-    }
-
     /// Given the (canonicalized) result to a canonical query,
     /// instantiates the result so it can be used, plugging in the
     /// values from the canonical query. (Note that the result may
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index d25542dadd5..070d285b5a6 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::{
     self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
-    GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind,
-    Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
-    TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
+    GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueHiddenType, OpaqueTypeKey,
+    PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
+    TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
 };
 use rustc_span::{Span, Symbol};
 use snapshot::undo_log::InferCtxtUndoLogs;
@@ -198,7 +198,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
     }
 
     #[inline]
-    fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
+    pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
         self.opaque_type_storage.with_log(&mut self.undo_log)
     }
 
@@ -224,15 +224,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
             .expect("region constraints already solved")
             .with_log(&mut self.undo_log)
     }
-
-    // Iterates through the opaque type definitions without taking them; this holds the
-    // `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects
-    // while looping through this.
-    pub fn iter_opaque_types(
-        &self,
-    ) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> {
-        self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
-    }
 }
 
 pub struct InferCtxt<'tcx> {
@@ -954,13 +945,13 @@ impl<'tcx> InferCtxt<'tcx> {
     }
 
     #[instrument(level = "debug", skip(self), ret)]
-    pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
-        std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
+    pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
     }
 
     #[instrument(level = "debug", skip(self), ret)]
-    pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
-        self.inner.borrow().opaque_type_storage.opaque_types.clone()
+    pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
     }
 
     #[inline(always)]
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index ce5d2e6e17a..df7144c31da 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -1,5 +1,4 @@
 use hir::def_id::{DefId, LocalDefId};
-use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::traits::ObligationCause;
@@ -19,7 +18,6 @@ use crate::traits::{self, Obligation, PredicateObligations};
 
 mod table;
 
-pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>;
 pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};
 
 impl<'tcx> InferCtxt<'tcx> {
diff --git a/compiler/rustc_infer/src/infer/opaque_types/table.rs b/compiler/rustc_infer/src/infer/opaque_types/table.rs
index ba6cc0d783d..3c5bf9d722b 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/table.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/table.rs
@@ -1,18 +1,17 @@
+use std::ops::Deref;
+
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::undo_log::UndoLogs;
 use rustc_middle::bug;
 use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
 use tracing::instrument;
 
-use super::OpaqueTypeMap;
 use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};
 
 #[derive(Default, Debug, Clone)]
-pub(crate) struct OpaqueTypeStorage<'tcx> {
-    /// Opaque types found in explicit return types and their
-    /// associated fresh inference variable. Writeback resolves these
-    /// variables to get the concrete type, which can be used to
-    /// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.
-    pub opaque_types: OpaqueTypeMap<'tcx>,
+pub struct OpaqueTypeStorage<'tcx> {
+    opaque_types: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
+    duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
 }
 
 impl<'tcx> OpaqueTypeStorage<'tcx> {
@@ -33,6 +32,52 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
         }
     }
 
+    pub(crate) fn pop_duplicate_entry(&mut self) {
+        let entry = self.duplicate_entries.pop();
+        assert!(entry.is_some());
+    }
+
+    pub(crate) fn is_empty(&self) -> bool {
+        let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
+        opaque_types.is_empty() && duplicate_entries.is_empty()
+    }
+
+    pub(crate) fn take_opaque_types(
+        &mut self,
+    ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
+        std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
+    }
+
+    /// Only returns the opaque types from the lookup table. These are used
+    /// when normalizing opaque types and have a unique key.
+    ///
+    /// Outside of canonicalization one should generally use `iter_opaque_types`
+    /// to also consider duplicate entries.
+    pub fn iter_lookup_table(
+        &self,
+    ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        self.opaque_types.iter().map(|(k, v)| (*k, *v))
+    }
+
+    /// Only returns the opaque types which are stored in `duplicate_entries`.
+    ///
+    /// These have to considered when checking all opaque type uses but are e.g.
+    /// irrelevant for canonical inputs as nested queries never meaningfully
+    /// accesses them.
+    pub fn iter_duplicate_entries(
+        &self,
+    ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        self.duplicate_entries.iter().copied()
+    }
+
+    pub fn iter_opaque_types(
+        &self,
+    ) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
+        let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
+        opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())
+    }
+
     #[inline]
     pub(crate) fn with_log<'a>(
         &'a mut self,
@@ -44,21 +89,27 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
 
 impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
     fn drop(&mut self) {
-        if !self.opaque_types.is_empty() {
+        if !self.is_empty() {
             ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
         }
     }
 }
 
-pub(crate) struct OpaqueTypeTable<'a, 'tcx> {
+pub struct OpaqueTypeTable<'a, 'tcx> {
     storage: &'a mut OpaqueTypeStorage<'tcx>,
 
     undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
 }
+impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {
+    type Target = OpaqueTypeStorage<'tcx>;
+    fn deref(&self) -> &Self::Target {
+        self.storage
+    }
+}
 
 impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
     #[instrument(skip(self), level = "debug")]
-    pub(crate) fn register(
+    pub fn register(
         &mut self,
         key: OpaqueTypeKey<'tcx>,
         hidden_type: OpaqueHiddenType<'tcx>,
@@ -72,4 +123,9 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
         self.undo_log.push(UndoLog::OpaqueTypes(key, None));
         None
     }
+
+    pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {
+        self.storage.duplicate_entries.push((key, hidden_type));
+        self.undo_log.push(UndoLog::DuplicateOpaqueType);
+    }
 }
diff --git a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
index ba7d8f588e6..b7412d3d6a6 100644
--- a/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
+++ b/compiler/rustc_infer/src/infer/snapshot/undo_log.rs
@@ -17,6 +17,7 @@ pub struct Snapshot<'tcx> {
 /// Records the "undo" data for a single operation that affects some form of inference variable.
 #[derive(Clone)]
 pub(crate) enum UndoLog<'tcx> {
+    DuplicateOpaqueType,
     OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
     TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
     ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
@@ -58,6 +59,7 @@ impl_from! {
 impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
     fn reverse(&mut self, undo: UndoLog<'tcx>) {
         match undo {
+            UndoLog::DuplicateOpaqueType => self.opaque_type_storage.pop_duplicate_entry(),
             UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
             UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
             UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 03b8112938c..3cea24634fe 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2352,37 +2352,11 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `soft_unstable` lint detects unstable features that were
-    /// unintentionally allowed on stable.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// #[cfg(test)]
-    /// extern crate test;
-    ///
-    /// #[bench]
-    /// fn name(b: &mut test::Bencher) {
-    ///     b.iter(|| 123)
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// The [`bench` attribute] was accidentally allowed to be specified on
-    /// the [stable release channel]. Turning this to a hard error would have
-    /// broken some projects. This lint allows those projects to continue to
-    /// build correctly when [`--cap-lints`] is used, but otherwise signal an
-    /// error that `#[bench]` should not be used on the stable channel. This
-    /// is a [future-incompatible] lint to transition this to a hard error in
-    /// the future. See [issue #64266] for more details.
+    /// The `soft_unstable` lint detects unstable features that were unintentionally allowed on
+    /// stable. This is a [future-incompatible] lint to transition this to a hard error in the
+    /// future. See [issue #64266] for more details.
     ///
     /// [issue #64266]: https://github.com/rust-lang/rust/issues/64266
-    /// [`bench` attribute]: https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html
-    /// [stable release channel]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
-    /// [`--cap-lints`]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints
     /// [future-incompatible]: ../index.md#future-incompatible-lints
     pub SOFT_UNSTABLE,
     Deny,
diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs
index 25493970a0c..9e8fbd66b70 100644
--- a/compiler/rustc_next_trait_solver/src/delegate.rs
+++ b/compiler/rustc_next_trait_solver/src/delegate.rs
@@ -39,7 +39,10 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
         term: <Self::Interner as Interner>::Term,
     ) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;
 
-    fn clone_opaque_types_for_query_response(
+    fn clone_opaque_types_lookup_table(
+        &self,
+    ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
+    fn clone_duplicate_opaque_types(
         &self,
     ) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
 
@@ -68,6 +71,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
         hidden_ty: <Self::Interner as Interner>::Ty,
         span: <Self::Interner as Interner>::Span,
     ) -> Option<<Self::Interner as Interner>::Ty>;
+    fn add_duplicate_opaque_type(
+        &self,
+        opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
+        hidden_ty: <Self::Interner as Interner>::Ty,
+        span: <Self::Interner as Interner>::Span,
+    );
 
     fn add_item_bounds_for_hidden_type(
         &self,
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index dded84f6768..65b10e4f23f 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -56,7 +56,10 @@ where
         &self,
         goal: Goal<I, T>,
     ) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
-        let opaque_types = self.delegate.clone_opaque_types_for_query_response();
+        // We only care about one entry per `OpaqueTypeKey` here,
+        // so we only canonicalize the lookup table and ignore
+        // duplicate entries.
+        let opaque_types = self.delegate.clone_opaque_types_lookup_table();
         let (goal, opaque_types) =
             (goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));
 
@@ -241,19 +244,21 @@ where
             Default::default()
         };
 
-        ExternalConstraintsData {
-            region_constraints,
-            opaque_types: self
-                .delegate
-                .clone_opaque_types_for_query_response()
-                .into_iter()
-                // Only return *newly defined* opaque types.
-                .filter(|(a, _)| {
-                    self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
-                })
-                .collect(),
-            normalization_nested_goals,
-        }
+        // We only return *newly defined* opaque types from canonical queries.
+        //
+        // Constraints for any existing opaque types are already tracked by changes
+        // to the `var_values`.
+        let opaque_types = self
+            .delegate
+            .clone_opaque_types_lookup_table()
+            .into_iter()
+            .filter(|(a, _)| {
+                self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
+            })
+            .chain(self.delegate.clone_duplicate_opaque_types())
+            .collect();
+
+        ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
     }
 
     /// After calling a canonical query, we apply the constraints returned
@@ -432,7 +437,16 @@ where
     fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
         for &(key, ty) in opaque_types {
             let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
-            assert_eq!(prev, None);
+            // We eagerly resolve inference variables when computing the query response.
+            // This can cause previously distinct opaque type keys to now be structurally equal.
+            //
+            // To handle this, we store any duplicate entries in a separate list to check them
+            // at the end of typeck/borrowck. We could alternatively eagerly equate the hidden
+            // types here. However, doing so is difficult as it may result in nested goals and
+            // any errors may make it harder to track the control flow for diagnostics.
+            if let Some(prev) = prev {
+                self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span);
+            }
         }
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index 6dd554299a6..c13e7308055 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -14,7 +14,7 @@ use rustc_type_ir::{
     TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
     TypingMode,
 };
-use tracing::{instrument, trace};
+use tracing::{debug, instrument, trace};
 
 use super::has_only_region_constraints;
 use crate::coherence;
@@ -361,7 +361,20 @@ where
 
         for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
             let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
-            assert_eq!(prev, None);
+            // It may be possible that two entries in the opaque type storage end up
+            // with the same key after resolving contained inference variables.
+            //
+            // We could put them in the duplicate list but don't have to. The opaques we
+            // encounter here are already tracked in the caller, so there's no need to
+            // also store them here. We'd take them out when computing the query response
+            // and then discard them, as they're already present in the input.
+            //
+            // Ideally we'd drop duplicate opaque type definitions when computing
+            // the canonical input. This is more annoying to implement and may cause a
+            // perf regression, so we do it inside of the query for now.
+            if let Some(prev) = prev {
+                debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_type_storage`");
+            }
         }
 
         if !ecx.nested_goals.is_empty() {
@@ -1065,14 +1078,17 @@ where
         &mut self,
         key: ty::OpaqueTypeKey<I>,
     ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
-        let mut matching =
-            self.delegate.clone_opaque_types_for_query_response().into_iter().filter(
-                |(candidate_key, _)| {
-                    candidate_key.def_id == key.def_id
-                        && DeepRejectCtxt::relate_rigid_rigid(self.cx())
-                            .args_may_unify(candidate_key.args, key.args)
-                },
-            );
+        // We shouldn't have any duplicate entries when using
+        // this function during `TypingMode::Analysis`.
+        let duplicate_entries = self.delegate.clone_duplicate_opaque_types();
+        assert!(duplicate_entries.is_empty(), "unexpected duplicates: {duplicate_entries:?}");
+        let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter(
+            |(candidate_key, _)| {
+                candidate_key.def_id == key.def_id
+                    && DeepRejectCtxt::relate_rigid_rigid(self.cx())
+                        .args_may_unify(candidate_key.args, key.args)
+            },
+        );
         let first = matching.next();
         let second = matching.next();
         assert_eq!(second, None);
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index ab0a802dc7f..b621920d62b 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -41,6 +41,7 @@ use tracing::{debug, trace};
 
 use crate::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, StableCrateId};
 use crate::edition::Edition;
+use crate::source_map::SourceMap;
 use crate::symbol::{Symbol, kw, sym};
 use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};
 
@@ -907,6 +908,30 @@ impl SyntaxContext {
     pub fn edition(self) -> Edition {
         HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
     }
+
+    /// Returns whether this context originates in a foreign crate's external macro.
+    ///
+    /// This is used to test whether a lint should not even begin to figure out whether it should
+    /// be reported on the current node.
+    pub fn in_external_macro(self, sm: &SourceMap) -> bool {
+        let expn_data = self.outer_expn_data();
+        match expn_data.kind {
+            ExpnKind::Root
+            | ExpnKind::Desugaring(
+                DesugaringKind::ForLoop
+                | DesugaringKind::WhileLoop
+                | DesugaringKind::OpaqueTy
+                | DesugaringKind::Async
+                | DesugaringKind::Await,
+            ) => false,
+            ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
+            ExpnKind::Macro(MacroKind::Bang, _) => {
+                // Dummy span for the `def_site` means it's an external macro.
+                expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site)
+            }
+            ExpnKind::Macro { .. } => true, // definitely a plugin
+        }
+    }
 }
 
 impl fmt::Debug for SyntaxContext {
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 6fcf77e31a2..61c96e67c17 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -594,28 +594,13 @@ impl Span {
         !self.is_dummy() && sm.is_span_accessible(self)
     }
 
-    /// Returns whether `span` originates in a foreign crate's external macro.
+    /// Returns whether this span originates in a foreign crate's external macro.
     ///
     /// This is used to test whether a lint should not even begin to figure out whether it should
     /// be reported on the current node.
+    #[inline]
     pub fn in_external_macro(self, sm: &SourceMap) -> bool {
-        let expn_data = self.ctxt().outer_expn_data();
-        match expn_data.kind {
-            ExpnKind::Root
-            | ExpnKind::Desugaring(
-                DesugaringKind::ForLoop
-                | DesugaringKind::WhileLoop
-                | DesugaringKind::OpaqueTy
-                | DesugaringKind::Async
-                | DesugaringKind::Await,
-            ) => false,
-            ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
-            ExpnKind::Macro(MacroKind::Bang, _) => {
-                // Dummy span for the `def_site` means it's an external macro.
-                expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site)
-            }
-            ExpnKind::Macro { .. } => true, // definitely a plugin
-        }
+        self.ctxt().in_external_macro(sm)
     }
 
     /// Returns `true` if `span` originates in a derive-macro's expansion.
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index ea142e3d482..40cec408308 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -459,6 +459,7 @@ symbols! {
         anonymous_lifetime_in_impl_trait,
         any,
         append_const_msg,
+        apx_target_feature,
         arbitrary_enum_discriminant,
         arbitrary_self_types,
         arbitrary_self_types_pointers,
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index d04c8f3f2eb..5a21925ba04 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -393,6 +393,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
     ("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
     ("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
+    ("apxf", Unstable(sym::apx_target_feature), &[]),
     ("avx", Stable, &["sse4.2"]),
     (
         "avx10.1",
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index e6de2a3978d..1071105522d 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -20,7 +20,6 @@ rustc_parse_format = { path = "../rustc_parse_format" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
-rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2"
 tracing = "0.1"
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 908c058aabe..87b8db59a78 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -104,8 +104,23 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
         .map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect())
     }
 
-    fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
-        self.0.clone_opaque_types_for_query_response()
+    fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
+        self.0
+            .inner
+            .borrow_mut()
+            .opaque_types()
+            .iter_lookup_table()
+            .map(|(k, h)| (k, h.ty))
+            .collect()
+    }
+    fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
+        self.0
+            .inner
+            .borrow_mut()
+            .opaque_types()
+            .iter_duplicate_entries()
+            .map(|(k, h)| (k, h.ty))
+            .collect()
     }
 
     fn make_deduplicated_outlives_constraints(
@@ -156,14 +171,26 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
     fn register_hidden_type_in_storage(
         &self,
         opaque_type_key: ty::OpaqueTypeKey<'tcx>,
-        hidden_ty: <Self::Interner as rustc_type_ir::Interner>::Ty,
-        span: <Self::Interner as rustc_type_ir::Interner>::Span,
-    ) -> Option<<Self::Interner as rustc_type_ir::Interner>::Ty> {
+        hidden_ty: Ty<'tcx>,
+        span: Span,
+    ) -> Option<Ty<'tcx>> {
         self.0.register_hidden_type_in_storage(
             opaque_type_key,
             ty::OpaqueHiddenType { span, ty: hidden_ty },
         )
     }
+    fn add_duplicate_opaque_type(
+        &self,
+        opaque_type_key: ty::OpaqueTypeKey<'tcx>,
+        hidden_ty: Ty<'tcx>,
+        span: Span,
+    ) {
+        self.0
+            .inner
+            .borrow_mut()
+            .opaque_types()
+            .add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty })
+    }
 
     fn add_item_bounds_for_hidden_type(
         &self,
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index f8844e2d3a5..712f38a76c0 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1188,6 +1188,73 @@ impl<T, A: Allocator> VecDeque<T, A> {
         }
     }
 
+    /// Shortens the deque, keeping the last `len` elements and dropping
+    /// the rest.
+    ///
+    /// If `len` is greater or equal to the deque's current length, this has
+    /// no effect.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// # #![feature(vec_deque_truncate_front)]
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut buf = VecDeque::new();
+    /// buf.push_front(5);
+    /// buf.push_front(10);
+    /// buf.push_front(15);
+    /// assert_eq!(buf, [15, 10, 5]);
+    /// assert_eq!(buf.as_slices(), (&[15, 10, 5][..], &[][..]));
+    /// buf.truncate_front(1);
+    /// assert_eq!(buf.as_slices(), (&[5][..], &[][..]));
+    /// ```
+    #[unstable(feature = "vec_deque_truncate_front", issue = "140667")]
+    pub fn truncate_front(&mut self, len: usize) {
+        /// Runs the destructor for all items in the slice when it gets dropped (normally or
+        /// during unwinding).
+        struct Dropper<'a, T>(&'a mut [T]);
+
+        impl<'a, T> Drop for Dropper<'a, T> {
+            fn drop(&mut self) {
+                unsafe {
+                    ptr::drop_in_place(self.0);
+                }
+            }
+        }
+
+        unsafe {
+            if len >= self.len {
+                // No action is taken
+                return;
+            }
+
+            let (front, back) = self.as_mut_slices();
+            if len > back.len() {
+                // The 'back' slice remains unchanged.
+                // front.len() + back.len() == self.len, so 'end' is non-negative
+                // and end < front.len()
+                let end = front.len() - (len - back.len());
+                let drop_front = front.get_unchecked_mut(..end) as *mut _;
+                self.head += end;
+                self.len = len;
+                ptr::drop_in_place(drop_front);
+            } else {
+                let drop_front = front as *mut _;
+                // 'end' is non-negative by the condition above
+                let end = back.len() - len;
+                let drop_back = back.get_unchecked_mut(..end) as *mut _;
+                self.head = self.to_physical_idx(self.len - len);
+                self.len = len;
+
+                // Make sure the second half is dropped even when a destructor
+                // in the first one panics.
+                let _back_dropper = Dropper(&mut *drop_back);
+                ptr::drop_in_place(drop_front);
+            }
+        }
+    }
+
     /// Returns a reference to the underlying allocator.
     #[unstable(feature = "allocator_api", issue = "32838")]
     #[inline]
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 619d9f258e3..4b8ea708e7e 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -3536,11 +3536,11 @@ impl<T> Default for Weak<T> {
     }
 }
 
-// NOTE: We checked_add here to deal with mem::forget safely. In particular
-// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
-// you can free the allocation while outstanding Rcs (or Weaks) exist.
-// We abort because this is such a degenerate scenario that we don't care about
-// what happens -- no real program should ever experience this.
+// NOTE: If you mem::forget Rcs (or Weaks), drop is skipped and the ref-count
+// is not decremented, meaning the ref-count can overflow, and then you can
+// free the allocation while outstanding Rcs (or Weaks) exist, which would be
+// unsound. We abort because this is such a degenerate scenario that we don't
+// care about what happens -- no real program should ever experience this.
 //
 // This should have negligible overhead since you don't actually need to
 // clone these much in Rust thanks to ownership and move-semantics.
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index f1f4cc6f93b..38309585fad 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -37,6 +37,7 @@
 #![feature(str_as_str)]
 #![feature(strict_provenance_lints)]
 #![feature(vec_deque_pop_if)]
+#![feature(vec_deque_truncate_front)]
 #![feature(unique_rc_arc)]
 #![feature(macro_metavar_expr_concat)]
 #![allow(internal_features)]
diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs
index 1b03c29e5bd..b77ea3a312b 100644
--- a/library/alloctests/tests/vec_deque.rs
+++ b/library/alloctests/tests/vec_deque.rs
@@ -1688,6 +1688,40 @@ fn truncate_leak() {
 
 #[test]
 #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn truncate_front_leak() {
+    static mut DROPS: i32 = 0;
+
+    struct D(bool);
+
+    impl Drop for D {
+        fn drop(&mut self) {
+            unsafe {
+                DROPS += 1;
+            }
+
+            if self.0 {
+                panic!("panic in `drop`");
+            }
+        }
+    }
+
+    let mut q = VecDeque::new();
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_back(D(false));
+    q.push_front(D(true));
+    q.push_front(D(false));
+    q.push_front(D(false));
+
+    catch_unwind(AssertUnwindSafe(|| q.truncate_front(1))).ok();
+
+    assert_eq!(unsafe { DROPS }, 7);
+}
+
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
 fn test_drain_leak() {
     static mut DROPS: i32 = 0;
 
@@ -1863,3 +1897,38 @@ fn test_collect_from_into_iter_keeps_allocation() {
         assert_eq!(v.capacity(), 13);
     }
 }
+
+#[test]
+fn test_truncate_front() {
+    let mut v = VecDeque::with_capacity(13);
+    v.extend(0..7);
+    assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+    v.truncate_front(10);
+    assert_eq!(v.len(), 7);
+    assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+    v.truncate_front(7);
+    assert_eq!(v.len(), 7);
+    assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+    v.truncate_front(3);
+    assert_eq!(v.as_slices(), ([4, 5, 6].as_slice(), [].as_slice()));
+    assert_eq!(v.len(), 3);
+    v.truncate_front(0);
+    assert_eq!(v.as_slices(), ([].as_slice(), [].as_slice()));
+    assert_eq!(v.len(), 0);
+
+    v.clear();
+    v.extend(0..7);
+    assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+    v.push_front(9);
+    v.push_front(8);
+    v.push_front(7);
+    assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
+    v.truncate_front(12);
+    assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
+    v.truncate_front(10);
+    assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
+    v.truncate_front(8);
+    assert_eq!(v.as_slices(), ([9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
+    v.truncate_front(5);
+    assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
+}
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 3ad6662bdd7..7dc8c060cd5 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1661,7 +1661,6 @@ pub(crate) mod builtin {
     #[unstable(
         feature = "test",
         issue = "50297",
-        soft,
         reason = "`bench` is a part of custom test frameworks which are unstable"
     )]
     #[allow_internal_unstable(test, rustc_attrs, coverage_attribute)]
diff --git a/library/std/src/sys/pal/unix/fuchsia.rs b/library/std/src/sys/pal/unix/fuchsia.rs
index 7932bd26d76..c118dee6247 100644
--- a/library/std/src/sys/pal/unix/fuchsia.rs
+++ b/library/std/src/sys/pal/unix/fuchsia.rs
@@ -1,48 +1,35 @@
-#![allow(non_camel_case_types, unused)]
+#![expect(non_camel_case_types)]
 
-use libc::{c_int, c_void, size_t};
+use libc::size_t;
 
+use crate::ffi::{c_char, c_int, c_void};
 use crate::io;
-use crate::mem::MaybeUninit;
-use crate::os::raw::c_char;
 
-pub type zx_handle_t = u32;
-pub type zx_vaddr_t = usize;
-pub type zx_rights_t = u32;
-pub type zx_status_t = i32;
-
-pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
+//////////
+// Time //
+//////////
 
 pub type zx_time_t = i64;
-pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX;
-
-pub type zx_signals_t = u32;
-
-pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3;
 
-pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3;
+pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX;
 
-pub const ZX_RIGHT_SAME_RIGHTS: zx_rights_t = 1 << 31;
+unsafe extern "C" {
+    pub safe fn zx_clock_get_monotonic() -> zx_time_t;
+}
 
-// The upper four bits gives the minor version.
-pub type zx_object_info_topic_t = u32;
+/////////////
+// Handles //
+/////////////
 
-pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28);
+pub type zx_handle_t = u32;
 
-pub type zx_info_process_flags_t = u32;
+pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
 
-pub fn zx_cvt<T>(t: T) -> io::Result<T>
-where
-    T: TryInto<zx_status_t> + Copy,
-{
-    if let Ok(status) = TryInto::try_into(t) {
-        if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) }
-    } else {
-        Err(io::Error::last_os_error())
-    }
+unsafe extern "C" {
+    pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;
 }
 
-// Safe wrapper around zx_handle_t
+/// A safe wrapper around `zx_handle_t`.
 pub struct Handle {
     raw: zx_handle_t,
 }
@@ -65,6 +52,66 @@ impl Drop for Handle {
     }
 }
 
+///////////
+// Futex //
+///////////
+
+pub type zx_futex_t = crate::sync::atomic::Atomic<u32>;
+
+unsafe extern "C" {
+    pub fn zx_object_wait_one(
+        handle: zx_handle_t,
+        signals: zx_signals_t,
+        timeout: zx_time_t,
+        pending: *mut zx_signals_t,
+    ) -> zx_status_t;
+
+    pub fn zx_futex_wait(
+        value_ptr: *const zx_futex_t,
+        current_value: zx_futex_t,
+        new_futex_owner: zx_handle_t,
+        deadline: zx_time_t,
+    ) -> zx_status_t;
+    pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
+    pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
+    pub safe fn zx_thread_self() -> zx_handle_t;
+}
+
+////////////////
+// Properties //
+////////////////
+
+pub const ZX_PROP_NAME: u32 = 3;
+
+unsafe extern "C" {
+    pub fn zx_object_set_property(
+        handle: zx_handle_t,
+        property: u32,
+        value: *const libc::c_void,
+        value_size: libc::size_t,
+    ) -> zx_status_t;
+}
+
+/////////////
+// Signals //
+/////////////
+
+pub type zx_signals_t = u32;
+
+pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3;
+pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3;
+
+/////////////////
+// Object info //
+/////////////////
+
+// The upper four bits gives the minor version.
+pub type zx_object_info_topic_t = u32;
+
+pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28);
+
+pub type zx_info_process_flags_t = u32;
+
 // Returned for topic ZX_INFO_PROCESS
 #[derive(Default)]
 #[repr(C)]
@@ -76,25 +123,6 @@ pub struct zx_info_process_t {
 }
 
 unsafe extern "C" {
-    pub fn zx_job_default() -> zx_handle_t;
-
-    pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;
-
-    pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;
-
-    pub fn zx_handle_duplicate(
-        handle: zx_handle_t,
-        rights: zx_rights_t,
-        out: *const zx_handle_t,
-    ) -> zx_handle_t;
-
-    pub fn zx_object_wait_one(
-        handle: zx_handle_t,
-        signals: zx_signals_t,
-        timeout: zx_time_t,
-        pending: *mut zx_signals_t,
-    ) -> zx_status_t;
-
     pub fn zx_object_get_info(
         handle: zx_handle_t,
         topic: u32,
@@ -105,6 +133,10 @@ unsafe extern "C" {
     ) -> zx_status_t;
 }
 
+///////////////
+// Processes //
+///////////////
+
 #[derive(Default)]
 #[repr(C)]
 pub struct fdio_spawn_action_t {
@@ -130,6 +162,8 @@ unsafe extern "C" {
 
     pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t;
     pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t;
+
+    pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;
 }
 
 // fdio_spawn_etc flags
@@ -137,173 +171,34 @@ unsafe extern "C" {
 pub const FDIO_SPAWN_CLONE_JOB: u32 = 0x0001;
 pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
 pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
-pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
 pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
 pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020;
-pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;
 
 // fdio_spawn_etc actions
 
-pub const FDIO_SPAWN_ACTION_CLONE_FD: u32 = 0x0001;
 pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002;
 
-// Errors
-
-#[allow(unused)]
-pub const ERR_INTERNAL: zx_status_t = -1;
-
-// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
-// or enabled.
-#[allow(unused)]
-pub const ERR_NOT_SUPPORTED: zx_status_t = -2;
-
-// ERR_NO_RESOURCES: The system was not able to allocate some resource
-// needed for the operation.
-#[allow(unused)]
-pub const ERR_NO_RESOURCES: zx_status_t = -3;
-
-// ERR_NO_MEMORY: The system was not able to allocate memory needed
-// for the operation.
-#[allow(unused)]
-pub const ERR_NO_MEMORY: zx_status_t = -4;
-
-// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete
-// successfully.
-#[allow(unused)]
-pub const ERR_CALL_FAILED: zx_status_t = -5;
-
-// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
-// retried.  This should not be seen outside of the VDSO.
-#[allow(unused)]
-pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6;
-
-// ======= Parameter errors =======
-// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
-#[allow(unused)]
-pub const ERR_INVALID_ARGS: zx_status_t = -10;
-
-// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
-#[allow(unused)]
-pub const ERR_BAD_HANDLE: zx_status_t = -11;
-
-// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
-// perform the operation.
-// Example: Attempting a message_read on a thread handle.
-#[allow(unused)]
-pub const ERR_WRONG_TYPE: zx_status_t = -12;
-
-// ERR_BAD_SYSCALL: The specified syscall number is invalid.
-#[allow(unused)]
-pub const ERR_BAD_SYSCALL: zx_status_t = -13;
-
-// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
-// operation.
-#[allow(unused)]
-pub const ERR_OUT_OF_RANGE: zx_status_t = -14;
-
-// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
-// this operation.
-#[allow(unused)]
-pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15;
-
-// ======= Precondition or state errors =======
-// ERR_BAD_STATE: operation failed because the current state of the
-// object does not allow it, or a precondition of the operation is
-// not satisfied
-#[allow(unused)]
-pub const ERR_BAD_STATE: zx_status_t = -20;
-
-// ERR_TIMED_OUT: The time limit for the operation elapsed before
-// the operation completed.
-#[allow(unused)]
-pub const ERR_TIMED_OUT: zx_status_t = -21;
-
-// ERR_SHOULD_WAIT: The operation cannot be performed currently but
-// potentially could succeed if the caller waits for a prerequisite
-// to be satisfied, for example waiting for a handle to be readable
-// or writable.
-// Example: Attempting to read from a message pipe that has no
-// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
-// Attempting to read from a message pipe that has no messages waiting
-// and has a closed remote end will return ERR_REMOTE_CLOSED.
-#[allow(unused)]
-pub const ERR_SHOULD_WAIT: zx_status_t = -22;
-
-// ERR_CANCELED: The in-progress operation (e.g., a wait) has been
-// // canceled.
-#[allow(unused)]
-pub const ERR_CANCELED: zx_status_t = -23;
-
-// ERR_PEER_CLOSED: The operation failed because the remote end
-// of the subject of the operation was closed.
-#[allow(unused)]
-pub const ERR_PEER_CLOSED: zx_status_t = -24;
-
-// ERR_NOT_FOUND: The requested entity is not found.
-#[allow(unused)]
-pub const ERR_NOT_FOUND: zx_status_t = -25;
-
-// ERR_ALREADY_EXISTS: An object with the specified identifier
-// already exists.
-// Example: Attempting to create a file when a file already exists
-// with that name.
-#[allow(unused)]
-pub const ERR_ALREADY_EXISTS: zx_status_t = -26;
-
-// ERR_ALREADY_BOUND: The operation failed because the named entity
-// is already owned or controlled by another entity. The operation
-// could succeed later if the current owner releases the entity.
-#[allow(unused)]
-pub const ERR_ALREADY_BOUND: zx_status_t = -27;
-
-// ERR_UNAVAILABLE: The subject of the operation is currently unable
-// to perform the operation.
-// Note: This is used when there's no direct way for the caller to
-// observe when the subject will be able to perform the operation
-// and should thus retry.
-#[allow(unused)]
-pub const ERR_UNAVAILABLE: zx_status_t = -28;
-
-// ======= Permission check errors =======
-// ERR_ACCESS_DENIED: The caller did not have permission to perform
-// the specified operation.
-#[allow(unused)]
-pub const ERR_ACCESS_DENIED: zx_status_t = -30;
-
-// ======= Input-output errors =======
-// ERR_IO: Otherwise unspecified error occurred during I/O.
-#[allow(unused)]
-pub const ERR_IO: zx_status_t = -40;
-
-// ERR_REFUSED: The entity the I/O operation is being performed on
-// rejected the operation.
-// Example: an I2C device NAK'ing a transaction or a disk controller
-// rejecting an invalid command.
-#[allow(unused)]
-pub const ERR_IO_REFUSED: zx_status_t = -41;
-
-// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
-// check and is possibly corrupted.
-// Example: CRC or Parity error.
-#[allow(unused)]
-pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42;
-
-// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
-// and may be permanently lost.
-// Example: A disk block is irrecoverably damaged.
-#[allow(unused)]
-pub const ERR_IO_DATA_LOSS: zx_status_t = -43;
-
-// Filesystem specific errors
-#[allow(unused)]
-pub const ERR_BAD_PATH: zx_status_t = -50;
-#[allow(unused)]
-pub const ERR_NOT_DIR: zx_status_t = -51;
-#[allow(unused)]
-pub const ERR_NOT_FILE: zx_status_t = -52;
-// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
-#[allow(unused)]
-pub const ERR_FILE_BIG: zx_status_t = -53;
-// ERR_NO_SPACE: Filesystem or device space is exhausted.
-#[allow(unused)]
-pub const ERR_NO_SPACE: zx_status_t = -54;
+////////////
+// Errors //
+////////////
+
+pub type zx_status_t = i32;
+
+pub const ZX_OK: zx_status_t = 0;
+pub const ZX_ERR_NOT_SUPPORTED: zx_status_t = -2;
+pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
+pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
+pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
+pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
+pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;
+
+pub fn zx_cvt<T>(t: T) -> io::Result<T>
+where
+    T: TryInto<zx_status_t> + Copy,
+{
+    if let Ok(status) = TryInto::try_into(t) {
+        if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) }
+    } else {
+        Err(io::Error::last_os_error())
+    }
+}
diff --git a/library/std/src/sys/pal/unix/futex.rs b/library/std/src/sys/pal/unix/futex.rs
index 8d89163c42c..c23278bdf5e 100644
--- a/library/std/src/sys/pal/unix/futex.rs
+++ b/library/std/src/sys/pal/unix/futex.rs
@@ -255,66 +255,28 @@ pub fn futex_wake_all(futex: &Atomic<u32>) {
 }
 
 #[cfg(target_os = "fuchsia")]
-pub mod zircon {
-    pub type zx_futex_t = crate::sync::atomic::Atomic<u32>;
-    pub type zx_handle_t = u32;
-    pub type zx_status_t = i32;
-    pub type zx_time_t = i64;
-
-    pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
-
-    pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX;
-
-    pub const ZX_OK: zx_status_t = 0;
-    pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
-    pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
-    pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
-    pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
-    pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;
-
-    unsafe extern "C" {
-        pub fn zx_clock_get_monotonic() -> zx_time_t;
-        pub fn zx_futex_wait(
-            value_ptr: *const zx_futex_t,
-            current_value: zx_futex_t,
-            new_futex_owner: zx_handle_t,
-            deadline: zx_time_t,
-        ) -> zx_status_t;
-        pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
-        pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
-        pub fn zx_thread_self() -> zx_handle_t;
-    }
-}
-
-#[cfg(target_os = "fuchsia")]
 pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
+    use super::fuchsia::*;
+
     // Sleep forever if the timeout is longer than fits in a i64.
     let deadline = timeout
-        .and_then(|d| {
-            i64::try_from(d.as_nanos())
-                .ok()?
-                .checked_add(unsafe { zircon::zx_clock_get_monotonic() })
-        })
-        .unwrap_or(zircon::ZX_TIME_INFINITE);
+        .and_then(|d| i64::try_from(d.as_nanos()).ok()?.checked_add(zx_clock_get_monotonic()))
+        .unwrap_or(ZX_TIME_INFINITE);
 
     unsafe {
-        zircon::zx_futex_wait(
-            futex,
-            core::sync::atomic::AtomicU32::new(expected),
-            zircon::ZX_HANDLE_INVALID,
-            deadline,
-        ) != zircon::ZX_ERR_TIMED_OUT
+        zx_futex_wait(futex, zx_futex_t::new(expected), ZX_HANDLE_INVALID, deadline)
+            != ZX_ERR_TIMED_OUT
     }
 }
 
 // Fuchsia doesn't tell us how many threads are woken up, so this always returns false.
 #[cfg(target_os = "fuchsia")]
 pub fn futex_wake(futex: &Atomic<u32>) -> bool {
-    unsafe { zircon::zx_futex_wake(futex, 1) };
+    unsafe { super::fuchsia::zx_futex_wake(futex, 1) };
     false
 }
 
 #[cfg(target_os = "fuchsia")]
 pub fn futex_wake_all(futex: &Atomic<u32>) {
-    unsafe { zircon::zx_futex_wake(futex, u32::MAX) };
+    unsafe { super::fuchsia::zx_futex_wake(futex, u32::MAX) };
 }
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 4cdc2eaf0e5..afda7c65e10 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -22,23 +22,6 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
 #[cfg(any(target_os = "espidf", target_os = "nuttx"))]
 pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used
 
-#[cfg(target_os = "fuchsia")]
-mod zircon {
-    type zx_handle_t = u32;
-    type zx_status_t = i32;
-    pub const ZX_PROP_NAME: u32 = 3;
-
-    unsafe extern "C" {
-        pub fn zx_object_set_property(
-            handle: zx_handle_t,
-            property: u32,
-            value: *const libc::c_void,
-            value_size: libc::size_t,
-        ) -> zx_status_t;
-        pub fn zx_thread_self() -> zx_handle_t;
-    }
-}
-
 pub struct Thread {
     id: libc::pthread_t,
 }
@@ -216,7 +199,7 @@ impl Thread {
 
     #[cfg(target_os = "fuchsia")]
     pub fn set_name(name: &CStr) {
-        use self::zircon::*;
+        use super::fuchsia::*;
         unsafe {
             zx_object_set_property(
                 zx_thread_self(),
diff --git a/library/std/src/sys/process/unix/fuchsia.rs b/library/std/src/sys/process/unix/fuchsia.rs
index fbe06c4799b..017ab91797c 100644
--- a/library/std/src/sys/process/unix/fuchsia.rs
+++ b/library/std/src/sys/process/unix/fuchsia.rs
@@ -76,7 +76,7 @@ impl Command {
 
                 let mut handle = ZX_HANDLE_INVALID;
                 let status = fdio_fd_clone(target_fd, &mut handle);
-                if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED {
+                if status == ZX_ERR_INVALID_ARGS || status == ZX_ERR_NOT_SUPPORTED {
                     // This descriptor is closed; skip it rather than generating an
                     // error.
                     return Ok(Default::default());
@@ -192,7 +192,7 @@ impl Process {
                 zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, 0, ptr::null_mut());
             match status {
                 0 => {} // Success
-                x if x == ERR_TIMED_OUT => {
+                x if x == ZX_ERR_TIMED_OUT => {
                     return Ok(None);
                 }
                 _ => {
diff --git a/library/std/src/sys/sync/mutex/fuchsia.rs b/library/std/src/sys/sync/mutex/fuchsia.rs
index 3d388a4564a..cbb1926530f 100644
--- a/library/std/src/sys/sync/mutex/fuchsia.rs
+++ b/library/std/src/sys/sync/mutex/fuchsia.rs
@@ -39,7 +39,7 @@
 
 use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
 use crate::sync::atomic::{Atomic, AtomicU32};
-use crate::sys::futex::zircon::{
+use crate::sys::fuchsia::{
     ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE,
     ZX_OK, ZX_TIME_INFINITE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t,
     zx_thread_self,
@@ -83,13 +83,13 @@ impl Mutex {
 
     #[inline]
     pub fn try_lock(&self) -> bool {
-        let thread_self = unsafe { zx_thread_self() };
+        let thread_self = zx_thread_self();
         self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed).is_ok()
     }
 
     #[inline]
     pub fn lock(&self) {
-        let thread_self = unsafe { zx_thread_self() };
+        let thread_self = zx_thread_self();
         if let Err(state) =
             self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed)
         {
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 27ae0553c60..dbfdd8ebd16 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -14,7 +14,6 @@ base64 = "0.21.7"
 itertools = "0.12"
 indexmap = "2"
 minifier = { version = "0.3.5", default-features = false }
-pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false }
 pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
 regex = "1"
 rustdoc-json-types = { path = "../rustdoc-json-types" }
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index dcc27cd62e3..b09ea056885 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -196,14 +196,6 @@ declare_rustdoc_lint! {
     "detects redundant explicit links in doc comments"
 }
 
-declare_rustdoc_lint! {
-    /// This compatibility lint checks for Markdown syntax that works in the old engine but not
-    /// the new one.
-    UNPORTABLE_MARKDOWN,
-    Warn,
-    "detects markdown that is interpreted differently in different parser"
-}
-
 pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
     vec![
         BROKEN_INTRA_DOC_LINKS,
@@ -217,7 +209,6 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
         MISSING_CRATE_LEVEL_DOCS,
         UNESCAPED_BACKTICKS,
         REDUNDANT_EXPLICIT_LINKS,
-        UNPORTABLE_MARKDOWN,
     ]
 });
 
@@ -241,4 +232,5 @@ pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
         .register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
     lint_store.register_renamed("non_autolinks", "rustdoc::bare_urls");
     lint_store.register_renamed("rustdoc::non_autolinks", "rustdoc::bare_urls");
+    lint_store.register_removed("rustdoc::unportable_markdown", "old parser removed");
 }
diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs
index 1ecb53e61ac..7740d14148b 100644
--- a/src/librustdoc/passes/lint.rs
+++ b/src/librustdoc/passes/lint.rs
@@ -6,7 +6,6 @@ mod check_code_block_syntax;
 mod html_tags;
 mod redundant_explicit_links;
 mod unescaped_backticks;
-mod unportable_markdown;
 
 use super::Pass;
 use crate::clean::*;
@@ -49,9 +48,6 @@ impl DocVisitor<'_> for Linter<'_, '_> {
             }
             if may_have_block_comment_or_html {
                 html_tags::visit_item(self.cx, item, hir_id, &dox);
-                unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
-            } else if may_have_link {
-                unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
             }
         }
 
diff --git a/src/librustdoc/passes/lint/unportable_markdown.rs b/src/librustdoc/passes/lint/unportable_markdown.rs
deleted file mode 100644
index 95646413a2d..00000000000
--- a/src/librustdoc/passes/lint/unportable_markdown.rs
+++ /dev/null
@@ -1,145 +0,0 @@
-//! Detects specific markdown syntax that's different between pulldown-cmark
-//! 0.9 and 0.11.
-//!
-//! This is a mitigation for old parser bugs that affected some
-//! real crates' docs. The old parser claimed to comply with CommonMark,
-//! but it did not. These warnings will eventually be removed,
-//! though some of them may become Clippy lints.
-//!
-//! <https://github.com/rust-lang/rust/pull/121659#issuecomment-1992752820>
-//!
-//! <https://rustc-dev-guide.rust-lang.org/bug-fix-procedure.html#add-the-lint-to-the-list-of-removed-lists>
-
-use std::collections::{BTreeMap, BTreeSet};
-
-use rustc_hir::HirId;
-use rustc_lint_defs::Applicability;
-use rustc_resolve::rustdoc::source_span_for_markdown_range;
-use {pulldown_cmark as cmarkn, pulldown_cmark_old as cmarko};
-
-use crate::clean::Item;
-use crate::core::DocContext;
-
-pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &str) {
-    let tcx = cx.tcx;
-
-    // P1: unintended strikethrough was fixed by requiring single-tildes to flank
-    // the same way underscores do, so nothing is done here
-
-    // P2: block quotes without following space parsed wrong
-    //
-    // This is the set of starting points for block quotes with no space after
-    // the `>`. It is populated by the new parser, and if the old parser fails to
-    // clear it out, it'll produce a warning.
-    let mut spaceless_block_quotes = BTreeSet::new();
-
-    // P3: missing footnote references
-    //
-    // This is populated by listening for FootnoteReference from
-    // the new parser and old parser.
-    let mut missing_footnote_references = BTreeMap::new();
-    let mut found_footnote_references = BTreeSet::new();
-
-    // populate problem cases from new parser
-    {
-        pub fn main_body_opts_new() -> cmarkn::Options {
-            cmarkn::Options::ENABLE_TABLES
-                | cmarkn::Options::ENABLE_FOOTNOTES
-                | cmarkn::Options::ENABLE_STRIKETHROUGH
-                | cmarkn::Options::ENABLE_TASKLISTS
-                | cmarkn::Options::ENABLE_SMART_PUNCTUATION
-        }
-        let parser_new = cmarkn::Parser::new_ext(dox, main_body_opts_new()).into_offset_iter();
-        for (event, span) in parser_new {
-            if let cmarkn::Event::Start(cmarkn::Tag::BlockQuote(_)) = event {
-                if !dox[span.clone()].starts_with("> ") {
-                    spaceless_block_quotes.insert(span.start);
-                }
-            }
-            if let cmarkn::Event::FootnoteReference(_) = event {
-                found_footnote_references.insert(span.start + 1);
-            }
-        }
-    }
-
-    // remove cases where they don't actually differ
-    {
-        pub fn main_body_opts_old() -> cmarko::Options {
-            cmarko::Options::ENABLE_TABLES
-                | cmarko::Options::ENABLE_FOOTNOTES
-                | cmarko::Options::ENABLE_STRIKETHROUGH
-                | cmarko::Options::ENABLE_TASKLISTS
-                | cmarko::Options::ENABLE_SMART_PUNCTUATION
-        }
-        let parser_old = cmarko::Parser::new_ext(dox, main_body_opts_old()).into_offset_iter();
-        for (event, span) in parser_old {
-            if let cmarko::Event::Start(cmarko::Tag::BlockQuote) = event
-                && !dox[span.clone()].starts_with("> ")
-            {
-                spaceless_block_quotes.remove(&span.start);
-            }
-            if let cmarko::Event::FootnoteReference(_) = event
-                && !found_footnote_references.contains(&(span.start + 1))
-            {
-                missing_footnote_references.insert(span.start + 1, span);
-            }
-        }
-    }
-
-    for start in spaceless_block_quotes {
-        let (span, precise) =
-            source_span_for_markdown_range(tcx, dox, &(start..start + 1), &item.attrs.doc_strings)
-                .map(|span| (span, true))
-                .unwrap_or_else(|| (item.attr_span(tcx), false));
-
-        tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, span, |lint| {
-            lint.primary_message("unportable markdown");
-            lint.help("confusing block quote with no space after the `>` marker".to_string());
-            if precise {
-                lint.span_suggestion(
-                    span.shrink_to_hi(),
-                    "if the quote is intended, add a space",
-                    " ",
-                    Applicability::MaybeIncorrect,
-                );
-                lint.span_suggestion(
-                    span.shrink_to_lo(),
-                    "if it should not be a quote, escape it",
-                    "\\",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-        });
-    }
-    for (_caret, span) in missing_footnote_references {
-        let (ref_span, precise) =
-            source_span_for_markdown_range(tcx, dox, &span, &item.attrs.doc_strings)
-                .map(|span| (span, true))
-                .unwrap_or_else(|| (item.attr_span(tcx), false));
-
-        tcx.node_span_lint(crate::lint::UNPORTABLE_MARKDOWN, hir_id, ref_span, |lint| {
-            lint.primary_message("unportable markdown");
-            if precise {
-                lint.span_suggestion(
-                    ref_span.shrink_to_lo(),
-                    "if it should not be a footnote, escape it",
-                    "\\",
-                    Applicability::MaybeIncorrect,
-                );
-            }
-            if dox.as_bytes().get(span.end) == Some(&b'[') {
-                lint.help("confusing footnote reference and link");
-                if precise {
-                    lint.span_suggestion(
-                        ref_span.shrink_to_hi(),
-                        "if the footnote is intended, add a space",
-                        " ",
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    lint.help("there should be a space between the link and the footnote");
-                }
-            }
-        });
-    }
-}
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index d6c69d39e17..cacce01675f 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -312,6 +312,7 @@ impl<'a> LintExtractor<'a> {
         if matches!(
             lint.name.as_str(),
             "unused_features" // broken lint
+            | "soft_unstable" // cannot have a stable example
         ) {
             return Ok(());
         }
diff --git a/tests/rustdoc-ui/unportable-markdown.rs b/tests/rustdoc-ui/unportable-markdown.rs
deleted file mode 100644
index 105fc1e59d5..00000000000
--- a/tests/rustdoc-ui/unportable-markdown.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-// https://internals.rust-lang.org/t/proposal-migrate-the-syntax-of-rustdoc-markdown-footnotes-to-be-compatible-with-the-syntax-used-in-github/18929
-//
-// A series of test cases for CommonMark corner cases that pulldown-cmark 0.11 fixes.
-//
-// This version of the lint is targeted at two especially-common cases where docs got broken.
-// Other differences in parsing should not warn.
-#![allow(rustdoc::broken_intra_doc_links)]
-#![deny(rustdoc::unportable_markdown)]
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/654>
-///
-/// Test footnote [^foot].
-///
-/// [^foot]: This is nested within the footnote now, but didn't used to be.
-///
-///     This is a multi-paragraph footnote.
-pub struct GfmFootnotes;
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/773>
-///
-/// test [^foo][^bar]
-///
-/// [^foo]: test
-/// [^bar]: test2
-pub struct FootnoteSmashedName;
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/829>
-///
-/// - _t
-///   # test
-///   t_
-pub struct NestingCornerCase;
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/650>
-///
-/// *~~__emphasis strike strong__~~* ~~*__strike emphasis strong__*~~
-pub struct Emphasis1;
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/732>
-///
-/// |
-/// |
-pub struct NotEnoughTable;
-
-/// <https://github.com/pulldown-cmark/pulldown-cmark/pull/675>
-///
-/// foo
-/// >bar
-//~^ ERROR unportable markdown
-pub struct BlockQuoteNoSpace;
-
-/// Negative test.
-///
-/// foo
-/// > bar
-pub struct BlockQuoteSpace;
-
-/// Negative test.
-///
-/// >bar
-/// baz
-pub struct BlockQuoteNoSpaceStart;
diff --git a/tests/rustdoc-ui/unportable-markdown.stderr b/tests/rustdoc-ui/unportable-markdown.stderr
deleted file mode 100644
index 952ae4bb6ee..00000000000
--- a/tests/rustdoc-ui/unportable-markdown.stderr
+++ /dev/null
@@ -1,23 +0,0 @@
-error: unportable markdown
-  --> $DIR/unportable-markdown.rs:48:5
-   |
-LL | /// >bar
-   |     ^
-   |
-   = help: confusing block quote with no space after the `>` marker
-note: the lint level is defined here
-  --> $DIR/unportable-markdown.rs:8:9
-   |
-LL | #![deny(rustdoc::unportable_markdown)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: if the quote is intended, add a space
-   |
-LL | /// > bar
-   |      +
-help: if it should not be a quote, escape it
-   |
-LL | /// \>bar
-   |     +
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/cast/cast-alias-of-array-to-element.rs b/tests/ui/cast/cast-alias-of-array-to-element.rs
new file mode 100644
index 00000000000..124d0e0346f
--- /dev/null
+++ b/tests/ui/cast/cast-alias-of-array-to-element.rs
@@ -0,0 +1,22 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/203>.
+// Test that we structually normalize in the hacky `&[T; N] -> *const T` in cast.
+
+trait Mirror {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Mirror for T {
+    type Assoc = T;
+}
+
+struct W<'a>(&'a <[f32; 0] as Mirror>::Assoc);
+
+fn foo(x: W<'_>) -> *const f32 {
+    x.0 as *const f32
+}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index 3d7323298ba..eb66633f9dd 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -27,6 +27,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `amx-tf32`
 `amx-tile`
 `amx-transpose`
+`apxf`
 `atomics`
 `avx`
 `avx10.1`
diff --git a/tests/ui/feature-gates/bench.rs b/tests/ui/feature-gates/bench.rs
index 12e646f7a32..94c8992a8fe 100644
--- a/tests/ui/feature-gates/bench.rs
+++ b/tests/ui/feature-gates/bench.rs
@@ -1,9 +1,7 @@
 //@ edition:2018
 
 #[bench] //~ ERROR use of unstable library feature `test`
-         //~| WARN this was previously accepted
 fn bench() {}
 
 use bench as _; //~ ERROR use of unstable library feature `test`
-                //~| WARN this was previously accepted
 fn main() {}
diff --git a/tests/ui/feature-gates/bench.stderr b/tests/ui/feature-gates/bench.stderr
index de78e863012..f5fc579b23b 100644
--- a/tests/ui/feature-gates/bench.stderr
+++ b/tests/ui/feature-gates/bench.stderr
@@ -1,43 +1,23 @@
-error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
+error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
   --> $DIR/bench.rs:3:3
    |
 LL | #[bench]
    |   ^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
-   = note: `#[deny(soft_unstable)]` on by default
+   = note: see issue #50297 <https://github.com/rust-lang/rust/issues/50297> for more information
+   = help: add `#![feature(test)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/bench.rs:7:5
+error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
+  --> $DIR/bench.rs:6:5
    |
 LL | use bench as _;
    |     ^^^^^
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
+   = note: see issue #50297 <https://github.com/rust-lang/rust/issues/50297> for more information
+   = help: add `#![feature(test)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 2 previous errors
 
-Future incompatibility report: Future breakage diagnostic:
-error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/bench.rs:3:3
-   |
-LL | #[bench]
-   |   ^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
-   = note: `#[deny(soft_unstable)]` on by default
-
-Future breakage diagnostic:
-error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/bench.rs:7:5
-   |
-LL | use bench as _;
-   |     ^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
-   = note: `#[deny(soft_unstable)]` on by default
-
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-apx-target-feature.rs b/tests/ui/feature-gates/feature-gate-apx-target-feature.rs
new file mode 100644
index 00000000000..a2ac4ac86ac
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-apx-target-feature.rs
@@ -0,0 +1,6 @@
+//@ only-x86_64
+#[target_feature(enable = "apxf")]
+//~^ ERROR: currently unstable
+unsafe fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr b/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr
new file mode 100644
index 00000000000..1999ab53537
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-apx-target-feature.stderr
@@ -0,0 +1,13 @@
+error[E0658]: the target feature `apxf` is currently unstable
+  --> $DIR/feature-gate-apx-target-feature.rs:2:18
+   |
+LL | #[target_feature(enable = "apxf")]
+   |                  ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #139284 <https://github.com/rust-lang/rust/issues/139284> for more information
+   = help: add `#![feature(apx_target_feature)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/lint/expansion-time.rs b/tests/ui/lint/expansion-time.rs
index 3cb4b91ff2b..5ffb0c7881e 100644
--- a/tests/ui/lint/expansion-time.rs
+++ b/tests/ui/lint/expansion-time.rs
@@ -9,13 +9,6 @@ macro_rules! foo {
 macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier
                               //~| WARN this was previously accepted
 
-#[warn(soft_unstable)]
-mod benches {
-    #[bench] //~ WARN use of unstable library feature `test`
-             //~| WARN this was previously accepted
-    fn foo() {}
-}
-
 #[deprecated = "reason"]
 macro_rules! deprecated {
     () => {}
diff --git a/tests/ui/lint/expansion-time.stderr b/tests/ui/lint/expansion-time.stderr
index f65627c2c08..f24d1b68a8d 100644
--- a/tests/ui/lint/expansion-time.stderr
+++ b/tests/ui/lint/expansion-time.stderr
@@ -26,20 +26,6 @@ note: the lint level is defined here
 LL | #[warn(missing_fragment_specifier)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/expansion-time.rs:14:7
-   |
-LL |     #[bench]
-   |       ^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
-note: the lint level is defined here
-  --> $DIR/expansion-time.rs:12:8
-   |
-LL | #[warn(soft_unstable)]
-   |        ^^^^^^^^^^^^^
-
 warning: include macro expected single expression in source
   --> $DIR/expansion-time-include.rs:4:1
    |
@@ -47,12 +33,12 @@ LL | 2
    | ^
    |
 note: the lint level is defined here
-  --> $DIR/expansion-time.rs:29:8
+  --> $DIR/expansion-time.rs:22:8
    |
 LL | #[warn(incomplete_include)]
    |        ^^^^^^^^^^^^^^^^^^
 
-warning: 4 warnings emitted
+warning: 3 warnings emitted
 
 Future incompatibility report: Future breakage diagnostic:
 warning: missing fragment specifier
@@ -69,18 +55,3 @@ note: the lint level is defined here
 LL | #[warn(missing_fragment_specifier)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Future breakage diagnostic:
-warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
-  --> $DIR/expansion-time.rs:14:7
-   |
-LL |     #[bench]
-   |       ^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
-note: the lint level is defined here
-  --> $DIR/expansion-time.rs:12:8
-   |
-LL | #[warn(soft_unstable)]
-   |        ^^^^^^^^^^^^^
-
diff --git a/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs b/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs
new file mode 100644
index 00000000000..e0668ac3d39
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/duplicate-opaque-type-entries.rs
@@ -0,0 +1,25 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@ check-pass
+#![crate_type = "lib"]
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+trait ConstrainAndEq<T> {}
+impl<T, U> ConstrainAndEq<T> for U
+where
+    T: FnOnce() -> u32,
+    U: FnOnce() -> u32,
+    T: Eq<U>,
+{}
+
+fn constrain_and_eq<T: ConstrainAndEq<U>, U>(_: T, _: U) {}
+fn foo<'a>() -> impl Sized + use<'a> {
+    // This proves `foo<'a>: FnOnce() -> u32` and `foo<'1>: FnOnce() -> u32`,
+    // We constrain both `opaque<'a>` and `opaque<'1>` to `u32`, resulting in
+    // two distinct opaque type uses. Proving `foo<'a>: Eq<foo<'1>>` then
+    // equates the two regions at which point the two opaque type keys are now
+    // equal. This previously caused an ICE.
+    constrain_and_eq(foo::<'a>, foo::<'_>);
+    1u32
+}