about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2024-01-09 13:23:15 +0100
committerGitHub <noreply@github.com>2024-01-09 13:23:15 +0100
commit4a24b5bc054f78c165cbdf4dd3e0a7f56f468d7d (patch)
tree8c1fef00c6ab1567f6552704e4593932d04d6685
parentbe00c5a9b89161b7f45ba80340f709e8e41122f9 (diff)
parenta8aa6878f63e53a9b0cfee542e9765407e1ca0d6 (diff)
Rollup merge of #117556 - obeis:static-mut-ref-lint, r=davidtwco
Disallow reference to `static mut` and adding `static_mut_ref` lint

Closes #114447

r? `@scottmcm`
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs3
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs3
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0796.md22
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml1
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl14
-rw-r--r--compiler/rustc_hir_analysis/src/check/errs.rs97
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs91
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs52
-rw-r--r--library/panic_unwind/src/seh.rs4
-rw-r--r--library/std/src/panicking.rs2
-rw-r--r--library/std/src/sys/common/thread_local/fast_local.rs2
-rw-r--r--library/std/src/sys/common/thread_local/static_local.rs2
-rw-r--r--library/std/src/thread/local.rs2
-rw-r--r--src/tools/lint-docs/src/groups.rs1
-rw-r--r--src/tools/miri/tests/fail/tls/tls_static_dealloc.rs2
-rw-r--r--src/tools/miri/tests/pass/static_mut.rs3
-rw-r--r--src/tools/miri/tests/pass/tls/tls_static.rs2
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.rs2
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.stderr31
-rw-r--r--tests/ui/borrowck/borrowck-access-permissions.rs36
-rw-r--r--tests/ui/borrowck/borrowck-access-permissions.stderr33
-rw-r--r--tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs9
-rw-r--r--tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr17
-rw-r--r--tests/ui/borrowck/issue-20801.rs1
-rw-r--r--tests/ui/borrowck/issue-20801.stderr25
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs41
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr75
-rw-r--r--tests/ui/consts/const_let_assign2.rs1
-rw-r--r--tests/ui/consts/const_let_assign2.stderr17
-rw-r--r--tests/ui/consts/issue-17718-const-bad-values.rs3
-rw-r--r--tests/ui/consts/issue-17718-const-bad-values.stderr17
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr77
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr77
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs22
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref.rs1
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref.stderr17
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr23
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref2.rs10
-rw-r--r--tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr23
-rw-r--r--tests/ui/drop/issue-23338-ensure-param-drop-order.rs90
-rw-r--r--tests/ui/drop/issue-23338-ensure-param-drop-order.stderr17
-rw-r--r--tests/ui/error-codes/E0017.rs12
-rw-r--r--tests/ui/error-codes/E0017.stderr29
-rw-r--r--tests/ui/impl-header-lifetime-elision/bare_type.rs (renamed from tests/ui/issues/issue-20616.rs)9
-rw-r--r--tests/ui/issues/issue-23611-enum-swap-in-drop.rs44
-rw-r--r--tests/ui/issues/issue-23611-enum-swap-in-drop.stderr17
-rw-r--r--tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs5
-rw-r--r--tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr17
-rw-r--r--tests/ui/static/reference-of-mut-static-safe.e2021.stderr26
-rw-r--r--tests/ui/static/reference-of-mut-static-safe.e2024.stderr15
-rw-r--r--tests/ui/static/reference-of-mut-static-safe.rs13
-rw-r--r--tests/ui/static/reference-of-mut-static-unsafe-fn.rs23
-rw-r--r--tests/ui/static/reference-of-mut-static-unsafe-fn.stderr63
-rw-r--r--tests/ui/static/reference-of-mut-static.e2021.stderr91
-rw-r--r--tests/ui/static/reference-of-mut-static.e2024.stderr75
-rw-r--r--tests/ui/static/reference-of-mut-static.rs50
-rw-r--r--tests/ui/static/safe-extern-statics-mut.rs2
-rw-r--r--tests/ui/static/safe-extern-statics-mut.stderr35
-rw-r--r--tests/ui/statics/issue-15261.rs3
-rw-r--r--tests/ui/statics/issue-15261.stderr17
-rw-r--r--tests/ui/statics/static-mut-xc.rs3
-rw-r--r--tests/ui/statics/static-mut-xc.stderr31
-rw-r--r--tests/ui/statics/static-recursive.rs27
-rw-r--r--tests/ui/statics/static-recursive.stderr17
-rw-r--r--tests/ui/thread-local/thread-local-static.rs3
-rw-r--r--tests/ui/thread-local/thread-local-static.stderr17
-rw-r--r--tests/ui/thread-local/thread-local-static.thir.stderr59
71 files changed, 1445 insertions, 235 deletions
diff --git a/Cargo.lock b/Cargo.lock
index b43c39dd965..5b9dd05398f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3876,6 +3876,7 @@ dependencies = [
  "rustc_feature",
  "rustc_fluent_macro",
  "rustc_hir",
+ "rustc_hir_pretty",
  "rustc_index",
  "rustc_infer",
  "rustc_lint_defs",
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
index a1cdf31c68a..2a7b1107ffc 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs
@@ -111,6 +111,9 @@ fn start<T: Termination + 'static>(
 }
 
 static mut NUM: u8 = 6 * 7;
+
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[allow(static_mut_ref)]
 static NUM_REF: &'static u8 = unsafe { &NUM };
 
 unsafe fn zeroed<T>() -> T {
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index 40a1ad22c0e..9827e299f2a 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -98,6 +98,9 @@ fn start<T: Termination + 'static>(
 }
 
 static mut NUM: u8 = 6 * 7;
+
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[allow(static_mut_ref)]
 static NUM_REF: &'static u8 = unsafe { &NUM };
 
 macro_rules! assert {
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 1028d43f9c5..a1391cceb71 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -515,6 +515,7 @@ E0792: include_str!("./error_codes/E0792.md"),
 E0793: include_str!("./error_codes/E0793.md"),
 E0794: include_str!("./error_codes/E0794.md"),
 E0795: include_str!("./error_codes/E0795.md"),
+E0796: include_str!("./error_codes/E0796.md"),
 }
 
 // Undocumented removed error codes. Note that many removed error codes are kept in the list above
diff --git a/compiler/rustc_error_codes/src/error_codes/E0796.md b/compiler/rustc_error_codes/src/error_codes/E0796.md
new file mode 100644
index 00000000000..cea18f8db85
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0796.md
@@ -0,0 +1,22 @@
+Reference of mutable static.
+
+Erroneous code example:
+
+```compile_fail,edition2024,E0796
+static mut X: i32 = 23;
+static mut Y: i32 = 24;
+
+unsafe {
+  let y = &X;
+  let ref x = X;
+  let (x, y) = (&X, &Y);
+  foo(&X);
+}
+
+fn foo<'a>(_x: &'a i32) {}
+```
+
+Mutable statics can be written to by multiple threads: aliasing violations or
+data races will cause undefined behavior.
+
+Reference of mutable static is a hard error from 2024 edition.
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index b671bebeb05..b5ebc1fab76 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -17,6 +17,7 @@ rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
+rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
 rustc_infer = { path = "../rustc_infer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index d8b6b9a1272..6a17668ad17 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -346,6 +346,20 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha
 hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]`
     .label = `#[start]` function is not allowed to be `#[track_caller]`
 
+hir_analysis_static_mut_ref = reference of mutable static is disallowed
+    .label = reference of mutable static
+    .note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+    .suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+    .suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+
+hir_analysis_static_mut_ref_lint = {$shared}reference of mutable static is discouraged
+    .label = shared reference of mutable static
+    .label_mut = mutable reference of mutable static
+    .suggestion = shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+    .suggestion_mut = mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+    .note = reference of mutable static is a hard error from 2024 edition
+    .why_note = mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+
 hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
 hir_analysis_substs_on_overridden_impl = could not resolve substs on overridden impl
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
new file mode 100644
index 00000000000..27bb2c57a5c
--- /dev/null
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -0,0 +1,97 @@
+use rustc_hir as hir;
+use rustc_hir_pretty::qpath_to_string;
+use rustc_lint_defs::builtin::STATIC_MUT_REF;
+use rustc_middle::ty::TyCtxt;
+use rustc_span::Span;
+use rustc_type_ir::Mutability;
+
+use crate::errors;
+
+/// Check for shared or mutable references of `static mut` inside expression
+pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) {
+    let span = expr.span;
+    let hir_id = expr.hir_id;
+    if let hir::ExprKind::AddrOf(borrow_kind, m, expr) = expr.kind
+        && matches!(borrow_kind, hir::BorrowKind::Ref)
+        && let Some(var) = is_path_static_mut(*expr)
+    {
+        handle_static_mut_ref(
+            tcx,
+            span,
+            var,
+            span.edition().at_least_rust_2024(),
+            matches!(m, Mutability::Mut),
+            hir_id,
+        );
+    }
+}
+
+/// Check for shared or mutable references of `static mut` inside statement
+pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) {
+    if let hir::StmtKind::Local(loc) = stmt.kind
+        && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
+        && matches!(ba.0, rustc_ast::ByRef::Yes)
+        && let Some(init) = loc.init
+        && let Some(var) = is_path_static_mut(*init)
+    {
+        handle_static_mut_ref(
+            tcx,
+            init.span,
+            var,
+            loc.span.edition().at_least_rust_2024(),
+            matches!(ba.1, Mutability::Mut),
+            stmt.hir_id,
+        );
+    }
+}
+
+fn is_path_static_mut(expr: hir::Expr<'_>) -> Option<String> {
+    if let hir::ExprKind::Path(qpath) = expr.kind
+        && let hir::QPath::Resolved(_, path) = qpath
+        && let hir::def::Res::Def(def_kind, _) = path.res
+        && let hir::def::DefKind::Static(mt) = def_kind
+        && matches!(mt, Mutability::Mut)
+    {
+        return Some(qpath_to_string(&qpath));
+    }
+    None
+}
+
+fn handle_static_mut_ref(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    var: String,
+    e2024: bool,
+    mutable: bool,
+    hir_id: hir::HirId,
+) {
+    if e2024 {
+        let sugg = if mutable {
+            errors::StaticMutRefSugg::Mut { span, var }
+        } else {
+            errors::StaticMutRefSugg::Shared { span, var }
+        };
+        tcx.sess.parse_sess.dcx.emit_err(errors::StaticMutRef { span, sugg });
+        return;
+    }
+
+    let (label, sugg, shared) = if mutable {
+        (
+            errors::RefOfMutStaticLabel::Mut { span },
+            errors::RefOfMutStaticSugg::Mut { span, var },
+            "mutable ",
+        )
+    } else {
+        (
+            errors::RefOfMutStaticLabel::Shared { span },
+            errors::RefOfMutStaticSugg::Shared { span, var },
+            "shared ",
+        )
+    };
+    tcx.emit_spanned_lint(
+        STATIC_MUT_REF,
+        hir_id,
+        span,
+        errors::RefOfMutStatic { shared, why_note: (), label, sugg },
+    );
+}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index f60d6950670..ac0c715c6b3 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -66,6 +66,7 @@ mod check;
 mod compare_impl_item;
 pub mod dropck;
 mod entry;
