about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <476013+matthiaskrgr@users.noreply.github.com>2025-07-18 14:49:19 +0200
committerGitHub <noreply@github.com>2025-07-18 14:49:19 +0200
commit82fbbddf633f104cbfac6f388fa96e0b94971ad9 (patch)
treed6c9a97f6a782036fef0c569f20e7eaafcb4d5ee
parent744ca5959a665e23e7e7b30ecf81d17c22223cc2 (diff)
parent68b415a0c4cfa054f275424db770d08227c09099 (diff)
downloadrust-82fbbddf633f104cbfac6f388fa96e0b94971ad9.tar.gz
rust-82fbbddf633f104cbfac6f388fa96e0b94971ad9.zip
Rollup merge of #143925 - oli-obk:slice-const-partialeq, r=fee1-dead
Make slice comparisons const

This needed a fix for `derive_const`, too, as it wasn't usable in libcore anymore as trait impls need const stability attributes. I think we can't use the same system as normal trait impls while `const_trait_impl` is still unstable.

r? ```@fee1-dead```

cc rust-lang/rust#143800
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs47
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs1
-rw-r--r--compiler/rustc_expand/src/build.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--library/core/src/cmp.rs3
-rw-r--r--library/core/src/cmp/bytewise.rs8
-rw-r--r--library/core/src/intrinsics/mod.rs1
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/macros/mod.rs2
-rw-r--r--library/core/src/num/nonzero.rs5
-rw-r--r--library/core/src/option.rs3
-rw-r--r--library/core/src/prelude/v1.rs2
-rw-r--r--library/core/src/slice/cmp.rs22
-rw-r--r--library/core/src/str/traits.rs3
-rw-r--r--library/std/src/prelude/v1.rs2
-rw-r--r--tests/ui/consts/const-compare-bytes-ub.rs2
-rw-r--r--tests/ui/consts/const-compare-bytes.rs2
-rw-r--r--tests/ui/consts/const-eval/auxiliary/stability.rs9
-rw-r--r--tests/ui/traits/const-traits/const-impl-trait.rs2
-rw-r--r--tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr1
-rw-r--r--tests/ui/traits/const-traits/match-non-const-eq.gated.stderr12
-rw-r--r--tests/ui/traits/const-traits/match-non-const-eq.rs9
-rw-r--r--tests/ui/traits/const-traits/match-non-const-eq.stock.stderr22
31 files changed, 134 insertions, 49 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index a98e9c6d1c7..dd8f0e46a0e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -23,6 +23,7 @@ pub(crate) fn expand_deriving_copy(
         methods: Vec::new(),
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand(cx, mitem, item, push);
@@ -46,6 +47,7 @@ pub(crate) fn expand_deriving_const_param_ty(
         methods: Vec::new(),
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand(cx, mitem, item, push);
@@ -60,6 +62,7 @@ pub(crate) fn expand_deriving_const_param_ty(
         methods: Vec::new(),
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand(cx, mitem, item, push);
@@ -83,6 +86,7 @@ pub(crate) fn expand_deriving_unsized_const_param_ty(
         methods: Vec::new(),
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 69f8c273797..3c78f53c5cb 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -87,6 +87,7 @@ pub(crate) fn expand_deriving_clone(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand_ext(cx, mitem, item, push, is_simple)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index eca79e4dc48..29d531219a6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -43,6 +43,7 @@ pub(crate) fn expand_deriving_eq(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     trait_def.expand_ext(cx, mitem, item, push, true)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 1ed44c20bc6..0e1ecf3118a 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -34,6 +34,7 @@ pub(crate) fn expand_deriving_ord(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     trait_def.expand(cx, mitem, item, push)
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index b1d950b8d89..990835fa277 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -30,6 +30,7 @@ pub(crate) fn expand_deriving_partial_eq(
         methods: Vec::new(),
         associated_types: Vec::new(),
         is_const: false,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     structural_trait_def.expand(cx, mitem, item, push);
 
@@ -58,6 +59,7 @@ pub(crate) fn expand_deriving_partial_eq(
         methods,
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 0a076dd670b..f5d262ece36 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -64,6 +64,7 @@ pub(crate) fn expand_deriving_partial_ord(
         methods: vec![partial_cmp_def],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 8ab21986e68..1d63ce7d5fd 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_debug(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 1fe567e23f4..b4e2d27fed3 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -51,6 +51,7 @@ pub(crate) fn expand_deriving_default(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
     trait_def.expand(cx, mitem, item, push)
 }
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index c55a9e73e38..b24e5563761 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -181,9 +181,11 @@ use std::{iter, vec};
 pub(crate) use StaticFields::*;
 pub(crate) use SubstructureFields::*;
 use rustc_ast::ptr::P;
+use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind};
+use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree};
 use rustc_ast::{
-    self as ast, AnonConst, BindingMode, ByRef, EnumDef, Expr, GenericArg, GenericParamKind,
-    Generics, Mutability, PatKind, VariantData,
+    self as ast, AnonConst, AttrArgs, BindingMode, ByRef, DelimArgs, EnumDef, Expr, GenericArg,
+    GenericParamKind, Generics, Mutability, PatKind, Safety, VariantData,
 };
 use rustc_attr_data_structures::{AttributeKind, ReprPacked};
 use rustc_attr_parsing::AttributeParser;
@@ -222,6 +224,8 @@ pub(crate) struct TraitDef<'a> {
     pub associated_types: Vec<(Ident, Ty)>,
 
     pub is_const: bool,
+
+    pub is_staged_api_crate: bool,
 }
 
 pub(crate) struct MethodDef<'a> {
@@ -784,8 +788,45 @@ impl<'a> TraitDef<'a> {
         // Create the type of `self`.
         let path = cx.path_all(self.span, false, vec![type_ident], self_params);
         let self_type = cx.ty_path(path);
+        let rustc_const_unstable =
+            cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span));
+
+        let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
+
+        // Only add `rustc_const_unstable` attributes if `derive_const` is used within libcore/libstd,
+        // Other crates don't need stability attributes, so adding them is not useful, but libcore needs them
+        // on all const trait impls.
+        if self.is_const && self.is_staged_api_crate {
+            attrs.push(
+                cx.attr_nested(
+                    rustc_ast::AttrItem {
+                        unsafety: Safety::Default,
+                        path: rustc_const_unstable,
+                        args: AttrArgs::Delimited(DelimArgs {
+                            dspan: DelimSpan::from_single(self.span),
+                            delim: rustc_ast::token::Delimiter::Parenthesis,
+                            tokens: [
+                                TokenKind::Ident(sym::feature, IdentIsRaw::No),
+                                TokenKind::Eq,
+                                TokenKind::lit(LitKind::Str, sym::derive_const, None),
+                                TokenKind::Comma,
+                                TokenKind::Ident(sym::issue, IdentIsRaw::No),
+                                TokenKind::Eq,
+                                TokenKind::lit(LitKind::Str, sym::derive_const_issue, None),
+                            ]
+                            .into_iter()
+                            .map(|kind| {
+                                TokenTree::Token(Token { kind, span: self.span }, Spacing::Alone)
+                            })
+                            .collect(),
+                        }),
+                        tokens: None,
+                    },
+                    self.span,
+                ),
+            )
+        }
 
-        let attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),];
         let opt_trait_ref = Some(trait_ref);
 
         cx.item(
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 6e6dbe19e4d..78534449895 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -41,6 +41,7 @@ pub(crate) fn expand_deriving_hash(
         }],
         associated_types: Vec::new(),
         is_const,
+        is_staged_api_crate: cx.ecfg.features.staged_api(),
     };
 
     hash_trait_def.expand(cx, mitem, item, push);
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 85683c1a03f..51d6e43ab67 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -3,8 +3,8 @@ use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::util::literal;
 use rustc_ast::{
-    self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
-    attr, token, tokenstream,
+    self as ast, AnonConst, AttrItem, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind,
+    UnOp, attr, token, tokenstream,
 };
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -766,4 +766,10 @@ impl<'a> ExtCtxt<'a> {
             span,
         )
     }
+
+    // Builds an attribute fully manually.
+    pub fn attr_nested(&self, inner: AttrItem, span: Span) -> ast::Attribute {
+        let g = &self.sess.psess.attr_id_generator;
+        attr::mk_attr_from_item(g, inner, None, ast::AttrStyle::Outer, span)
+    }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7147f37efc1..d28a73bc139 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -840,6 +840,7 @@ symbols! {
         derive,
         derive_coerce_pointee,
         derive_const,
+        derive_const_issue: "118304",
         derive_default_enum,
         derive_smart_pointer,
         destruct,
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 03b120fbf0c..6419ae99113 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -381,7 +381,8 @@ pub struct AssertParamIsEq<T: Eq + PointeeSized> {
 ///
 /// assert_eq!(2.cmp(&1), Ordering::Greater);
 /// ```
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+#[derive(Clone, Copy, Eq, PartialOrd, Ord, Debug, Hash)]
+#[derive_const(PartialEq)]
 #[stable(feature = "rust1", since = "1.0.0")]
 // This is a lang item only so that `BinOp::Cmp` in MIR can return it.
 // It has no special behavior, but does require that the three variants
diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs
index a06a5227fe2..7d61c9345ec 100644
--- a/library/core/src/cmp/bytewise.rs
+++ b/library/core/src/cmp/bytewise.rs
@@ -17,11 +17,15 @@ use crate::num::NonZero;
 /// - Neither `Self` nor `Rhs` have provenance, so integer comparisons are correct.
 /// - `<Self as PartialEq<Rhs>>::{eq,ne}` are equivalent to comparing the bytes.
 #[rustc_specialization_trait]
-pub(crate) unsafe trait BytewiseEq<Rhs = Self>: PartialEq<Rhs> + Sized {}
+#[const_trait]
+pub(crate) unsafe trait BytewiseEq<Rhs = Self>:
+    ~const PartialEq<Rhs> + Sized
+{
+}
 
 macro_rules! is_bytewise_comparable {
     ($($t:ty),+ $(,)?) => {$(
-        unsafe impl BytewiseEq for $t {}
+        unsafe impl const BytewiseEq for $t {}
     )+};
 }
 
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index fa27acac217..f90e6851d1f 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -2208,6 +2208,7 @@ pub const unsafe fn raw_eq<T>(a: &T, b: &T) -> bool;
 /// [valid]: crate::ptr#safety
 #[rustc_nounwind]
 #[rustc_intrinsic]
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
 pub const unsafe fn compare_bytes(left: *const u8, right: *const u8, bytes: usize) -> i32;
 
 /// See documentation of [`std::hint::black_box`] for details.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index e08edde3b38..729de5ffc8f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -103,6 +103,7 @@
 #![feature(cfg_select)]
 #![feature(cfg_target_has_reliable_f16_f128)]
 #![feature(const_carrying_mul_add)]
+#![feature(const_cmp)]
 #![feature(const_destruct)]
 #![feature(const_eval_select)]
 #![feature(core_intrinsics)]
@@ -146,6 +147,7 @@
 #![feature(const_trait_impl)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
+#![feature(derive_const)]
 #![feature(doc_cfg)]
 #![feature(doc_cfg_hide)]
 #![feature(doc_notable_trait)]
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 1b6dbc2f428..8ac6ce2242d 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1615,7 +1615,7 @@ pub(crate) mod builtin {
     /// See [the reference] for more info.
     ///
     /// [the reference]: ../../../reference/attributes/derive.html
-    #[unstable(feature = "derive_const", issue = "none")]
+    #[unstable(feature = "derive_const", issue = "118304")]
     #[rustc_builtin_macro]
     pub macro derive_const($item:item) {
         /* compiler built-in */
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 11d50e0f89f..b8900c4113a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -200,9 +200,10 @@ impl<T> UseCloned for NonZero<T> where T: ZeroablePrimitive {}
 impl<T> Copy for NonZero<T> where T: ZeroablePrimitive {}
 
 #[stable(feature = "nonzero", since = "1.28.0")]
-impl<T> PartialEq for NonZero<T>
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl<T> const PartialEq for NonZero<T>
 where
-    T: ZeroablePrimitive + PartialEq,
+    T: ZeroablePrimitive + ~const PartialEq,
 {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 7633429fc5c..8036c59e893 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -2300,7 +2300,8 @@ impl<'a, T> From<&'a mut Option<T>> for Option<&'a mut T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> crate::marker::StructuralPartialEq for Option<T> {}
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: PartialEq> PartialEq for Option<T> {
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl<T: ~const PartialEq> const PartialEq for Option<T> {
     #[inline]
     fn eq(&self, other: &Self) -> bool {
         // Spelling out the cases explicitly optimizes better than
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 7b9e04920d5..a4be66b90ca 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -80,7 +80,7 @@ pub use crate::macros::builtin::{
     alloc_error_handler, bench, derive, global_allocator, test, test_case,
 };
 
-#[unstable(feature = "derive_const", issue = "none")]
+#[unstable(feature = "derive_const", issue = "118304")]
 pub use crate::macros::builtin::derive_const;
 
 #[unstable(
diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs
index 5ce72b46eee..1eda8bc1bec 100644
--- a/library/core/src/slice/cmp.rs
+++ b/library/core/src/slice/cmp.rs
@@ -8,9 +8,10 @@ use crate::num::NonZero;
 use crate::ops::ControlFlow;
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T, U> PartialEq<[U]> for [T]
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl<T, U> const PartialEq<[U]> for [T]
 where
-    T: PartialEq<U>,
+    T: ~const PartialEq<U>,
 {
     fn eq(&self, other: &[U]) -> bool {
         SlicePartialEq::equal(self, other)
@@ -94,6 +95,8 @@ impl<T: PartialOrd> PartialOrd for [T] {
 
 #[doc(hidden)]
 // intermediate trait for specialization of slice's PartialEq
+#[const_trait]
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
 trait SlicePartialEq<B> {
     fn equal(&self, other: &[B]) -> bool;
 
@@ -103,9 +106,10 @@ trait SlicePartialEq<B> {
 }
 
 // Generic slice equality
-impl<A, B> SlicePartialEq<B> for [A]
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl<A, B> const SlicePartialEq<B> for [A]
 where
-    A: PartialEq<B>,
+    A: ~const PartialEq<B>,
 {
     default fn equal(&self, other: &[B]) -> bool {
         if self.len() != other.len() {
@@ -115,11 +119,14 @@ where
         // Implemented as explicit indexing rather
         // than zipped iterators for performance reasons.
         // See PR https://github.com/rust-lang/rust/pull/116846
-        for idx in 0..self.len() {
+        // FIXME(const_hack): make this a `for idx in 0..self.len()` loop.
+        let mut idx = 0;
+        while idx < self.len() {
             // bound checks are optimized away
             if self[idx] != other[idx] {
                 return false;
             }
+            idx += 1;
         }
 
         true
@@ -128,9 +135,10 @@ where
 
 // When each element can be compared byte-wise, we can compare all the bytes
 // from the whole size in one call to the intrinsics.
-impl<A, B> SlicePartialEq<B> for [A]
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl<A, B> const SlicePartialEq<B> for [A]
 where
-    A: BytewiseEq<B>,
+    A: ~const BytewiseEq<B>,
 {
     fn equal(&self, other: &[B]) -> bool {
         if self.len() != other.len() {
diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs
index 42ffc591b5b..d0f2b9226bf 100644
--- a/library/core/src/str/traits.rs
+++ b/library/core/src/str/traits.rs
@@ -23,7 +23,8 @@ impl Ord for str {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl PartialEq for str {
+#[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
+impl const PartialEq for str {
     #[inline]
     fn eq(&self, other: &str) -> bool {
         self.as_bytes() == other.as_bytes()
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 69f03353153..70c11131556 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -67,7 +67,7 @@ pub use core::prelude::v1::{
     alloc_error_handler, bench, derive, global_allocator, test, test_case,
 };
 
-#[unstable(feature = "derive_const", issue = "none")]
+#[unstable(feature = "derive_const", issue = "118304")]
 pub use core::prelude::v1::derive_const;
 
 // Do not `doc(no_inline)` either.
diff --git a/tests/ui/consts/const-compare-bytes-ub.rs b/tests/ui/consts/const-compare-bytes-ub.rs
index 0bc8585a4ee..7e3df92a2bf 100644
--- a/tests/ui/consts/const-compare-bytes-ub.rs
+++ b/tests/ui/consts/const-compare-bytes-ub.rs
@@ -1,6 +1,6 @@
 //@ check-fail
 
-#![feature(core_intrinsics)]
+#![feature(core_intrinsics, const_cmp)]
 use std::intrinsics::compare_bytes;
 use std::mem::MaybeUninit;
 
diff --git a/tests/ui/consts/const-compare-bytes.rs b/tests/ui/consts/const-compare-bytes.rs
index cd5cdfd0400..9563375555c 100644
--- a/tests/ui/consts/const-compare-bytes.rs
+++ b/tests/ui/consts/const-compare-bytes.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-#![feature(core_intrinsics)]
+#![feature(core_intrinsics, const_cmp)]
 use std::intrinsics::compare_bytes;
 
 fn main() {
diff --git a/tests/ui/consts/const-eval/auxiliary/stability.rs b/tests/ui/consts/const-eval/auxiliary/stability.rs
index e6159551860..48ced3bc51e 100644
--- a/tests/ui/consts/const-eval/auxiliary/stability.rs
+++ b/tests/ui/consts/const-eval/auxiliary/stability.rs
@@ -1,10 +1,11 @@
 // Crate that exports a const fn. Used for testing cross-crate.
 
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 #![stable(feature = "rust1", since = "1.0.0")]
-
 #![feature(staged_api)]
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[rustc_const_unstable(feature="foo", issue = "none")]
-pub const fn foo() -> u32 { 42 }
+#[rustc_const_unstable(feature = "foo", issue = "none")]
+pub const fn foo() -> u32 {
+    42
+}
diff --git a/tests/ui/traits/const-traits/const-impl-trait.rs b/tests/ui/traits/const-traits/const-impl-trait.rs
index dc960422a4a..da28d9a47c3 100644
--- a/tests/ui/traits/const-traits/const-impl-trait.rs
+++ b/tests/ui/traits/const-traits/const-impl-trait.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: -Znext-solver
 //@ known-bug: #110395
 
-// Broken until we have `const PartialEq` impl in stdlib
+// Broken until `(): const PartialEq`
 
 #![allow(incomplete_features)]
 #![feature(const_trait_impl, const_cmp, const_destruct)]
diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
index 5ed12b37052..cbc62d602a4 100644
--- a/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
+++ b/tests/ui/traits/const-traits/const_derives/derive-const-gate.stderr
@@ -4,6 +4,7 @@ error[E0658]: use of unstable library feature `derive_const`
 LL | #[derive_const(Debug)]
    |   ^^^^^^^^^^^^
    |
+   = note: see issue #118304 <https://github.com/rust-lang/rust/issues/118304> for more information
    = help: add `#![feature(derive_const)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
diff --git a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr b/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr
deleted file mode 100644
index 89e59e5db6e..00000000000
--- a/tests/ui/traits/const-traits/match-non-const-eq.gated.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0015]: cannot match on `str` in constant functions
-  --> $DIR/match-non-const-eq.rs:7:9
-   |
-LL |         "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
-   |         ^^^
-   |
-   = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/traits/const-traits/match-non-const-eq.rs b/tests/ui/traits/const-traits/match-non-const-eq.rs
index 73f8af86bd0..03adb8dc5a4 100644
--- a/tests/ui/traits/const-traits/match-non-const-eq.rs
+++ b/tests/ui/traits/const-traits/match-non-const-eq.rs
@@ -1,11 +1,12 @@
-//@ known-bug: #110395
 //@ revisions: stock gated
-#![cfg_attr(gated, feature(const_trait_impl))]
+#![cfg_attr(gated, feature(const_trait_impl, const_cmp))]
+//@[gated] check-pass
 
 const fn foo(input: &'static str) {
     match input {
-        "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
-        //FIXME ~^ ERROR cannot match on `str` in constant functions
+        "a" => (),
+        //[stock]~^ ERROR cannot match on `str` in constant functions
+        //[stock]~| ERROR `PartialEq` is not yet stable as a const trait
         _ => (),
     }
 }
diff --git a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr
index 89e59e5db6e..5b662447bde 100644
--- a/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr
+++ b/tests/ui/traits/const-traits/match-non-const-eq.stock.stderr
@@ -1,12 +1,26 @@
-error[E0015]: cannot match on `str` in constant functions
+error[E0658]: cannot match on `str` in constant functions
   --> $DIR/match-non-const-eq.rs:7:9
    |
-LL |         "a" => (), //FIXME [gated]~ ERROR can't compare `str` with `str` in const contexts
+LL |         "a" => (),
    |         ^^^
    |
    = note: `str` cannot be compared in compile-time, and therefore cannot be used in `match`es
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+   = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
+   = help: add `#![feature(const_trait_impl)]` 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
+error: `PartialEq` is not yet stable as a const trait
+  --> $DIR/match-non-const-eq.rs:7:9
+   |
+LL |         "a" => (),
+   |         ^^^
+   |
+help: add `#![feature(const_cmp)]` to the crate attributes to enable
+   |
+LL + #![feature(const_cmp)]
+   |
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0658`.