diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index a79909ce0c878..47db7ee369186 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -8,6 +8,7 @@
     rustc_attrs,
     transparent_unions,
     auto_traits,
+    freeze_impls,
     thread_local
 )]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 230009741dc41..1f364f78ece76 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -1,6 +1,6 @@
 #![feature(
     no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
-    decl_macro, rustc_attrs, transparent_unions, auto_traits,
+    decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
     thread_local
 )]
 #![no_core]
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 53254d567ccf2..db192ae9a3519 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -469,6 +469,8 @@ declare_features! (
     (unstable, fn_align, "1.53.0", Some(82232)),
     /// Support delegating implementation of functions to other already implemented functions.
     (incomplete, fn_delegation, "1.76.0", Some(118212)),
+    /// Allows impls for the Freeze trait.
+    (internal, freeze_impls, "CURRENT_RUSTC_VERSION", Some(121675)),
     /// Allows defining gen blocks and `gen fn`.
     (unstable, gen_blocks, "1.75.0", Some(117078)),
     /// Infer generic args for both consts and types.
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index d6281fa08f745..52acc10b9fe7f 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_session::parse::feature_err;
 use rustc_span::{sym, ErrorGuaranteed};
 use rustc_trait_selection::traits;
 
@@ -49,6 +50,19 @@ fn enforce_trait_manually_implementable(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_header_span = tcx.def_span(impl_def_id);
 
+    if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
+        if !tcx.features().freeze_impls {
+            feature_err(
+                &tcx.sess,
+                sym::freeze_impls,
+                impl_header_span,
+                "explicit impls for the `Freeze` trait are not permitted",
+            )
+            .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
+            .emit();
+        }
+    }
+
     // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
     if trait_def.deny_explicit_impl {
         let trait_name = tcx.item_name(trait_def_id);
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 4d8475bef54c8..f52f187973fa0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -841,6 +841,7 @@ symbols! {
         format_placeholder,
         format_unsafe_arg,
         freeze,
+        freeze_impls,
         freg,
         frem_algebraic,
         frem_fast,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 7b735d48bdfce..6ea7fda15389d 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -203,6 +203,7 @@
 // Language features:
 // tidy-alphabetical-start
 #![cfg_attr(bootstrap, feature(platform_intrinsics))]
+#![cfg_attr(not(bootstrap), feature(freeze_impls))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 2e22129d7b64d..a56a2578c2241 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -810,15 +810,21 @@ pub trait DiscriminantKind {
     type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
 }
 
-/// Compiler-internal trait used to determine whether a type contains
+/// Used to determine whether a type contains
 /// any `UnsafeCell` internally, but not through an indirection.
 /// This affects, for example, whether a `static` of that type is
 /// placed in read-only static memory or writable static memory.
+/// This can be used to declare that a constant with a generic type
+/// will not contain interior mutability, and subsequently allow
+/// placing the constant behind references.
 #[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
+#[unstable(feature = "freeze", issue = "121675")]
+pub unsafe auto trait Freeze {}
 
+#[unstable(feature = "freeze", issue = "121675")]
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
 marker_impls! {
+    #[unstable(feature = "freeze", issue = "121675")]
     unsafe Freeze for
         {T: ?Sized} PhantomData<T>,
         {T: ?Sized} *const T,
diff --git a/tests/run-make/min-global-align/min_global_align.rs b/tests/run-make/min-global-align/min_global_align.rs
index 135792e937205..cd1ef8cb351ff 100644
--- a/tests/run-make/min-global-align/min_global_align.rs
+++ b/tests/run-make/min-global-align/min_global_align.rs
@@ -1,4 +1,4 @@
-#![feature(no_core, lang_items)]
+#![feature(no_core, lang_items, freeze_impls)]
 #![crate_type = "rlib"]
 #![no_core]
 
diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
index 0663ed5fc81ff..7d9133b85a613 100644
--- a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
+++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
@@ -1,5 +1,5 @@
 // https://github.com/rust-lang/rust/issues/50159
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 pub trait Signal {
     type Item;
@@ -9,7 +9,10 @@ pub trait Signal2 {
     type Item2;
 }
 
-impl<B, C> Signal2 for B where B: Signal<Item = C> {
+impl<B, C> Signal2 for B
+where
+    B: Signal<Item = C>,
+{
     type Item2 = C;
 }
 
@@ -17,7 +20,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 // @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
 // @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
 pub struct Switch<B: Signal> {
     pub inner: <B as Signal2>::Item2,
 }
diff --git a/tests/rustdoc/empty-section.rs b/tests/rustdoc/empty-section.rs
index d8241ab96f6dd..0d6afb0e44447 100644
--- a/tests/rustdoc/empty-section.rs
+++ b/tests/rustdoc/empty-section.rs
@@ -1,6 +1,5 @@
 #![crate_name = "foo"]
-
-#![feature(negative_impls)]
+#![feature(negative_impls, freeze_impls, freeze)]
 
 pub struct Foo;
 
@@ -8,6 +7,7 @@ pub struct Foo;
 // @!hasraw - 'Auto Trait Implementations'
 impl !Send for Foo {}
 impl !Sync for Foo {}
+impl !std::marker::Freeze for Foo {}
 impl !std::marker::Unpin for Foo {}
 impl !std::panic::RefUnwindSafe for Foo {}
 impl !std::panic::UnwindSafe for Foo {}
diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs
index 043ac24148838..16b8cce490c84 100644
--- a/tests/rustdoc/synthetic_auto/basic.rs
+++ b/tests/rustdoc/synthetic_auto/basic.rs
@@ -2,7 +2,7 @@
 // @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
 // @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
 pub struct Foo<T> {
     field: T,
 }
diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs
index 7fc8447df3efc..692d68294a7ef 100644
--- a/tests/rustdoc/synthetic_auto/manual.rs
+++ b/tests/rustdoc/synthetic_auto/manual.rs
@@ -6,7 +6,7 @@
 // 'impl<T> Send for Foo<T>'
 //
 // @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
 pub struct Foo<T> {
     field: T,
 }
diff --git a/tests/ui/associated-consts/freeze.rs b/tests/ui/associated-consts/freeze.rs
new file mode 100644
index 0000000000000..2364ee1f4956f
--- /dev/null
+++ b/tests/ui/associated-consts/freeze.rs
@@ -0,0 +1,12 @@
+#![feature(freeze)]
+
+//@ check-pass
+
+use std::marker::Freeze;
+
+trait Trait<T: Freeze + 'static> {
+    const VALUE: T;
+    const VALUE_REF: &'static T = &Self::VALUE;
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.rs b/tests/ui/feature-gates/feature-gate-freeze-impls.rs
new file mode 100644
index 0000000000000..c14c9494874a2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-freeze-impls.rs
@@ -0,0 +1,15 @@
+#![feature(freeze, negative_impls)]
+
+use std::marker::Freeze;
+
+struct Foo;
+
+unsafe impl Freeze for Foo {}
+//~^ explicit impls for the `Freeze` trait are not permitted
+
+struct Bar;
+
+impl !Freeze for Bar {}
+//~^ explicit impls for the `Freeze` trait are not permitted
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.stderr b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr
new file mode 100644
index 0000000000000..eef524fe78e8b
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr
@@ -0,0 +1,23 @@
+error[E0658]: explicit impls for the `Freeze` trait are not permitted
+  --> $DIR/feature-gate-freeze-impls.rs:7:1
+   |
+LL | unsafe impl Freeze for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
+   |
+   = note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
+   = help: add `#![feature(freeze_impls)]` 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[E0658]: explicit impls for the `Freeze` trait are not permitted
+  --> $DIR/feature-gate-freeze-impls.rs:12:1
+   |
+LL | impl !Freeze for Bar {}
+   | ^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
+   |
+   = note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
+   = help: add `#![feature(freeze_impls)]` 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
+
+For more information about this error, try `rustc --explain E0658`.