+mod errs;
 pub mod intrinsic;
 pub mod intrinsicck;
 mod region;
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 542e69a6c34..5d5a4789734 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -18,6 +18,8 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::source_map;
 use rustc_span::Span;
 
+use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut};
+
 use std::mem;
 
 #[derive(Debug, Copy, Clone)]
@@ -224,6 +226,8 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
     let stmt_id = stmt.hir_id.local_id;
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
+    maybe_stmt_static_mut(visitor.tcx, *stmt);
+
     // Every statement will clean up the temporaries created during
     // execution of that statement. Therefore each statement has an
     // associated destruction scope that represents the scope of the
@@ -242,6 +246,8 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
 fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
     debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
 
+    maybe_expr_static_mut(visitor.tcx, *expr);
+
     let prev_cx = visitor.cx;
     visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
 
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 9124d502110..4f22da4ba3b 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1410,3 +1410,94 @@ pub struct OnlyCurrentTraitsPointerSugg<'a> {
     pub mut_key: &'a str,
     pub ptr_ty: Ty<'a>,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_static_mut_ref, code = "E0796")]
+#[note]
+pub struct StaticMutRef {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: StaticMutRefSugg,
+}
+
+#[derive(Subdiagnostic)]
+pub enum StaticMutRefSugg {
+    #[suggestion(
+        hir_analysis_suggestion,
+        style = "verbose",
+        code = "addr_of!({var})",
+        applicability = "maybe-incorrect"
+    )]
+    Shared {
+        #[primary_span]
+        span: Span,
+        var: String,
+    },
+    #[suggestion(
+        hir_analysis_suggestion_mut,
+        style = "verbose",
+        code = "addr_of_mut!({var})",
+        applicability = "maybe-incorrect"
+    )]
+    Mut {
+        #[primary_span]
+        span: Span,
+        var: String,
+    },
+}
+
+// STATIC_MUT_REF lint
+#[derive(LintDiagnostic)]
+#[diag(hir_analysis_static_mut_ref_lint)]
+#[note]
+pub struct RefOfMutStatic<'a> {
+    pub shared: &'a str,
+    #[note(hir_analysis_why_note)]
+    pub why_note: (),
+    #[subdiagnostic]
+    pub label: RefOfMutStaticLabel,
+    #[subdiagnostic]
+    pub sugg: RefOfMutStaticSugg,
+}
+
+#[derive(Subdiagnostic)]
+pub enum RefOfMutStaticLabel {
+    #[label(hir_analysis_label)]
+    Shared {
+        #[primary_span]
+        span: Span,
+    },
+    #[label(hir_analysis_label_mut)]
+    Mut {
+        #[primary_span]
+        span: Span,
+    },
+}
+
+#[derive(Subdiagnostic)]
+pub enum RefOfMutStaticSugg {
+    #[suggestion(
+        hir_analysis_suggestion,
+        style = "verbose",
+        code = "addr_of!({var})",
+        applicability = "maybe-incorrect"
+    )]
+    Shared {
+        #[primary_span]
+        span: Span,
+        var: String,
+    },
+    #[suggestion(
+        hir_analysis_suggestion_mut,
+        style = "verbose",
+        code = "addr_of_mut!({var})",
+        applicability = "maybe-incorrect"
+    )]
+    Mut {
+        #[primary_span]
+        span: Span,
+        var: String,
+    },
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index c74d4bb651c..e917e7cb02b 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -88,6 +88,7 @@ declare_lint_pass! {
         SINGLE_USE_LIFETIMES,
         SOFT_UNSTABLE,
         STABLE_FEATURES,
+        STATIC_MUT_REF,
         SUSPICIOUS_AUTO_TRAIT_IMPLS,
         TEST_UNSTABLE_LINT,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
@@ -1767,6 +1768,57 @@ declare_lint! {
 }
 
 declare_lint! {
+    /// The `static_mut_ref` lint checks for shared or mutable references
+    /// of mutable static inside `unsafe` blocks and `unsafe` functions.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,edition2021
+    /// fn main() {
+    ///     static mut X: i32 = 23;
+    ///     static mut Y: i32 = 24;
+    ///
+    ///     unsafe {
+    ///         let y = &X;
+    ///         let ref x = X;
+    ///         let (x, y) = (&X, &Y);
+    ///         foo(&X);
+    ///     }
+    /// }
+    ///
+    /// unsafe fn _foo() {
+    ///     static mut X: i32 = 23;
+    ///     static mut Y: i32 = 24;
+    ///
+    ///     let y = &X;
+    ///     let ref x = X;
+    ///     let (x, y) = (&X, &Y);
+    ///     foo(&X);
+    /// }
+    ///
+    /// fn foo<'a>(_x: &'a i32) {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Shared or mutable references of mutable static are almost always a mistake and
+    /// can lead to undefined behavior and various other problems in your code.
+    ///
+    /// This lint is "warn" by default on editions up to 2021, from 2024 there is
+    /// a hard error instead.
+    pub STATIC_MUT_REF,
+    Warn,
+    "shared references or mutable references of mutable static is discouraged",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #114447 <https://github.com/rust-lang/rust/issues/114447>",
+        explain_reason: false,
+    };
+}
+
+declare_lint! {
     /// The `absolute_paths_not_starting_with_crate` lint detects fully
     /// qualified paths that start with a module name instead of `crate`,
     /// `self`, or an extern crate name
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 99db00e5490..ccae406cc28 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -261,6 +261,8 @@ cfg_if::cfg_if! {
    }
 }
 
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_ref))]
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     use core::intrinsics::atomic_store_seqcst;
 
@@ -322,6 +324,8 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     _CxxThrowException(throw_ptr, &mut THROW_INFO as *mut _ as *mut _);
 }
 
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_ref))]
 pub unsafe fn cleanup(payload: *mut u8) -> Box<dyn Any + Send> {
     // A null payload here means that we got here from the catch (...) of
     // __rust_try. This happens when a non-Rust foreign exception is caught.
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 66b4ec37c8e..c80f15d8a61 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -337,6 +337,8 @@ pub mod panic_count {
 #[doc(hidden)]
 #[cfg(not(feature = "panic_immediate_abort"))]
 #[unstable(feature = "update_panic_count", issue = "none")]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_ref))]
 pub mod panic_count {
     use crate::cell::Cell;
     use crate::sync::atomic::{AtomicUsize, Ordering};
diff --git a/library/std/src/sys/common/thread_local/fast_local.rs b/library/std/src/sys/common/thread_local/fast_local.rs
index c0a9619bf7b..9206588be06 100644
--- a/library/std/src/sys/common/thread_local/fast_local.rs
+++ b/library/std/src/sys/common/thread_local/fast_local.rs
@@ -13,6 +13,8 @@ pub macro thread_local_inner {
     (@key $t:ty, const $init:expr) => {{
         #[inline]
         #[deny(unsafe_op_in_unsafe_fn)]
+        // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+        #[cfg_attr(not(bootstrap), allow(static_mut_ref))]
         unsafe fn __getit(
             _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
         ) -> $crate::option::Option<&'static $t> {
diff --git a/library/std/src/sys/common/thread_local/static_local.rs b/library/std/src/sys/common/thread_local/static_local.rs
index 5cb6c541a0e..51cba66fad7 100644
--- a/library/std/src/sys/common/thread_local/static_local.rs
+++ b/library/std/src/sys/common/thread_local/static_local.rs
@@ -11,6 +11,8 @@ pub macro thread_local_inner {
     (@key $t:ty, const $init:expr) => {{
         #[inline] // see comments below
         #[deny(unsafe_op_in_unsafe_fn)]
+        // FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+        #[cfg_attr(not(bootstrap), allow(static_mut_ref))]
         unsafe fn __getit(
             _init: $crate::option::Option<&mut $crate::option::Option<$t>>,
         ) -> $crate::option::Option<&'static $t> {
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 9cf37b0e634..338567777f7 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -180,6 +180,8 @@ impl<T: 'static> fmt::Debug for LocalKey<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "thread_local_macro")]
 #[allow_internal_unstable(thread_local_internals)]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_ref))]
 macro_rules! thread_local {
     // empty (base case for the recursion)
     () => {};
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index 5be8ef7996b..c5cd30ccc34 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -15,6 +15,7 @@ static GROUP_DESCRIPTIONS: &[(&str, &str)] = &[
     ("future-incompatible", "Lints that detect code that has future-compatibility problems"),
     ("rust-2018-compatibility", "Lints used to transition code from the 2015 edition to 2018"),
     ("rust-2021-compatibility", "Lints used to transition code from the 2018 edition to 2021"),
+    ("rust-2024-compatibility", "Lints used to transition code from the 2021 edition to 2024"),
 ];
 
 type LintGroups = BTreeMap<String, BTreeSet<String>>;
diff --git a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
index d5e6d37226a..762a8d85314 100644
--- a/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
+++ b/src/tools/miri/tests/fail/tls/tls_static_dealloc.rs
@@ -1,6 +1,8 @@
 //! Ensure that thread-local statics get deallocated when the thread dies.
 
 #![feature(thread_local)]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#![allow(static_mut_ref)]
 
 #[thread_local]
 static mut TLS: u8 = 0;
diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs
index 218b02525bd..c1e58b70adb 100644
--- a/src/tools/miri/tests/pass/static_mut.rs
+++ b/src/tools/miri/tests/pass/static_mut.rs
@@ -1,4 +1,7 @@
 static mut FOO: i32 = 42;
+
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#[allow(static_mut_ref)]
 static BAR: Foo = Foo(unsafe { &FOO as *const _ });
 
 #[allow(dead_code)]
diff --git a/src/tools/miri/tests/pass/tls/tls_static.rs b/src/tools/miri/tests/pass/tls/tls_static.rs
index fc4c8a283dd..9be00af47aa 100644
--- a/src/tools/miri/tests/pass/tls/tls_static.rs
+++ b/src/tools/miri/tests/pass/tls/tls_static.rs
@@ -8,6 +8,8 @@
 //! test, we also check that thread-locals act as per-thread statics.
 
 #![feature(thread_local)]
+// FIXME: Use `SyncUnsafeCell` instead of allowing `static_mut_ref` lint
+#![allow(static_mut_ref)]
 
 use std::thread;
 
diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs
index ecd8ee94a01..eb732e7c2c3 100644
--- a/tests/ui/abi/statics/static-mut-foreign.rs
+++ b/tests/ui/abi/statics/static-mut-foreign.rs
@@ -33,7 +33,9 @@ unsafe fn run() {
     rust_dbg_static_mut = -3;
     assert_eq!(rust_dbg_static_mut, -3);
     static_bound(&rust_dbg_static_mut);
+    //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
     static_bound_set(&mut rust_dbg_static_mut);
+    //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 }
 
 pub fn main() {
diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr
new file mode 100644
index 00000000000..144ac056f87
--- /dev/null
+++ b/tests/ui/abi/statics/static-mut-foreign.stderr
@@ -0,0 +1,31 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/static-mut-foreign.rs:35:18
+   |
+LL |     static_bound(&rust_dbg_static_mut);
+   |                  ^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     static_bound(addr_of!(rust_dbg_static_mut));
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/static-mut-foreign.rs:37:22
+   |
+LL |     static_bound_set(&mut rust_dbg_static_mut);
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     static_bound_set(addr_of_mut!(rust_dbg_static_mut));
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/borrowck/borrowck-access-permissions.rs b/tests/ui/borrowck/borrowck-access-permissions.rs
index 469ad508b0e..1638644103b 100644
--- a/tests/ui/borrowck/borrowck-access-permissions.rs
+++ b/tests/ui/borrowck/borrowck-access-permissions.rs
@@ -1,21 +1,27 @@
-static static_x : i32 = 1;
-static mut static_x_mut : i32 = 1;
+static static_x: i32 = 1;
+static mut static_x_mut: i32 = 1;
 
 fn main() {
     let x = 1;
     let mut x_mut = 1;
 
-    { // borrow of local
+    {
+        // borrow of local
         let _y1 = &mut x; //~ ERROR [E0596]
         let _y2 = &mut x_mut; // No error
     }
 
-    { // borrow of static
+    {
+        // borrow of static
         let _y1 = &mut static_x; //~ ERROR [E0596]
-        unsafe { let _y2 = &mut static_x_mut; } // No error
+        unsafe {
+            let _y2 = &mut static_x_mut;
+            //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+        }
     }
 
-    { // borrow of deref to box
+    {
+        // borrow of deref to box
         let box_x = Box::new(1);
         let mut box_x_mut = Box::new(1);
 
@@ -23,7 +29,8 @@ fn main() {
         let _y2 = &mut *box_x_mut; // No error
     }
 
-    { // borrow of deref to reference
+    {
+        // borrow of deref to reference
         let ref_x = &x;
         let ref_x_mut = &mut x_mut;
 
@@ -31,9 +38,10 @@ fn main() {
         let _y2 = &mut *ref_x_mut; // No error
     }
 
-    { // borrow of deref to pointer
-        let ptr_x : *const _ = &x;
-        let ptr_mut_x : *mut _ = &mut x_mut;
+    {
+        // borrow of deref to pointer
+        let ptr_x: *const _ = &x;
+        let ptr_mut_x: *mut _ = &mut x_mut;
 
         unsafe {
             let _y1 = &mut *ptr_x; //~ ERROR [E0596]
@@ -41,8 +49,12 @@ fn main() {
         }
     }
 
-    { // borrowing mutably through an immutable reference
-        struct Foo<'a> { f: &'a mut i32, g: &'a i32 };
+    {
+        // borrowing mutably through an immutable reference
+        struct Foo<'a> {
+            f: &'a mut i32,
+            g: &'a i32,
+        };
         let mut foo = Foo { f: &mut x_mut, g: &x };
         let foo_ref = &foo;
         let _y = &mut *foo_ref.f; //~ ERROR [E0596]
diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr
index c161e2d95b4..93d92295dd9 100644
--- a/tests/ui/borrowck/borrowck-access-permissions.stderr
+++ b/tests/ui/borrowck/borrowck-access-permissions.stderr
@@ -1,5 +1,20 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/borrowck-access-permissions.rs:18:23
+   |
+LL |             let _y2 = &mut static_x_mut;
+   |                       ^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |             let _y2 = addr_of_mut!(static_x_mut);
+   |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/borrowck-access-permissions.rs:9:19
+  --> $DIR/borrowck-access-permissions.rs:10:19
    |
 LL |         let _y1 = &mut x;
    |                   ^^^^^^ cannot borrow as mutable
@@ -10,13 +25,13 @@ LL |     let mut x = 1;
    |         +++
 
 error[E0596]: cannot borrow immutable static item `static_x` as mutable
-  --> $DIR/borrowck-access-permissions.rs:14:19
+  --> $DIR/borrowck-access-permissions.rs:16:19
    |
 LL |         let _y1 = &mut static_x;
    |                   ^^^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
-  --> $DIR/borrowck-access-permissions.rs:22:19
+  --> $DIR/borrowck-access-permissions.rs:28:19
    |
 LL |         let _y1 = &mut *box_x;
    |                   ^^^^^^^^^^^ cannot borrow as mutable
@@ -27,7 +42,7 @@ LL |         let mut box_x = Box::new(1);
    |             +++
 
 error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
-  --> $DIR/borrowck-access-permissions.rs:30:19
+  --> $DIR/borrowck-access-permissions.rs:37:19
    |
 LL |         let _y1 = &mut *ref_x;
    |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -38,18 +53,18 @@ LL |         let ref_x = &mut x;
    |                      +++
 
 error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
-  --> $DIR/borrowck-access-permissions.rs:39:23
+  --> $DIR/borrowck-access-permissions.rs:47:23
    |
 LL |             let _y1 = &mut *ptr_x;
    |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
    |
 help: consider changing this to be a mutable pointer
    |
-LL |         let ptr_x : *const _ = &mut x;
-   |                                 +++
+LL |         let ptr_x: *const _ = &mut x;
+   |                                +++
 
 error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
-  --> $DIR/borrowck-access-permissions.rs:48:18
+  --> $DIR/borrowck-access-permissions.rs:60:18
    |
 LL |         let _y = &mut *foo_ref.f;
    |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -59,6 +74,6 @@ help: consider changing this to be a mutable reference
 LL |         let foo_ref = &mut foo;
    |                        +++
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs
index adc7dfd541f..1bf079e24ca 100644
--- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs
+++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.rs
@@ -2,17 +2,22 @@
 
 // Test file taken from issue 45129 (https://github.com/rust-lang/rust/issues/45129)
 
-struct Foo { x: [usize; 2] }
+struct Foo {
+    x: [usize; 2],
+}
 
 static mut SFOO: Foo = Foo { x: [23, 32] };
 
 impl Foo {
-    fn x(&mut self) -> &mut usize { &mut self.x[0] }
+    fn x(&mut self) -> &mut usize {
+        &mut self.x[0]
+    }
 }
 
 fn main() {
     unsafe {
         let sfoo: *mut Foo = &mut SFOO;
+        //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
         let x = (*sfoo).x();
         (*sfoo).x[1] += 1;
         *x += 1;
diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
new file mode 100644
index 00000000000..7a3824f79a4
--- /dev/null
+++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
@@ -0,0 +1,17 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/borrowck-unsafe-static-mutable-borrows.rs:19:30
+   |
+LL |         let sfoo: *mut Foo = &mut SFOO;
+   |                              ^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         let sfoo: *mut Foo = addr_of_mut!(SFOO);
+   |                              ~~~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/borrowck/issue-20801.rs b/tests/ui/borrowck/issue-20801.rs
index c3f136f2876..ec83af5d5df 100644
--- a/tests/ui/borrowck/issue-20801.rs
+++ b/tests/ui/borrowck/issue-20801.rs
@@ -12,6 +12,7 @@ fn imm_ref() -> &'static T {
 
 fn mut_ref() -> &'static mut T {
     unsafe { &mut GLOBAL_MUT_T }
+    //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 }
 
 fn mut_ptr() -> *mut T {
diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr
index 215bf010063..b2bee2d8803 100644
--- a/tests/ui/borrowck/issue-20801.stderr
+++ b/tests/ui/borrowck/issue-20801.stderr
@@ -1,5 +1,20 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/issue-20801.rs:14:14
+   |
+LL |     unsafe { &mut GLOBAL_MUT_T }
+   |              ^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     unsafe { addr_of_mut!(GLOBAL_MUT_T) }
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/issue-20801.rs:26:22
+  --> $DIR/issue-20801.rs:27:22
    |
 LL |     let a = unsafe { *mut_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -11,7 +26,7 @@ LL +     let a = unsafe { mut_ref() };
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-20801.rs:29:22
+  --> $DIR/issue-20801.rs:30:22
    |
 LL |     let b = unsafe { *imm_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -23,7 +38,7 @@ LL +     let b = unsafe { imm_ref() };
    |
 
 error[E0507]: cannot move out of a raw pointer
-  --> $DIR/issue-20801.rs:32:22
+  --> $DIR/issue-20801.rs:33:22
    |
 LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -35,7 +50,7 @@ LL +     let c = unsafe { mut_ptr() };
    |
 
 error[E0507]: cannot move out of a raw pointer
-  --> $DIR/issue-20801.rs:35:22
+  --> $DIR/issue-20801.rs:36:22
    |
 LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -46,6 +61,6 @@ LL -     let d = unsafe { *const_ptr() };
 LL +     let d = unsafe { const_ptr() };
    |
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
index b3cce1b3a06..9b172b41319 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
@@ -8,7 +8,10 @@ mod borrowck_closures_unique {
         static mut Y: isize = 3;
         let mut c1 = |y: &'static mut isize| x = y;
         //~^ ERROR is not declared as mutable
-        unsafe { c1(&mut Y); }
+        unsafe {
+            c1(&mut Y);
+            //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+        }
     }
 }
 
@@ -17,36 +20,50 @@ mod borrowck_closures_unique_grandparent {
         static mut Z: isize = 3;
         let mut c1 = |z: &'static mut isize| {
             let mut c2 = |y: &'static mut isize| x = y;
-        //~^ ERROR is not declared as mutable
+            //~^ ERROR is not declared as mutable
             c2(z);
         };
-        unsafe { c1(&mut Z); }
+        unsafe {
+            c1(&mut Z);
+            //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+        }
     }
 }
 
 // adapted from mutability_errors.rs
 mod mutability_errors {
     pub fn capture_assign_whole(x: (i32,)) {
-        || { x = (1,); };
-        //~^ ERROR is not declared as mutable
+        || {
+            x = (1,);
+            //~^ ERROR is not declared as mutable
+        };
     }
     pub fn capture_assign_part(x: (i32,)) {
-        || { x.0 = 1; };
-        //~^ ERROR is not declared as mutable
+        || {
+            x.0 = 1;
+            //~^ ERROR is not declared as mutable
+        };
     }
     pub fn capture_reborrow_whole(x: (i32,)) {
-        || { &mut x; };
-        //~^ ERROR is not declared as mutable
+        || {
+            &mut x;
+            //~^ ERROR is not declared as mutable
+        };
     }
     pub fn capture_reborrow_part(x: (i32,)) {
-        || { &mut x.0; };
-        //~^ ERROR is not declared as mutable
+        || {
+            &mut x.0;
+            //~^ ERROR is not declared as mutable
+        };
     }
 }
 
 fn main() {
     static mut X: isize = 2;
-    unsafe { borrowck_closures_unique::e(&mut X); }
+    unsafe {
+        borrowck_closures_unique::e(&mut X);
+        //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+    }
 
     mutability_errors::capture_assign_whole((1000,));
     mutability_errors::capture_assign_part((2000,));
diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
index 4c299cdc455..e4e4947fce1 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
@@ -1,3 +1,46 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:12:16
+   |
+LL |             c1(&mut Y);
+   |                ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |             c1(addr_of_mut!(Y));
+   |                ~~~~~~~~~~~~~~~
+
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16
+   |
+LL |             c1(&mut Z);
+   |                ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |             c1(addr_of_mut!(Z));
+   |                ~~~~~~~~~~~~~~~
+
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37
+   |
+LL |         borrowck_closures_unique::e(&mut X);
+   |                                     ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         borrowck_closures_unique::e(addr_of_mut!(X));
+   |                                     ~~~~~~~~~~~~~~~
+
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46
    |
@@ -8,7 +51,7 @@ LL |         let mut c1 = |y: &'static mut isize| x = y;
    |                                              ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:19:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:22:50
    |
 LL |     pub fn ee(x: &'static mut isize) {
    |               - help: consider changing this to be mutable: `mut x`
@@ -17,38 +60,42 @@ LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:30:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:37:13
    |
 LL |     pub fn capture_assign_whole(x: (i32,)) {
    |                                 - help: consider changing this to be mutable: `mut x`
-LL |         || { x = (1,); };
-   |              ^^^^^^^^ cannot assign
+LL |         || {
+LL |             x = (1,);
+   |             ^^^^^^^^ cannot assign
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:34:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:43:13
    |
 LL |     pub fn capture_assign_part(x: (i32,)) {
    |                                - help: consider changing this to be mutable: `mut x`
-LL |         || { x.0 = 1; };
-   |              ^^^^^^^ cannot assign
+LL |         || {
+LL |             x.0 = 1;
+   |             ^^^^^^^ cannot assign
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:38:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:49:13
    |
 LL |     pub fn capture_reborrow_whole(x: (i32,)) {
    |                                   - help: consider changing this to be mutable: `mut x`
-LL |         || { &mut x; };
-   |              ^^^^^^ cannot borrow as mutable
+LL |         || {
+LL |             &mut x;
+   |             ^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:42:14
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:13
    |
 LL |     pub fn capture_reborrow_part(x: (i32,)) {
    |                                  - help: consider changing this to be mutable: `mut x`
-LL |         || { &mut x.0; };
-   |              ^^^^^^^^ cannot borrow as mutable
+LL |         || {
+LL |             &mut x.0;
+   |             ^^^^^^^^ cannot borrow as mutable
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0594, E0596.
 For more information about an error, try `rustc --explain E0594`.
diff --git a/tests/ui/consts/const_let_assign2.rs b/tests/ui/consts/const_let_assign2.rs
index 28265c85dd1..1c7afe0e3d6 100644
--- a/tests/ui/consts/const_let_assign2.rs
+++ b/tests/ui/consts/const_let_assign2.rs
@@ -16,6 +16,7 @@ static mut BB: AA = AA::new();
 
 fn main() {
     let ptr = unsafe { &mut BB };
+    //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
     for a in ptr.data.iter() {
         println!("{}", a);
     }
diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr
new file mode 100644
index 00000000000..2764153a8a5
--- /dev/null
+++ b/tests/ui/consts/const_let_assign2.stderr
@@ -0,0 +1,17 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/const_let_assign2.rs:18:24
+   |
+LL |     let ptr = unsafe { &mut BB };
+   |                        ^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     let ptr = unsafe { addr_of_mut!(BB) };
+   |                        ~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/consts/issue-17718-const-bad-values.rs b/tests/ui/consts/issue-17718-const-bad-values.rs
index 62bbb3b569c..4fedc48452b 100644
--- a/tests/ui/consts/issue-17718-const-bad-values.rs
+++ b/tests/ui/consts/issue-17718-const-bad-values.rs
@@ -3,7 +3,8 @@ const C1: &'static mut [usize] = &mut [];
 
 static mut S: usize = 3;
 const C2: &'static mut usize = unsafe { &mut S };
-//~^ ERROR: constants cannot refer to statics
+//~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+//~^^ ERROR: constants cannot refer to statics
 //~| ERROR: constants cannot refer to statics
 
 fn main() {}
diff --git a/tests/ui/consts/issue-17718-const-bad-values.stderr b/tests/ui/consts/issue-17718-const-bad-values.stderr
index 405c2195dec..2dc91f52669 100644
--- a/tests/ui/consts/issue-17718-const-bad-values.stderr
+++ b/tests/ui/consts/issue-17718-const-bad-values.stderr
@@ -1,3 +1,18 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/issue-17718-const-bad-values.rs:5:41
+   |
+LL | const C2: &'static mut usize = unsafe { &mut S };
+   |                                         ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL | const C2: &'static mut usize = unsafe { addr_of_mut!(S) };
+   |                                         ~~~~~~~~~~~~~~~
+
 error[E0764]: mutable references are not allowed in the final value of constants
   --> $DIR/issue-17718-const-bad-values.rs:1:34
    |
@@ -21,7 +36,7 @@ LL | const C2: &'static mut usize = unsafe { &mut S };
    = help: consider extracting the value of the `static` to a `const`, and referring to that
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 3 previous errors
+error: aborting due to 3 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0013, E0764.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
index 7960648ce3a..ed9db675426 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
@@ -1,3 +1,18 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:14
+   |
+LL |     unsafe { &static_cross_crate::ZERO }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     unsafe { addr_of!(static_cross_crate::ZERO) }
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const_refers_to_static_cross_crate.rs:10:1
    |
@@ -10,13 +25,13 @@ LL | const SLICE_MUT: &[u8; 1] = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:34:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
    |
 LL |         SLICE_MUT => true,
    |         ^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const_refers_to_static_cross_crate.rs:15:1
+  --> $DIR/const_refers_to_static_cross_crate.rs:17:1
    |
 LL | const U8_MUT: &u8 = {
    | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -27,31 +42,31 @@ LL | const U8_MUT: &u8 = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:50:9
    |
 LL |         U8_MUT => true,
    |         ^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_refers_to_static_cross_crate.rs:22:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:15
    |
 LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:52:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:60:9
    |
 LL |         U8_MUT2 => true,
    |         ^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:59:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:67:9
    |
 LL |         U8_MUT3 => true,
    |         ^^^^^^^
@@ -59,61 +74,61 @@ LL |         U8_MUT3 => true,
 warning: skipping const checks
    |
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:12:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:15
    |
 LL |     unsafe { &static_cross_crate::ZERO }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:12:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:15
    |
 LL |     unsafe { &static_cross_crate::ZERO }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:22:17
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:17
    |
 LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
index 6ae0b2d1bfe..275323bc286 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
@@ -1,3 +1,18 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:14
+   |
+LL |     unsafe { &static_cross_crate::ZERO }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     unsafe { addr_of!(static_cross_crate::ZERO) }
+   |              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0080]: it is undefined behavior to use this value
   --> $DIR/const_refers_to_static_cross_crate.rs:10:1
    |
@@ -10,13 +25,13 @@ LL | const SLICE_MUT: &[u8; 1] = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:34:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
    |
 LL |         SLICE_MUT => true,
    |         ^^^^^^^^^
 
 error[E0080]: it is undefined behavior to use this value
-  --> $DIR/const_refers_to_static_cross_crate.rs:15:1
+  --> $DIR/const_refers_to_static_cross_crate.rs:17:1
    |
 LL | const U8_MUT: &u8 = {
    | ^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a reference pointing to a static variable in a constant
@@ -27,31 +42,31 @@ LL | const U8_MUT: &u8 = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:50:9
    |
 LL |         U8_MUT => true,
    |         ^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_refers_to_static_cross_crate.rs:22:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:15
    |
 LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:52:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:60:9
    |
 LL |         U8_MUT2 => true,
    |         ^^^^^^^
 
 error[E0080]: evaluation of constant value failed
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:59:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:67:9
    |
 LL |         U8_MUT3 => true,
    |         ^^^^^^^
@@ -59,61 +74,61 @@ LL |         U8_MUT3 => true,
 warning: skipping const checks
    |
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:12:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:15
    |
 LL |     unsafe { &static_cross_crate::ZERO }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:12:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:13:15
    |
 LL |     unsafe { &static_cross_crate::ZERO }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:17:15
+  --> $DIR/const_refers_to_static_cross_crate.rs:20:15
    |
 LL |     unsafe { &static_cross_crate::ZERO[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:22:17
+  --> $DIR/const_refers_to_static_cross_crate.rs:25:17
    |
 LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/const_refers_to_static_cross_crate.rs:27:20
+  --> $DIR/const_refers_to_static_cross_crate.rs:31:15
    |
-LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         match static_cross_crate::OPT_ZERO {
+   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 8 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
index bbaa32ddfd1..3eafa58d9f9 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
@@ -7,13 +7,16 @@ extern crate static_cross_crate;
 
 // Sneaky: reference to a mutable static.
 // Allowing this would be a disaster for pattern matching, we could violate exhaustiveness checking!
-const SLICE_MUT: &[u8; 1] = { //~ ERROR undefined behavior to use this value
-//~| encountered a reference pointing to a static variable
+const SLICE_MUT: &[u8; 1] = {
+    //~^ ERROR undefined behavior to use this value
+    //~| encountered a reference pointing to a static variable
     unsafe { &static_cross_crate::ZERO }
+    //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
 };
 
-const U8_MUT: &u8 = { //~ ERROR undefined behavior to use this value
-//~| encountered a reference pointing to a static variable
+const U8_MUT: &u8 = {
+    //~^ ERROR undefined behavior to use this value
+    //~| encountered a reference pointing to a static variable
     unsafe { &static_cross_crate::ZERO[0] }
 };
 
@@ -24,9 +27,14 @@ const U8_MUT2: &u8 = {
     //~| constant accesses static
 };
 const U8_MUT3: &u8 = {
-    unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
-    //~^ ERROR evaluation of constant value failed
-    //~| constant accesses static
+    unsafe {
+        match static_cross_crate::OPT_ZERO {
+            //~^ ERROR evaluation of constant value failed
+            //~| constant accesses static
+            Some(ref u) => u,
+            None => panic!(),
+        }
+    }
 };
 
 pub fn test(x: &[u8; 1]) -> bool {
diff --git a/tests/ui/consts/static_mut_containing_mut_ref.rs b/tests/ui/consts/static_mut_containing_mut_ref.rs
index df09c76c558..874aa59df0b 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref.rs
+++ b/tests/ui/consts/static_mut_containing_mut_ref.rs
@@ -3,5 +3,6 @@
 static mut STDERR_BUFFER_SPACE: [u8; 42] = [0u8; 42];
 
 pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };
+//~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 
 fn main() {}
diff --git a/tests/ui/consts/static_mut_containing_mut_ref.stderr b/tests/ui/consts/static_mut_containing_mut_ref.stderr
new file mode 100644
index 00000000000..56ceba41cf8
--- /dev/null
+++ b/tests/ui/consts/static_mut_containing_mut_ref.stderr
@@ -0,0 +1,17 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/static_mut_containing_mut_ref.rs:5:52
+   |
+LL | pub static mut STDERR_BUFFER: *mut [u8] = unsafe { &mut STDERR_BUFFER_SPACE };
+   |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL | pub static mut STDERR_BUFFER: *mut [u8] = unsafe { addr_of_mut!(STDERR_BUFFER_SPACE) };
+   |                                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
index 3d0de233569..bc32ecc2c35 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
+++ b/tests/ui/consts/static_mut_containing_mut_ref2.mut_refs.stderr
@@ -1,9 +1,24 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/static_mut_containing_mut_ref2.rs:8:6
+   |
+LL |     *(&mut STDERR_BUFFER_SPACE) = 42;
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     *addr_of_mut!(STDERR_BUFFER_SPACE) = 42;
+   |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0080]: could not evaluate static initializer
-  --> $DIR/static_mut_containing_mut_ref2.rs:7:45
+  --> $DIR/static_mut_containing_mut_ref2.rs:8:5
    |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer
+LL |     *(&mut STDERR_BUFFER_SPACE) = 42;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ modifying a static's initial value from another static's initializer
 
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.rs b/tests/ui/consts/static_mut_containing_mut_ref2.rs
index 61368546083..fa79a78eab4 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref2.rs
+++ b/tests/ui/consts/static_mut_containing_mut_ref2.rs
@@ -4,8 +4,12 @@
 
 static mut STDERR_BUFFER_SPACE: u8 = 0;
 
-pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-//[mut_refs]~^ ERROR could not evaluate static initializer
-//[stock]~^^ ERROR mutable references are not allowed in statics
+pub static mut STDERR_BUFFER: () = unsafe {
+    *(&mut STDERR_BUFFER_SPACE) = 42;
+    //[mut_refs]~^ ERROR could not evaluate static initializer
+    //[stock]~^^ ERROR mutable references are not allowed in statics
+    //[mut_refs]~^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+    //[stock]~^^^^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+};
 
 fn main() {}
diff --git a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr
index 3d5b012d42f..c6e5b07e3b7 100644
--- a/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr
+++ b/tests/ui/consts/static_mut_containing_mut_ref2.stock.stderr
@@ -1,12 +1,27 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/static_mut_containing_mut_ref2.rs:8:6
+   |
+LL |     *(&mut STDERR_BUFFER_SPACE) = 42;
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     *addr_of_mut!(STDERR_BUFFER_SPACE) = 42;
+   |      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0658]: mutable references are not allowed in statics
-  --> $DIR/static_mut_containing_mut_ref2.rs:7:46
+  --> $DIR/static_mut_containing_mut_ref2.rs:8:6
    |
-LL | pub static mut STDERR_BUFFER: () = unsafe { *(&mut STDERR_BUFFER_SPACE) = 42; };
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     *(&mut STDERR_BUFFER_SPACE) = 42;
+   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error: aborting due to 1 previous error
+error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
index a99f260dde3..52603744c45 100644
--- a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
+++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
@@ -13,38 +13,39 @@ pub fn main() {
     d::println("created empty log");
     test(&log);
 
-    assert_eq!(&log.borrow()[..],
-               [
-                   //                                    created empty log
-                   //    +-- Make D(da_0, 0)
-                   //    | +-- Make D(de_1, 1)
-                   //    | |                             calling foo
-                   //    | |                             entered foo
-                   //    | | +-- Make D(de_2, 2)
-                   //    | | | +-- Make D(da_1, 3)
-                   //    | | | | +-- Make D(de_3, 4)
-                   //    | | | | | +-- Make D(de_4, 5)
-                   3, // | | | +-- Drop D(da_1, 3)
-                   //    | | |   | |
-                   4, // | | |   +-- Drop D(de_3, 4)
-                   //    | | |     |
-                   //    | | |     |                     eval tail of foo
-                   //    | | | +-- Make D(de_5, 6)
-                   //    | | | | +-- Make D(de_6, 7)
-                   5, // | | | | | +-- Drop D(de_4, 5)
-                   //    | | | | |
-                   2, // | | +-- Drop D(de_2, 2)
-                   //    | |   | |
-                   6, // | |   +-- Drop D(de_5, 6)
-                   //    | |     |
-                   1, // | +-- Drop D(de_1, 1)
-                   //    |       |
-                   0, // +-- Drop D(da_0, 0)
-                   //            |
-                   //            |                       result D(de_6, 7)
-                   7 //          +-- Drop D(de_6, 7)
-
-                       ]);
+    assert_eq!(
+        &log.borrow()[..],
+        [
+            //                                    created empty log
+            //    +-- Make D(da_0, 0)
+            //    | +-- Make D(de_1, 1)
+            //    | |                             calling foo
+            //    | |                             entered foo
+            //    | | +-- Make D(de_2, 2)
+            //    | | | +-- Make D(da_1, 3)
+            //    | | | | +-- Make D(de_3, 4)
+            //    | | | | | +-- Make D(de_4, 5)
+            3, // | | | +-- Drop D(da_1, 3)
+            //    | | |   | |
+            4, // | | |   +-- Drop D(de_3, 4)
+            //    | | |     |
+            //    | | |     |                     eval tail of foo
+            //    | | | +-- Make D(de_5, 6)
+            //    | | | | +-- Make D(de_6, 7)
+            5, // | | | | | +-- Drop D(de_4, 5)
+            //    | | | | |
+            2, // | | +-- Drop D(de_2, 2)
+            //    | |   | |
+            6, // | |   +-- Drop D(de_5, 6)
+            //    | |     |
+            1, // | +-- Drop D(de_1, 1)
+            //    |       |
+            0, // +-- Drop D(da_0, 0)
+            //            |
+            //            |                       result D(de_6, 7)
+            7 //          +-- Drop D(de_6, 7)
+        ]
+    );
 }
 
 fn test<'a>(log: d::Log<'a>) {
@@ -57,13 +58,13 @@ fn test<'a>(log: d::Log<'a>) {
 
 fn foo<'a>(da0: D<'a>, de1: D<'a>) -> D<'a> {
     d::println("entered foo");
-    let de2 = de1.incr();      // creates D(de_2, 2)
+    let de2 = de1.incr(); // creates D(de_2, 2)
     let de4 = {
         let _da1 = da0.incr(); // creates D(da_1, 3)
-        de2.incr().incr()      // creates D(de_3, 4) and D(de_4, 5)
+        de2.incr().incr() // creates D(de_3, 4) and D(de_4, 5)
     };
     d::println("eval tail of foo");
-    de4.incr().incr()          // creates D(de_5, 6) and D(de_6, 7)
+    de4.incr().incr() // creates D(de_5, 6) and D(de_6, 7)
 }
 
 // This module provides simultaneous printouts of the dynamic extents
@@ -74,9 +75,9 @@ const PREF_INDENT: u32 = 16;
 
 pub mod d {
     #![allow(unused_parens)]
+    use std::cell::RefCell;
     use std::fmt;
     use std::mem;
-    use std::cell::RefCell;
 
     static mut counter: u32 = 0;
     static mut trails: u64 = 0;
@@ -89,7 +90,8 @@ pub mod d {
 
     pub fn max_width() -> u32 {
         unsafe {
-            (mem::size_of_val(&trails)*8) as u32
+            (mem::size_of_val(&trails) * 8) as u32
+            //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
         }
     }
 
@@ -123,7 +125,11 @@ pub mod d {
     }
 
     pub struct D<'a> {
-        name: &'static str, i: u32, uid: u32, trail: u32, log: Log<'a>
+        name: &'static str,
+        i: u32,
+        uid: u32,
+        trail: u32,
+        log: Log<'a>,
     }
 
     impl<'a> fmt::Display for D<'a> {
@@ -139,9 +145,7 @@ pub mod d {
                 let ctr = counter;
                 counter += 1;
                 trails |= (1 << trail);
-                let ret = D {
-                    name: name, i: i, log: log, uid: ctr, trail: trail
-                };
+                let ret = D { name: name, i: i, log: log, uid: ctr, trail: trail };
                 indent_println(trail, &format!("+-- Make {}", ret));
                 ret
             }
@@ -153,7 +157,9 @@ pub mod d {
 
     impl<'a> Drop for D<'a> {
         fn drop(&mut self) {
-            unsafe { trails &= !(1 << self.trail); };
+            unsafe {
+                trails &= !(1 << self.trail);
+            };
             self.log.borrow_mut().push(self.uid);
             indent_println(self.trail, &format!("+-- Drop {}", self));
             indent_println(::PREF_INDENT, "");
diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
new file mode 100644
index 00000000000..fd36ccbcbee
--- /dev/null
+++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
@@ -0,0 +1,17 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/issue-23338-ensure-param-drop-order.rs:93:31
+   |
+LL |             (mem::size_of_val(&trails) * 8) as u32
+   |                               ^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
+   |                               ~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/error-codes/E0017.rs b/tests/ui/error-codes/E0017.rs
index c211ad1a2f8..9d3433fa543 100644
--- a/tests/ui/error-codes/E0017.rs
+++ b/tests/ui/error-codes/E0017.rs
@@ -3,12 +3,16 @@ const C: i32 = 2;
 static mut M: i32 = 3;
 
 const CR: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
-                                     //~| WARN taking a mutable
+//~| WARN taking a mutable
+
 static STATIC_REF: &'static mut i32 = &mut X; //~ ERROR E0658
-                                              //~| ERROR cannot borrow
-                                              //~| ERROR mutable references are not allowed
+//~| ERROR cannot borrow
+//~| ERROR mutable references are not allowed
 
 static CONST_REF: &'static mut i32 = &mut C; //~ ERROR mutable references are not allowed
-                                              //~| WARN taking a mutable
+//~| WARN taking a mutable
+
 static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M }; //~ ERROR mutable references are not
+//~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+
 fn main() {}
diff --git a/tests/ui/error-codes/E0017.stderr b/tests/ui/error-codes/E0017.stderr
index 6e48f9582f1..ea6055da1c1 100644
--- a/tests/ui/error-codes/E0017.stderr
+++ b/tests/ui/error-codes/E0017.stderr
@@ -1,3 +1,18 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/E0017.rs:15:52
+   |
+LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
+   |                                                    ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { addr_of_mut!(M) };
+   |                                                    ~~~~~~~~~~~~~~~
+
 warning: taking a mutable reference to a `const` item
   --> $DIR/E0017.rs:5:30
    |
@@ -20,7 +35,7 @@ LL | const CR: &'static mut i32 = &mut C;
    |                              ^^^^^^
 
 error[E0658]: mutation through a reference is not allowed in statics
-  --> $DIR/E0017.rs:7:39
+  --> $DIR/E0017.rs:8:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^
@@ -29,19 +44,19 @@ LL | static STATIC_REF: &'static mut i32 = &mut X;
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
 error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0017.rs:7:39
+  --> $DIR/E0017.rs:8:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^
 
 error[E0596]: cannot borrow immutable static item `X` as mutable
-  --> $DIR/E0017.rs:7:39
+  --> $DIR/E0017.rs:8:39
    |
 LL | static STATIC_REF: &'static mut i32 = &mut X;
    |                                       ^^^^^^ cannot borrow as mutable
 
 warning: taking a mutable reference to a `const` item
-  --> $DIR/E0017.rs:11:38
+  --> $DIR/E0017.rs:12:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
@@ -55,18 +70,18 @@ LL | const C: i32 = 2;
    | ^^^^^^^^^^^^
 
 error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0017.rs:11:38
+  --> $DIR/E0017.rs:12:38
    |
 LL | static CONST_REF: &'static mut i32 = &mut C;
    |                                      ^^^^^^
 
 error[E0764]: mutable references are not allowed in the final value of statics
-  --> $DIR/E0017.rs:13:52
+  --> $DIR/E0017.rs:15:52
    |
 LL | static STATIC_MUT_REF: &'static mut i32 = unsafe { &mut M };
    |                                                    ^^^^^^
 
-error: aborting due to 6 previous errors; 2 warnings emitted
+error: aborting due to 6 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0596, E0658, E0764.
 For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/issues/issue-20616.rs b/tests/ui/impl-header-lifetime-elision/bare_type.rs
index 6c24d437272..9af98f870d2 100644
--- a/tests/ui/issues/issue-20616.rs
+++ b/tests/ui/impl-header-lifetime-elision/bare_type.rs
@@ -33,12 +33,11 @@ type TypeI<T,> = T;
 static STATIC: () = ();
 
 fn main() {
-
     // ensure token `>=` works fine
-    let _: TypeA<'static>= &STATIC;
-    let _: TypeA<'static,>= &STATIC;
+    let _: TypeA<'static> = &STATIC;
+    let _: TypeA<'static,> = &STATIC;
 
     // ensure token `>>=` works fine
-    let _: Box<TypeA<'static>>= Box::new(&STATIC);
-    let _: Box<TypeA<'static,>>= Box::new(&STATIC);
+    let _: Box<TypeA<'static>> = Box::new(&STATIC);
+    let _: Box<TypeA<'static,>> = Box::new(&STATIC);
 }
diff --git a/tests/ui/issues/issue-23611-enum-swap-in-drop.rs b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs
index cdb130d600c..b967e6aecdd 100644
--- a/tests/ui/issues/issue-23611-enum-swap-in-drop.rs
+++ b/tests/ui/issues/issue-23611-enum-swap-in-drop.rs
@@ -37,11 +37,9 @@ pub fn main() {
             // | | | +-- Make D(g_b_5, 50000005)
             // | | | |                                 in g_B(b4b2) from GaspB::drop
             // | | | +-- Drop D(g_b_5, 50000005)
-            50000005,
-            // | | |
+            50000005, // | | |
             // | | +-- Drop D(GaspB::drop_3, 30000004)
-            30000004,
-            // | |
+            30000004, // | |
             // +-- Drop D(test_1, 10000000)
             10000000,
             //   |
@@ -49,15 +47,13 @@ pub fn main() {
             // | | +-- Make D(f_a_4, 40000007)
             // | | |                                   in f_A(a3a0) from GaspA::drop
             // | | +-- Drop D(f_a_4, 40000007)
-            40000007,
-            // | |
+            40000007, // | |
             // +-- Drop D(GaspA::drop_2, 20000006)
-            20000006,
-            //   |
+            20000006, //   |
             //   +-- Drop D(drop_6, 60000002)
-            60000002
-            //
-                ]);
+            60000002 //
+        ]
+    );
 
     // For reference purposes, the old (incorrect) behavior would produce the following
     // output, which you can compare to the above:
@@ -106,8 +102,8 @@ fn test<'a>(log: d::Log<'a>) {
     let _e = E::B(GaspB(g_b, 0xB4B0, log, D::new("test", 1, log)), true);
 }
 
-struct GaspA<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
-struct GaspB<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
+struct GaspA<'a>(for<'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
+struct GaspB<'a>(for<'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
 
 impl<'a> Drop for GaspA<'a> {
     fn drop(&mut self) {
@@ -124,7 +120,8 @@ impl<'a> Drop for GaspB<'a> {
 }
 
 enum E<'a> {
-    A(GaspA<'a>, bool), B(GaspB<'a>, bool),
+    A(GaspA<'a>, bool),
+    B(GaspB<'a>, bool),
 }
 
 fn f_a(x: u32, ctxt: &str, log: d::Log) {
@@ -174,9 +171,9 @@ const PREF_INDENT: u32 = 20;
 
 pub mod d {
     #![allow(unused_parens)]
+    use std::cell::RefCell;
     use std::fmt;
     use std::mem;
-    use std::cell::RefCell;
 
     static mut counter: u16 = 0;
     static mut trails: u64 = 0;
@@ -189,7 +186,8 @@ pub mod d {
 
     pub fn max_width() -> u32 {
         unsafe {
-            (mem::size_of_val(&trails)*8) as u32
+            (mem::size_of_val(&trails) * 8) as u32
+            //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
         }
     }
 
@@ -223,7 +221,11 @@ pub mod d {
     }
 
     pub struct D<'a> {
-        name: &'static str, i: u8, uid: u32, trail: u32, log: Log<'a>
+        name: &'static str,
+        i: u8,
+        uid: u32,
+        trail: u32,
+        log: Log<'a>,
     }
 
     impl<'a> fmt::Display for D<'a> {
@@ -239,9 +241,7 @@ pub mod d {
                 let ctr = ((i as u32) * 10_000_000) + (counter as u32);
                 counter += 1;
                 trails |= (1 << trail);
-                let ret = D {
-                    name: name, i: i, log: log, uid: ctr, trail: trail
-                };
+                let ret = D { name: name, i: i, log: log, uid: ctr, trail: trail };
                 indent_println(trail, &format!("+-- Make {}", ret));
                 ret
             }
@@ -250,7 +250,9 @@ pub mod d {
 
     impl<'a> Drop for D<'a> {
         fn drop(&mut self) {
-            unsafe { trails &= !(1 << self.trail); };
+            unsafe {
+                trails &= !(1 << self.trail);
+            };
             self.log.borrow_mut().push(self.uid);
             indent_println(self.trail, &format!("+-- Drop {}", self));
             indent_println(::PREF_INDENT, "");
diff --git a/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr b/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr
new file mode 100644
index 00000000000..14a986a3332
--- /dev/null
+++ b/tests/ui/issues/issue-23611-enum-swap-in-drop.stderr
@@ -0,0 +1,17 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/issue-23611-enum-swap-in-drop.rs:189:31
+   |
+LL |             (mem::size_of_val(&trails) * 8) as u32
+   |                               ^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
+   |                               ~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
index 7d3b00dfc71..8eb544e8ab9 100644
--- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
+++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.rs
@@ -14,9 +14,8 @@ struct S1 {
 
 impl S1 {
     fn new(_x: u64) -> S1 {
-        S1 {
-            a: unsafe { &mut X1 },
-        }
+        S1 { a: unsafe { &mut X1 } }
+        //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
     }
 }
 
diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
new file mode 100644
index 00000000000..17217cd5859
--- /dev/null
+++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
@@ -0,0 +1,17 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/borrowck-thread-local-static-mut-borrow-outlives-fn.rs:17:26
+   |
+LL |         S1 { a: unsafe { &mut X1 } }
+   |                          ^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         S1 { a: unsafe { addr_of_mut!(X1) } }
+   |                          ~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/static/reference-of-mut-static-safe.e2021.stderr b/tests/ui/static/reference-of-mut-static-safe.e2021.stderr
new file mode 100644
index 00000000000..16f47ace3a9
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static-safe.e2021.stderr
@@ -0,0 +1,26 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static-safe.rs:9:14
+   |
+LL |     let _x = &X;
+   |              ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let _x = addr_of!(X);
+   |              ~~~~~~~~~~~
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/reference-of-mut-static-safe.rs:9:15
+   |
+LL |     let _x = &X;
+   |               ^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/static/reference-of-mut-static-safe.e2024.stderr b/tests/ui/static/reference-of-mut-static-safe.e2024.stderr
new file mode 100644
index 00000000000..53f81179de5
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static-safe.e2024.stderr
@@ -0,0 +1,15 @@
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-safe.rs:9:14
+   |
+LL |     let _x = &X;
+   |              ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let _x = addr_of!(X);
+   |              ~~~~~~~~~~~
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0796`.
diff --git a/tests/ui/static/reference-of-mut-static-safe.rs b/tests/ui/static/reference-of-mut-static-safe.rs
new file mode 100644
index 00000000000..5cb1a03bef5
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static-safe.rs
@@ -0,0 +1,13 @@
+// revisions: e2021 e2024
+
+// [e2021] edition:2021
+// [e2024] compile-flags: --edition 2024 -Z unstable-options
+
+fn main() {
+    static mut X: i32 = 1;
+
+    let _x = &X;
+    //[e2024]~^ reference of mutable static is disallowed [E0796]
+    //[e2021]~^^ use of mutable static is unsafe and requires unsafe function or block [E0133]
+    //[e2021]~^^^ shared reference of mutable static is discouraged [static_mut_ref]
+}
diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.rs b/tests/ui/static/reference-of-mut-static-unsafe-fn.rs
new file mode 100644
index 00000000000..6b1e77850e5
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static-unsafe-fn.rs
@@ -0,0 +1,23 @@
+// compile-flags: --edition 2024 -Z unstable-options
+
+fn main() {}
+
+unsafe fn _foo() {
+    static mut X: i32 = 1;
+    static mut Y: i32 = 1;
+
+    let _y = &X;
+    //~^ ERROR reference of mutable static is disallowed
+
+    let ref _a = X;
+    //~^ ERROR reference of mutable static is disallowed
+
+    let (_b, _c) = (&X, &Y);
+    //~^ ERROR reference of mutable static is disallowed
+    //~^^ ERROR reference of mutable static is disallowed
+
+    foo(&X);
+    //~^ ERROR reference of mutable static is disallowed
+}
+
+fn foo<'a>(_x: &'a i32) {}
diff --git a/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr
new file mode 100644
index 00000000000..5c6fdedfa96
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static-unsafe-fn.stderr
@@ -0,0 +1,63 @@
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-unsafe-fn.rs:9:14
+   |
+LL |     let _y = &X;
+   |              ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let _y = addr_of!(X);
+   |              ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-unsafe-fn.rs:12:18
+   |
+LL |     let ref _a = X;
+   |                  ^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let ref _a = addr_of!(X);
+   |                  ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-unsafe-fn.rs:15:21
+   |
+LL |     let (_b, _c) = (&X, &Y);
+   |                     ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let (_b, _c) = (addr_of!(X), &Y);
+   |                     ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-unsafe-fn.rs:15:25
+   |
+LL |     let (_b, _c) = (&X, &Y);
+   |                         ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let (_b, _c) = (&X, addr_of!(Y));
+   |                         ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static-unsafe-fn.rs:19:9
+   |
+LL |     foo(&X);
+   |         ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     foo(addr_of!(X));
+   |         ~~~~~~~~~~~
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0796`.
diff --git a/tests/ui/static/reference-of-mut-static.e2021.stderr b/tests/ui/static/reference-of-mut-static.e2021.stderr
new file mode 100644
index 00000000000..77a6b3d304b
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static.e2021.stderr
@@ -0,0 +1,91 @@
+error: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:16:18
+   |
+LL |         let _y = &X;
+   |                  ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+note: the lint level is defined here
+  --> $DIR/reference-of-mut-static.rs:6:9
+   |
+LL | #![deny(static_mut_ref)]
+   |         ^^^^^^^^^^^^^^
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let _y = addr_of!(X);
+   |                  ~~~~~~~~~~~
+
+error: mutable reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:20:18
+   |
+LL |         let _y = &mut X;
+   |                  ^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         let _y = addr_of_mut!(X);
+   |                  ~~~~~~~~~~~~~~~
+
+error: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:28:22
+   |
+LL |         let ref _a = X;
+   |                      ^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let ref _a = addr_of!(X);
+   |                      ~~~~~~~~~~~
+
+error: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:32:25
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                         ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (addr_of!(X), &Y);
+   |                         ~~~~~~~~~~~
+
+error: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:32:29
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                             ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&X, addr_of!(Y));
+   |                             ~~~~~~~~~~~
+
+error: shared reference of mutable static is discouraged
+  --> $DIR/reference-of-mut-static.rs:38:13
+   |
+LL |         foo(&X);
+   |             ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         foo(addr_of!(X));
+   |             ~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/static/reference-of-mut-static.e2024.stderr b/tests/ui/static/reference-of-mut-static.e2024.stderr
new file mode 100644
index 00000000000..f445ec65a5d
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static.e2024.stderr
@@ -0,0 +1,75 @@
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:16:18
+   |
+LL |         let _y = &X;
+   |                  ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let _y = addr_of!(X);
+   |                  ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:20:18
+   |
+LL |         let _y = &mut X;
+   |                  ^^^^^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         let _y = addr_of_mut!(X);
+   |                  ~~~~~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:28:22
+   |
+LL |         let ref _a = X;
+   |                      ^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let ref _a = addr_of!(X);
+   |                      ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:32:25
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                         ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (addr_of!(X), &Y);
+   |                         ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:32:29
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                             ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&X, addr_of!(Y));
+   |                             ~~~~~~~~~~~
+
+error[E0796]: reference of mutable static is disallowed
+  --> $DIR/reference-of-mut-static.rs:38:13
+   |
+LL |         foo(&X);
+   |             ^^ reference of mutable static
+   |
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |         foo(addr_of!(X));
+   |             ~~~~~~~~~~~
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0796`.
diff --git a/tests/ui/static/reference-of-mut-static.rs b/tests/ui/static/reference-of-mut-static.rs
new file mode 100644
index 00000000000..01a3b1fbd9b
--- /dev/null
+++ b/tests/ui/static/reference-of-mut-static.rs
@@ -0,0 +1,50 @@
+// revisions: e2021 e2024
+
+// [e2021] edition:2021
+// [e2024] compile-flags: --edition 2024 -Z unstable-options
+
+#![deny(static_mut_ref)]
+
+use std::ptr::{addr_of, addr_of_mut};
+
+fn main() {
+    static mut X: i32 = 1;
+
+    static mut Y: i32 = 1;
+
+    unsafe {
+        let _y = &X;
+        //[e2024]~^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref]
+
+        let _y = &mut X;
+        //[e2024]~^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^ ERROR mutable reference of mutable static is discouraged [static_mut_ref]
+
+        let _z = addr_of_mut!(X);
+
+        let _p = addr_of!(X);
+
+        let ref _a = X;
+        //[e2024]~^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref]
+
+        let (_b, _c) = (&X, &Y);
+        //[e2024]~^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref]
+        //[e2024]~^^^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^^^ ERROR shared reference of mutable static is discouraged [static_mut_ref]
+
+        foo(&X);
+        //[e2024]~^ ERROR reference of mutable static is disallowed
+        //[e2021]~^^ ERROR shared reference of mutable static is discouraged [static_mut_ref]
+
+        static mut Z: &[i32; 3] = &[0, 1, 2];
+
+        let _ = Z.len();
+        let _ = Z[0];
+        let _ = format!("{:?}", Z);
+    }
+}
+
+fn foo<'a>(_x: &'a i32) {}
diff --git a/tests/ui/static/safe-extern-statics-mut.rs b/tests/ui/static/safe-extern-statics-mut.rs
index 324fa443aa5..1c0662e0a6c 100644
--- a/tests/ui/static/safe-extern-statics-mut.rs
+++ b/tests/ui/static/safe-extern-statics-mut.rs
@@ -10,6 +10,8 @@ extern "C" {
 fn main() {
     let b = B; //~ ERROR use of mutable static is unsafe
     let rb = &B; //~ ERROR use of mutable static is unsafe
+    //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
     let xb = XB; //~ ERROR use of mutable static is unsafe
     let xrb = &XB; //~ ERROR use of mutable static is unsafe
+    //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
 }
diff --git a/tests/ui/static/safe-extern-statics-mut.stderr b/tests/ui/static/safe-extern-statics-mut.stderr
index e390625f20a..eda353ce673 100644
--- a/tests/ui/static/safe-extern-statics-mut.stderr
+++ b/tests/ui/static/safe-extern-statics-mut.stderr
@@ -1,3 +1,32 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/safe-extern-statics-mut.rs:12:14
+   |
+LL |     let rb = &B;
+   |              ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let rb = addr_of!(B);
+   |              ~~~~~~~~~~~
+
+warning: shared reference of mutable static is discouraged
+  --> $DIR/safe-extern-statics-mut.rs:15:15
+   |
+LL |     let xrb = &XB;
+   |               ^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     let xrb = addr_of!(XB);
+   |               ~~~~~~~~~~~~
+
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/safe-extern-statics-mut.rs:11:13
    |
@@ -15,7 +44,7 @@ LL |     let rb = &B;
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/safe-extern-statics-mut.rs:13:14
+  --> $DIR/safe-extern-statics-mut.rs:14:14
    |
 LL |     let xb = XB;
    |              ^^ use of mutable static
@@ -23,13 +52,13 @@ LL |     let xb = XB;
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/safe-extern-statics-mut.rs:14:16
+  --> $DIR/safe-extern-statics-mut.rs:15:16
    |
 LL |     let xrb = &XB;
    |                ^^ use of mutable static
    |
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/statics/issue-15261.rs b/tests/ui/statics/issue-15261.rs
index ec413f6d1d2..14422329b7d 100644
--- a/tests/ui/statics/issue-15261.rs
+++ b/tests/ui/statics/issue-15261.rs
@@ -6,6 +6,7 @@
 
 static mut n_mut: usize = 0;
 
-static n: &'static usize = unsafe{ &n_mut };
+static n: &'static usize = unsafe { &n_mut };
+//~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
 
 fn main() {}
diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr
new file mode 100644
index 00000000000..72d88ce1b38
--- /dev/null
+++ b/tests/ui/statics/issue-15261.stderr
@@ -0,0 +1,17 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/issue-15261.rs:9:37
+   |
+LL | static n: &'static usize = unsafe { &n_mut };
+   |                                     ^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL | static n: &'static usize = unsafe { addr_of!(n_mut) };
+   |                                     ~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/statics/static-mut-xc.rs b/tests/ui/statics/static-mut-xc.rs
index 1d172d26a59..2fc265e02ea 100644
--- a/tests/ui/statics/static-mut-xc.rs
+++ b/tests/ui/statics/static-mut-xc.rs
@@ -7,7 +7,6 @@
 
 // aux-build:static_mut_xc.rs
 
-
 extern crate static_mut_xc;
 
 unsafe fn static_bound(_: &'static isize) {}
@@ -27,7 +26,9 @@ unsafe fn run() {
     static_mut_xc::a = -3;
     assert_eq!(static_mut_xc::a, -3);
     static_bound(&static_mut_xc::a);
+    //~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
     static_bound_set(&mut static_mut_xc::a);
+    //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
 }
 
 pub fn main() {
diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr
new file mode 100644
index 00000000000..37aa336bc50
--- /dev/null
+++ b/tests/ui/statics/static-mut-xc.stderr
@@ -0,0 +1,31 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:28:18
+   |
+LL |     static_bound(&static_mut_xc::a);
+   |                  ^^^^^^^^^^^^^^^^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL |     static_bound(addr_of!(static_mut_xc::a));
+   |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:30:22
+   |
+LL |     static_bound_set(&mut static_mut_xc::a);
+   |                      ^^^^^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     static_bound_set(addr_of_mut!(static_mut_xc::a));
+   |                      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/statics/static-recursive.rs b/tests/ui/statics/static-recursive.rs
index 95dadc81f81..216beb0206d 100644
--- a/tests/ui/statics/static-recursive.rs
+++ b/tests/ui/statics/static-recursive.rs
@@ -1,36 +1,43 @@
 // run-pass
+
 static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
+//~^ WARN shared reference of mutable static is discouraged [static_mut_ref]
 
 struct StaticDoubleLinked {
     prev: &'static StaticDoubleLinked,
     next: &'static StaticDoubleLinked,
     data: i32,
-    head: bool
+    head: bool,
 }
 
-static L1: StaticDoubleLinked = StaticDoubleLinked{prev: &L3, next: &L2, data: 1, head: true};
-static L2: StaticDoubleLinked = StaticDoubleLinked{prev: &L1, next: &L3, data: 2, head: false};
-static L3: StaticDoubleLinked = StaticDoubleLinked{prev: &L2, next: &L1, data: 3, head: false};
-
+static L1: StaticDoubleLinked = StaticDoubleLinked { prev: &L3, next: &L2, data: 1, head: true };
+static L2: StaticDoubleLinked = StaticDoubleLinked { prev: &L1, next: &L3, data: 2, head: false };
+static L3: StaticDoubleLinked = StaticDoubleLinked { prev: &L2, next: &L1, data: 3, head: false };
 
 pub fn main() {
-    unsafe { assert_eq!(S, *(S as *const *const u8)); }
+    unsafe {
+        assert_eq!(S, *(S as *const *const u8));
+    }
 
     let mut test_vec = Vec::new();
     let mut cur = &L1;
     loop {
         test_vec.push(cur.data);
         cur = cur.next;
-        if cur.head { break }
+        if cur.head {
+            break;
+        }
     }
-    assert_eq!(&test_vec, &[1,2,3]);
+    assert_eq!(&test_vec, &[1, 2, 3]);
 
     let mut test_vec = Vec::new();
     let mut cur = &L1;
     loop {
         cur = cur.prev;
         test_vec.push(cur.data);
-        if cur.head { break }
+        if cur.head {
+            break;
+        }
     }
-    assert_eq!(&test_vec, &[3,2,1]);
+    assert_eq!(&test_vec, &[3, 2, 1]);
 }
diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr
new file mode 100644
index 00000000000..15888e5c68d
--- /dev/null
+++ b/tests/ui/statics/static-recursive.stderr
@@ -0,0 +1,17 @@
+warning: shared reference of mutable static is discouraged
+  --> $DIR/static-recursive.rs:3:36
+   |
+LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
+   |                                    ^^ shared reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: shared references are dangerous since if there's any kind of mutation of that static while the reference lives, that's UB; use `addr_of!` instead to create a raw pointer
+   |
+LL | static mut S: *const u8 = unsafe { addr_of!(S) as *const *const u8 as *const u8 };
+   |                                    ~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/thread-local/thread-local-static.rs b/tests/ui/thread-local/thread-local-static.rs
index e6cd4839dda..f5fb0984897 100644
--- a/tests/ui/thread-local/thread-local-static.rs
+++ b/tests/ui/thread-local/thread-local-static.rs
@@ -8,7 +8,8 @@ static mut STATIC_VAR_2: [u32; 8] = [4; 8];
 const fn g(x: &mut [u32; 8]) {
     //~^ ERROR mutable references are not allowed
     std::mem::swap(x, &mut STATIC_VAR_2)
-    //~^ ERROR thread-local statics cannot be accessed
+    //~^ WARN mutable reference of mutable static is discouraged [static_mut_ref]
+    //~^^ ERROR thread-local statics cannot be accessed
     //~| ERROR mutable references are not allowed
     //~| ERROR use of mutable static is unsafe
     //~| constant functions cannot refer to statics
diff --git a/tests/ui/thread-local/thread-local-static.stderr b/tests/ui/thread-local/thread-local-static.stderr
index c1777dd60db..b03f4580c2c 100644
--- a/tests/ui/thread-local/thread-local-static.stderr
+++ b/tests/ui/thread-local/thread-local-static.stderr
@@ -1,3 +1,18 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/thread-local-static.rs:10:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     std::mem::swap(x, addr_of_mut!(STATIC_VAR_2))
+   |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/thread-local-static.rs:10:28
    |
@@ -38,7 +53,7 @@ LL |     std::mem::swap(x, &mut STATIC_VAR_2)
    = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
    = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0013, E0133, E0625, E0658.
 For more information about an error, try `rustc --explain E0013`.
diff --git a/tests/ui/thread-local/thread-local-static.thir.stderr b/tests/ui/thread-local/thread-local-static.thir.stderr
new file mode 100644
index 00000000000..2043b268c09
--- /dev/null
+++ b/tests/ui/thread-local/thread-local-static.thir.stderr
@@ -0,0 +1,59 @@
+warning: mutable reference of mutable static is discouraged
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ mutable reference of mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: reference of mutable static is a hard error from 2024 edition
+   = note: mutable statics can be written to by multiple threads: aliasing violations or data races will cause undefined behavior
+   = note: `#[warn(static_mut_ref)]` on by default
+help: mutable references are dangerous since if there's any other pointer or reference used for that static while the reference lives, that's UB; use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |     std::mem::swap(x, addr_of_mut!(STATIC_VAR_2))
+   |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:10:12
+   |
+LL | const fn g(x: &mut [u32; 8]) {
+   |            ^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0625]: thread-local statics cannot be accessed at compile-time
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+
+error[E0013]: constant functions cannot refer to statics
+  --> $DIR/thread-local-static.rs:12:28
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                            ^^^^^^^^^^^^
+   |
+   = help: consider extracting the value of the `static` to a `const`, and referring to that
+
+error[E0658]: mutable references are not allowed in constant functions
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+   = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0133]: use of mutable static is unsafe and requires unsafe function or block
+  --> $DIR/thread-local-static.rs:12:23
+   |
+LL |     std::mem::swap(x, &mut STATIC_VAR_2)
+   |                       ^^^^^^^^^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0013, E0133, E0625, E0658.
+For more information about an error, try `rustc --explain E0013`.