about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock14
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs10
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs2
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs5
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs25
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs45
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs72
-rw-r--r--compiler/rustc_interface/messages.ftl2
-rw-r--r--compiler/rustc_interface/src/passes.rs3
-rw-r--r--compiler/rustc_llvm/Cargo.toml3
-rw-r--r--compiler/rustc_metadata/messages.ftl7
-rw-r--r--compiler/rustc_metadata/src/creader.rs4
-rw-r--r--compiler/rustc_metadata/src/dependency_format.rs47
-rw-r--r--compiler/rustc_metadata/src/errors.rs10
-rw-r--r--compiler/rustc_middle/src/middle/lang_items.rs1
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs8
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs3
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs9
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs3
-rw-r--r--compiler/rustc_session/src/config.rs9
-rw-r--r--compiler/rustc_session/src/config/cfg.rs11
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_session/src/session.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs6
-rw-r--r--compiler/rustc_thread_pool/src/latch.rs8
-rw-r--r--compiler/rustc_windows_rc/Cargo.toml4
-rw-r--r--compiler/rustc_windows_rc/src/lib.rs34
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/alloc/src/alloc.rs4
-rw-r--r--library/alloc/src/raw_vec/mod.rs2
-rw-r--r--library/alloc/src/vec/mod.rs8
-rw-r--r--library/core/Cargo.toml2
-rw-r--r--library/core/src/cell.rs4
-rw-r--r--library/core/src/iter/adapters/flatten.rs2
-rw-r--r--library/core/src/num/mod.rs4
-rw-r--r--library/core/src/option.rs8
-rw-r--r--library/core/src/panicking.rs83
-rw-r--r--library/core/src/result.rs4
-rw-r--r--library/core/src/slice/index.rs4
-rw-r--r--library/core/src/slice/mod.rs4
-rw-r--r--library/core/src/slice/sort/shared/smallsort.rs4
-rw-r--r--library/core/src/str/mod.rs4
-rw-r--r--library/std/Cargo.toml5
-rw-r--r--library/std/src/io/mod.rs2
-rw-r--r--library/std/src/panicking.rs26
-rw-r--r--library/std/src/rt.rs4
-rw-r--r--library/std/src/thread/local.rs2
-rw-r--r--library/sysroot/Cargo.toml1
-rw-r--r--src/doc/rustc/src/codegen-options/index.md2
-rw-r--r--src/doc/rustc/src/linker-plugin-lto.md7
-rw-r--r--src/librustdoc/html/static/js/main.js25
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/compiletest/src/directives.rs19
-rw-r--r--src/tools/compiletest/src/directives/directive_names.rs1
-rw-r--r--src/tools/compiletest/src/runtest.rs22
-rw-r--r--src/tools/tidy/src/deps.rs1
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml12
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs65
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs46
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml4
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs1
-rw-r--r--tests/run-make-cargo/panic-immediate-abort-works/rmake.rs39
-rw-r--r--tests/run-make/crate-loading/dep-2-reexport.rs (renamed from tests/run-make/crate-loading/multiple-dep-versions-3.rs)0
-rw-r--r--tests/run-make/crate-loading/dependency-1.rs (renamed from tests/run-make/crate-loading/multiple-dep-versions-1.rs)0
-rw-r--r--tests/run-make/crate-loading/dependency-2.rs (renamed from tests/run-make/crate-loading/multiple-dep-versions-2.rs)0
-rw-r--r--tests/run-make/crate-loading/rmake.rs9
-rw-r--r--tests/rustdoc/reexport/private-mod-override-reexport.rs13
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.cargo.stderr2
-rw-r--r--tests/ui/check-cfg/report-in-external-macros.rustc.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg4
-rw-r--r--tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg4
-rw-r--r--tests/ui/diagnostic-flags/colored-session-opt-error.svg4
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.rs4
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.stderr11
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.svg48
-rw-r--r--tests/ui/diagnostic-flags/terminal_urls.windows.svg49
-rw-r--r--tests/ui/error-emitter/E0308-clarification.svg2
-rw-r--r--tests/ui/error-emitter/highlighting.svg2
-rw-r--r--tests/ui/error-emitter/highlighting.windows.svg2
-rw-r--r--tests/ui/error-emitter/multiline-multipart-suggestion.svg2
-rw-r--r--tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg2
-rw-r--r--tests/ui/error-emitter/multiline-removal-suggestion.svg4
-rw-r--r--tests/ui/error-emitter/unicode-output.svg2
-rw-r--r--tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg4
-rw-r--r--tests/ui/iterators/issue-58952-filter-type-length.rs2
-rw-r--r--tests/ui/panic-runtime/auxiliary/needs-abort.rs2
-rw-r--r--tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs7
-rw-r--r--tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs18
-rw-r--r--tests/ui/panic-runtime/bad-panic-flag1.rs2
-rw-r--r--tests/ui/panic-runtime/bad-panic-flag1.stderr2
-rw-r--r--tests/ui/panic-runtime/bad-panic-flag2.rs2
-rw-r--r--tests/ui/panic-runtime/bad-panic-flag2.stderr2
-rw-r--r--tests/ui/panic-runtime/immediate-abort-default-sysroot.rs15
-rw-r--r--tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr4
-rw-r--r--tests/ui/panic-runtime/need-abort-got-immediate-abort.rs21
-rw-r--r--tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr4
-rw-r--r--tests/ui/panic-runtime/need-immediate-abort-got-abort.rs20
-rw-r--r--tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr4
-rw-r--r--tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs20
-rw-r--r--tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr4
-rw-r--r--tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs21
-rw-r--r--tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr4
-rw-r--r--tests/ui/proc-macro/panic-abort.rs2
-rw-r--r--tests/ui/proc-macro/panic-abort.stderr2
-rw-r--r--tests/ui/suggestions/incorrect-variant-literal.svg2
-rw-r--r--tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs2
113 files changed, 823 insertions, 326 deletions
diff --git a/Cargo.lock b/Cargo.lock
index c2e635b4cfe..3d4a1bf6a78 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -128,9 +128,9 @@ dependencies = [
 
 [[package]]
 name = "anstyle-svg"
-version = "0.1.10"
+version = "0.1.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc03a770ef506fe1396c0e476120ac0e6523cf14b74218dd5f18cd6833326fa9"
+checksum = "26b9ec8c976eada1b0f9747a3d7cc4eae3bef10613e443746e7487f26c872fde"
 dependencies = [
  "anstyle",
  "anstyle-lossy",
@@ -1333,6 +1333,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "find-msvc-tools"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1ced73b1dacfc750a6db6c0a0c3a3853c8b41997e2e2c563dc90804ae6867959"
+
+[[package]]
 name = "flate2"
 version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3556,7 +3562,7 @@ dependencies = [
  "ar_archive_writer",
  "bitflags",
  "bstr",
- "cc",
+ "find-msvc-tools",
  "itertools",
  "libc",
  "object 0.37.3",
@@ -4760,7 +4766,7 @@ dependencies = [
 name = "rustc_windows_rc"
 version = "0.0.0"
 dependencies = [
- "cc",
+ "find-msvc-tools",
 ]
 
 [[package]]
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 51089e5a1d3..82c59d5a3a2 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -63,8 +63,8 @@ pub fn inject(
 
     if sess.is_test_crate() {
         let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) {
-            (PanicStrategy::Abort, true) => PanicStrategy::Abort,
-            (PanicStrategy::Abort, false) => {
+            (PanicStrategy::Abort | PanicStrategy::ImmediateAbort, true) => panic_strategy,
+            (PanicStrategy::Abort | PanicStrategy::ImmediateAbort, false) => {
                 if panic_strategy == platform_panic_strategy {
                     // Silently allow compiling with panic=abort on these platforms,
                     // but with old behavior (abort if a test fails).
@@ -287,10 +287,8 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> Box<ast::Item> {
     let ecx = &cx.ext_cx;
     let test_ident = Ident::new(sym::test, sp);
 
-    let runner_name = match cx.panic_strategy {
-        PanicStrategy::Unwind => "test_main_static",
-        PanicStrategy::Abort => "test_main_static_abort",
-    };
+    let runner_name =
+        if cx.panic_strategy.unwinds() { "test_main_static" } else { "test_main_static_abort" };
 
     // test::test_main_static(...)
     let mut test_runner = cx.test_runner.clone().unwrap_or_else(|| {
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index e9d72e457a0..e8672f49580 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -15,9 +15,9 @@ use rustc_middle::mir::mono::Visibility;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
+use rustc_target::spec::RelocModel;
 #[cfg(feature = "master")]
 use rustc_target::spec::SymbolVisibility;
-use rustc_target::spec::{PanicStrategy, RelocModel};
 
 use crate::builder::Builder;
 use crate::context::CodegenCx;
@@ -101,7 +101,7 @@ pub fn compile_codegen_unit(
         // Instantiate monomorphizations without filling out definitions yet...
         let context = new_context(tcx);
 
-        if tcx.sess.panic_strategy() == PanicStrategy::Unwind {
+        if tcx.sess.panic_strategy().unwinds() {
             context.add_command_line_option("-fexceptions");
             context.add_driver_option("-fexceptions");
         }
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 84fa56cf903..a915f5d6418 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -29,7 +29,6 @@ use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::{Span, Symbol, sym};
 use rustc_target::callconv::{ArgAbi, PassMode};
-use rustc_target::spec::PanicStrategy;
 
 #[cfg(feature = "master")]
 use crate::abi::FnAbiGccExt;
@@ -1334,7 +1333,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
     _catch_func: RValue<'gcc>,
     dest: PlaceRef<'tcx, RValue<'gcc>>,
 ) {
-    if bx.sess().panic_strategy() == PanicStrategy::Abort {
+    if !bx.sess().panic_strategy().unwinds() {
         bx.call(bx.type_void(), None, None, try_func, &[data], None, None);
         // Return 0 unconditionally from the intrinsic call;
         // we can never unwind.
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index e7f4a357048..50398a32142 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -18,7 +18,6 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{Span, Symbol, sym};
 use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate};
 use rustc_target::callconv::PassMode;
-use rustc_target::spec::PanicStrategy;
 use tracing::debug;
 
 use crate::abi::FnAbiLlvmExt;
@@ -674,7 +673,7 @@ fn catch_unwind_intrinsic<'ll, 'tcx>(
     catch_func: &'ll Value,
     dest: PlaceRef<'tcx, &'ll Value>,
 ) {
-    if bx.sess().panic_strategy() == PanicStrategy::Abort {
+    if !bx.sess().panic_strategy().unwinds() {
         let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void());
         bx.call(try_func_ty, None, None, try_func, &[data], None, None);
         // Return 0 unconditionally from the intrinsic call;
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 45c5c9aa551..3b920168e06 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -106,7 +106,7 @@ unsafe fn configure_llvm(sess: &Session) {
 
         if sess.target.os == "emscripten"
             && !sess.opts.unstable_opts.emscripten_wasm_eh
-            && sess.panic_strategy() == PanicStrategy::Unwind
+            && sess.panic_strategy().unwinds()
         {
             add("-enable-emscripten-cxx-exceptions", false);
         }
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 5462163f4ff..9c5a3d839ce 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -8,9 +8,7 @@ edition = "2024"
 ar_archive_writer = "0.5"
 bitflags = "2.4.1"
 bstr = "1.11.3"
-# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
-# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_windows_rc`.
-cc = "=1.2.16"
+find-msvc-tools = "0.1.2"
 itertools = "0.12"
 pathdiff = "0.2.0"
 regex = "1.4"
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index 48b01ea2df1..d6c304c1b14 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -9,7 +9,7 @@ use std::path::{Path, PathBuf};
 use std::process::{Output, Stdio};
 use std::{env, fmt, fs, io, mem, str};
 
-use cc::windows_registry;
+use find_msvc_tools;
 use itertools::Itertools;
 use regex::Regex;
 use rustc_arena::TypedArena;
@@ -47,8 +47,8 @@ use rustc_span::Symbol;
 use rustc_target::spec::crt_objects::CrtObjects;
 use rustc_target::spec::{
     BinaryFormat, Cc, LinkOutputKind, LinkSelfContainedComponents, LinkSelfContainedDefault,
-    LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, PanicStrategy, RelocModel, RelroLevel,
-    SanitizerSet, SplitDebuginfo,
+    LinkerFeatures, LinkerFlavor, LinkerFlavorCli, Lld, RelocModel, RelroLevel, SanitizerSet,
+    SplitDebuginfo,
 };
 use tracing::{debug, info, warn};
 
@@ -877,9 +877,9 @@ fn link_natively(
                     // All Microsoft `link.exe` linking ror codes are
                     // four digit numbers in the range 1000 to 9999 inclusive
                     if is_msvc_link_exe && (code < 1000 || code > 9999) {
-                        let is_vs_installed = windows_registry::find_vs_version().is_ok();
+                        let is_vs_installed = find_msvc_tools::find_vs_version().is_ok();
                         let has_linker =
-                            windows_registry::find_tool(&sess.target.arch, "link.exe").is_some();
+                            find_msvc_tools::find_tool(&sess.target.arch, "link.exe").is_some();
 
                         sess.dcx().emit_note(errors::LinkExeUnexpectedError);
 
@@ -2512,10 +2512,10 @@ fn add_order_independent_options(
     if sess.target.os == "emscripten" {
         cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh {
             "-fwasm-exceptions"
-        } else if sess.panic_strategy() == PanicStrategy::Abort {
-            "-sDISABLE_EXCEPTION_CATCHING=1"
-        } else {
+        } else if sess.panic_strategy().unwinds() {
             "-sDISABLE_EXCEPTION_CATCHING=0"
+        } else {
+            "-sDISABLE_EXCEPTION_CATCHING=1"
         });
     }
 
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index b90be2faa08..624ab1b5084 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -4,7 +4,7 @@ use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 use std::{env, io, iter, mem, str};
 
-use cc::windows_registry;
+use find_msvc_tools;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_metadata::{
     find_native_static_library, try_find_native_dynamic_library, try_find_native_static_library,
@@ -53,7 +53,7 @@ pub(crate) fn get_linker<'a>(
     self_contained: bool,
     target_cpu: &'a str,
 ) -> Box<dyn Linker + 'a> {
-    let msvc_tool = windows_registry::find_tool(&sess.target.arch, "link.exe");
+    let msvc_tool = find_msvc_tools::find_tool(&sess.target.arch, "link.exe");
 
     // If our linker looks like a batch script on Windows then to execute this
     // we'll need to spawn `cmd` explicitly. This is primarily done to handle
@@ -117,7 +117,6 @@ pub(crate) fn get_linker<'a>(
     if sess.target.is_like_msvc
         && let Some(ref tool) = msvc_tool
     {
-        cmd.args(tool.args());
         for (k, v) in tool.env() {
             if k == "PATH" {
                 new_path.extend(env::split_paths(v));
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index d2b275ad20a..70d796cda11 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -5,7 +5,7 @@ use rustc_ast_pretty::pprust;
 use rustc_errors::{Applicability, PResult};
 use rustc_macros::{Decodable, Encodable};
 use rustc_session::parse::ParseSess;
-use rustc_span::{Ident, Span, Symbol};
+use rustc_span::{Ident, Span, Symbol, sym};
 
 use crate::errors;
 
@@ -69,15 +69,15 @@ impl MetaVarExpr {
         }
 
         let mut iter = args.iter();
-        let rslt = match ident.as_str() {
-            "concat" => parse_concat(&mut iter, psess, outer_span, ident.span)?,
-            "count" => parse_count(&mut iter, psess, ident.span)?,
-            "ignore" => {
+        let rslt = match ident.name {
+            sym::concat => parse_concat(&mut iter, psess, outer_span, ident.span)?,
+            sym::count => parse_count(&mut iter, psess, ident.span)?,
+            sym::ignore => {
                 eat_dollar(&mut iter, psess, ident.span)?;
                 MetaVarExpr::Ignore(parse_ident(&mut iter, psess, ident.span)?)
             }
-            "index" => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?),
-            "len" => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?),
+            sym::index => MetaVarExpr::Index(parse_depth(&mut iter, psess, ident.span)?),
+            sym::len => MetaVarExpr::Len(parse_depth(&mut iter, psess, ident.span)?),
             _ => {
                 let err = errors::MveUnrecognizedExpr {
                     span: ident.span,
@@ -119,14 +119,13 @@ fn check_trailing_tokens<'psess>(
     }
 
     // `None` for max indicates the arg count must be exact, `Some` indicates a range is accepted.
-    let (min_or_exact_args, max_args) = match ident.as_str() {
-        "concat" => panic!("concat takes unlimited tokens but didn't eat them all"),
-        "ignore" => (1, None),
+    let (min_or_exact_args, max_args) = match ident.name {
+        sym::concat => panic!("concat takes unlimited tokens but didn't eat them all"),
+        sym::ignore => (1, None),
         // 1 or 2 args
-        "count" => (1, Some(2)),
+        sym::count => (1, Some(2)),
         // 0 or 1 arg
-        "index" => (0, Some(1)),
-        "len" => (0, Some(1)),
+        sym::index | sym::len => (0, Some(1)),
         other => unreachable!("unknown MVEs should be rejected earlier (got `{other}`)"),
     };
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index 6a3f1f62c91..dddd62a4945 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -375,6 +375,19 @@ fn transcribe_metavar<'tx>(
         return Ok(());
     };
 
+    let MatchedSingle(pnr) = cur_matched else {
+        // We were unable to descend far enough. This is an error.
+        return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident }));
+    };
+
+    transcribe_pnr(tscx, sp, pnr)
+}
+
+fn transcribe_pnr<'tx>(
+    tscx: &mut TranscrCtx<'tx, '_>,
+    mut sp: Span,
+    pnr: &ParseNtResult,
+) -> PResult<'tx, ()> {
     // We wrap the tokens in invisible delimiters, unless they are already wrapped
     // in invisible delimiters with the same `MetaVarKind`. Because some proc
     // macros can't handle multiple layers of invisible delimiters of the same
@@ -404,33 +417,33 @@ fn transcribe_metavar<'tx>(
         )
     };
 
-    let tt = match cur_matched {
-        MatchedSingle(ParseNtResult::Tt(tt)) => {
+    let tt = match pnr {
+        ParseNtResult::Tt(tt) => {
             // `tt`s are emitted into the output stream directly as "raw tokens",
             // without wrapping them into groups. Other variables are emitted into
             // the output stream as groups with `Delimiter::Invisible` to maintain
             // parsing priorities.
             maybe_use_metavar_location(tscx.psess, &tscx.stack, sp, tt, &mut tscx.marker)
         }
-        MatchedSingle(ParseNtResult::Ident(ident, is_raw)) => {
+        ParseNtResult::Ident(ident, is_raw) => {
             tscx.marker.mark_span(&mut sp);
             with_metavar_spans(|mspans| mspans.insert(ident.span, sp));
             let kind = token::NtIdent(*ident, *is_raw);
             TokenTree::token_alone(kind, sp)
         }
-        MatchedSingle(ParseNtResult::Lifetime(ident, is_raw)) => {
+        ParseNtResult::Lifetime(ident, is_raw) => {
             tscx.marker.mark_span(&mut sp);
             with_metavar_spans(|mspans| mspans.insert(ident.span, sp));
             let kind = token::NtLifetime(*ident, *is_raw);
             TokenTree::token_alone(kind, sp)
         }
-        MatchedSingle(ParseNtResult::Item(item)) => {
+        ParseNtResult::Item(item) => {
             mk_delimited(item.span, MetaVarKind::Item, TokenStream::from_ast(item))
         }
-        MatchedSingle(ParseNtResult::Block(block)) => {
+        ParseNtResult::Block(block) => {
             mk_delimited(block.span, MetaVarKind::Block, TokenStream::from_ast(block))
         }
-        MatchedSingle(ParseNtResult::Stmt(stmt)) => {
+        ParseNtResult::Stmt(stmt) => {
             let stream = if let StmtKind::Empty = stmt.kind {
                 // FIXME: Properly collect tokens for empty statements.
                 TokenStream::token_alone(token::Semi, stmt.span)
@@ -439,10 +452,10 @@ fn transcribe_metavar<'tx>(
             };
             mk_delimited(stmt.span, MetaVarKind::Stmt, stream)
         }
-        MatchedSingle(ParseNtResult::Pat(pat, pat_kind)) => {
+        ParseNtResult::Pat(pat, pat_kind) => {
             mk_delimited(pat.span, MetaVarKind::Pat(*pat_kind), TokenStream::from_ast(pat))
         }
-        MatchedSingle(ParseNtResult::Expr(expr, kind)) => {
+        ParseNtResult::Expr(expr, kind) => {
             let (can_begin_literal_maybe_minus, can_begin_string_literal) = match &expr.kind {
                 ExprKind::Lit(_) => (true, true),
                 ExprKind::Unary(UnOp::Neg, e) if matches!(&e.kind, ExprKind::Lit(_)) => {
@@ -460,14 +473,14 @@ fn transcribe_metavar<'tx>(
                 TokenStream::from_ast(expr),
             )
         }
-        MatchedSingle(ParseNtResult::Literal(lit)) => {
+        ParseNtResult::Literal(lit) => {
             mk_delimited(lit.span, MetaVarKind::Literal, TokenStream::from_ast(lit))
         }
-        MatchedSingle(ParseNtResult::Ty(ty)) => {
+        ParseNtResult::Ty(ty) => {
             let is_path = matches!(&ty.kind, TyKind::Path(None, _path));
             mk_delimited(ty.span, MetaVarKind::Ty { is_path }, TokenStream::from_ast(ty))
         }
-        MatchedSingle(ParseNtResult::Meta(attr_item)) => {
+        ParseNtResult::Meta(attr_item) => {
             let has_meta_form = attr_item.meta_kind().is_some();
             mk_delimited(
                 attr_item.span(),
@@ -475,16 +488,12 @@ fn transcribe_metavar<'tx>(
                 TokenStream::from_ast(attr_item),
             )
         }
-        MatchedSingle(ParseNtResult::Path(path)) => {
+        ParseNtResult::Path(path) => {
             mk_delimited(path.span, MetaVarKind::Path, TokenStream::from_ast(path))
         }
-        MatchedSingle(ParseNtResult::Vis(vis)) => {
+        ParseNtResult::Vis(vis) => {
             mk_delimited(vis.span, MetaVarKind::Vis, TokenStream::from_ast(vis))
         }
-        MatchedSeq(..) => {
-            // We were unable to descend far enough. This is an error.
-            return Err(dcx.create_err(MacroVarStillRepeating { span: sp, ident }));
-        }
     };
 
     tscx.result.push(tt);
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index f735c0a4160..46accb76a18 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -47,7 +47,7 @@ You can read more about trait objects in the Trait Objects section of the Refere
 https://doc.rust-lang.org/reference/types.html#trait-objects";
 
 fn is_number(text: &str) -> bool {
-    text.chars().all(|c: char| c.is_digit(10))
+    text.chars().all(|c: char| c.is_ascii_digit())
 }
 
 /// Information about the expected type at the top level of type checking a pattern.
@@ -262,8 +262,9 @@ enum InheritedRefMatchRule {
         /// pattern matches a given type:
         /// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
         /// - If the underlying type is a reference, a reference pattern matches if it can eat either one
-        ///    of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
-        ///    underlying type is `&mut` or the inherited reference is `&mut`.
+        ///   of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
+        ///   underlying type is `&mut` or the inherited reference is `&mut`.
+        ///
         /// If `false`, a reference pattern is only matched against the underlying type.
         /// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
         /// `ref_pat_eat_one_layer_2024_structural` feature gates.
@@ -1069,7 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 {
                     if !self.tcx.features().mut_ref() {
                         feature_err(
-                            &self.tcx.sess,
+                            self.tcx.sess,
                             sym::mut_ref,
                             pat.span.until(ident.span),
                             "binding cannot be both mutable and by-reference",
@@ -1487,31 +1488,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         opt_def_id: Option<hir::def_id::DefId>,
         ident: Ident,
     ) -> bool {
-        match opt_def_id {
-            Some(def_id) => match self.tcx.hir_get_if_local(def_id) {
-                Some(hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Const(_, _, _, body_id),
-                    ..
-                })) => match self.tcx.hir_node(body_id.hir_id) {
-                    hir::Node::Expr(expr) => {
-                        if hir::is_range_literal(expr) {
-                            let span = self.tcx.hir_span(body_id.hir_id);
-                            if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
-                                e.span_suggestion_verbose(
-                                    ident.span,
-                                    "you may want to move the range into the match block",
-                                    snip,
-                                    Applicability::MachineApplicable,
-                                );
-                                return true;
-                            }
-                        }
-                    }
-                    _ => (),
-                },
-                _ => (),
-            },
-            _ => (),
+        if let Some(def_id) = opt_def_id
+            && let Some(hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Const(_, _, _, body_id),
+                ..
+            })) = self.tcx.hir_get_if_local(def_id)
+            && let hir::Node::Expr(expr) = self.tcx.hir_node(body_id.hir_id)
+            && hir::is_range_literal(expr)
+        {
+            let span = self.tcx.hir_span(body_id.hir_id);
+            if let Ok(snip) = self.tcx.sess.source_map().span_to_snippet(span) {
+                e.span_suggestion_verbose(
+                    ident.span,
+                    "you may want to move the range into the match block",
+                    snip,
+                    Applicability::MachineApplicable,
+                );
+                return true;
+            }
         }
         false
     }
@@ -1529,7 +1523,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         if let Some(span) = self.tcx.hir_res_span(pat_res) {
             e.span_label(span, format!("{} defined here", res.descr()));
-            if let [hir::PathSegment { ident, .. }] = &*segments {
+            if let [hir::PathSegment { ident, .. }] = segments {
                 e.span_label(
                     pat_span,
                     format!(
@@ -1557,17 +1551,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             _ => (None, None),
                         };
 
-                        let is_range = match type_def_id.and_then(|id| self.tcx.as_lang_item(id)) {
+                        let is_range = matches!(
+                            type_def_id.and_then(|id| self.tcx.as_lang_item(id)),
                             Some(
                                 LangItem::Range
-                                | LangItem::RangeFrom
-                                | LangItem::RangeTo
-                                | LangItem::RangeFull
-                                | LangItem::RangeInclusiveStruct
-                                | LangItem::RangeToInclusive,
-                            ) => true,
-                            _ => false,
-                        };
+                                    | LangItem::RangeFrom
+                                    | LangItem::RangeTo
+                                    | LangItem::RangeFull
+                                    | LangItem::RangeInclusiveStruct
+                                    | LangItem::RangeToInclusive,
+                            )
+                        );
                         if is_range {
                             if !self.maybe_suggest_range_literal(&mut e, item_def_id, *ident) {
                                 let msg = "constants only support matching by type, \
diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl
index 6f6666f8c76..1f5c5e74d97 100644
--- a/compiler/rustc_interface/messages.ftl
+++ b/compiler/rustc_interface/messages.ftl
@@ -47,7 +47,7 @@ interface_out_dir_error =
     failed to find or create the directory specified by `--out-dir`
 
 interface_proc_macro_crate_panic_abort =
-    building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+    building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
 
 interface_temps_dir_error =
     failed to find or create the directory specified by `--temps-dir`
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 6cefe887530..761a5c80918 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -42,7 +42,6 @@ use rustc_span::{
     DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, SourceFileHash, SourceFileHashAlgorithm, Span,
     Symbol, sym,
 };
-use rustc_target::spec::PanicStrategy;
 use rustc_trait_selection::{solve, traits};
 use tracing::{info, instrument};
 
@@ -282,7 +281,7 @@ fn configure_and_expand(
         feature_err(sess, sym::export_stable, DUMMY_SP, "`sdylib` crate type is unstable").emit();
     }
 
-    if is_proc_macro_crate && sess.panic_strategy() == PanicStrategy::Abort {
+    if is_proc_macro_crate && !sess.panic_strategy().unwinds() {
         sess.dcx().emit_warn(errors::ProcMacroCratePanicAbort);
     }
 
diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml
index 0dfd1b13df5..ad93c745381 100644
--- a/compiler/rustc_llvm/Cargo.toml
+++ b/compiler/rustc_llvm/Cargo.toml
@@ -10,8 +10,7 @@ libc = "0.2.73"
 
 [build-dependencies]
 # tidy-alphabetical-start
-# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
-# per crate", so if you change this, you need to also change it in `rustc_codegen_ssa` and `rustc_windows_rc`.
+# `cc` updates often break things, so we pin it here.
 cc = "=1.2.16"
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index e104be2c466..e624bfc5b8b 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -98,6 +98,13 @@ metadata_full_metadata_not_found =
 metadata_global_alloc_required =
     no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
 
+metadata_incompatible_with_immediate_abort =
+    the crate `{$crate_name}` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+metadata_incompatible_with_immediate_abort_core =
+    the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
+    .help = consider building the standard library from source with `cargo build -Zbuild-std`
+
 metadata_incompatible_panic_in_drop_strategy =
     the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
 
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index 9e23da88f5e..7650acbd292 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -1027,6 +1027,10 @@ impl CStore {
         let name = match desired_strategy {
             PanicStrategy::Unwind => sym::panic_unwind,
             PanicStrategy::Abort => sym::panic_abort,
+            PanicStrategy::ImmediateAbort => {
+                // Immediate-aborting panics don't use a runtime.
+                return;
+            }
         };
         info!("panic runtime not found -- loading {}", name);
 
diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs
index fb9c2e23b71..8054a48d37a 100644
--- a/compiler/rustc_metadata/src/dependency_format.rs
+++ b/compiler/rustc_metadata/src/dependency_format.rs
@@ -61,11 +61,13 @@ use rustc_session::config::CrateType;
 use rustc_session::cstore::CrateDepKind;
 use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
 use rustc_span::sym;
+use rustc_target::spec::PanicStrategy;
 use tracing::info;
 
 use crate::creader::CStore;
 use crate::errors::{
-    BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
+    BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy,
+    IncompatibleWithImmediateAbort, IncompatibleWithImmediateAbortCore, LibRequired,
     NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired,
     TwoPanicRuntimes,
 };
@@ -402,15 +404,43 @@ fn activate_injected_dep(
 /// there's only going to be one panic runtime in the output.
 fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
     let sess = &tcx.sess;
+    let list: Vec<_> = list
+        .iter_enumerated()
+        .filter_map(
+            |(cnum, linkage)| if *linkage == Linkage::NotLinked { None } else { Some(cnum) },
+        )
+        .collect();
     if list.is_empty() {
         return;
     }
-    let mut panic_runtime = None;
-    for (cnum, linkage) in list.iter_enumerated() {
-        if let Linkage::NotLinked = *linkage {
-            continue;
+    let desired_strategy = sess.panic_strategy();
+
+    // If we are panic=immediate-abort, make sure everything in the dependency tree has also been
+    // compiled with immediate-abort.
+    if list
+        .iter()
+        .any(|cnum| tcx.required_panic_strategy(*cnum) == Some(PanicStrategy::ImmediateAbort))
+    {
+        let mut invalid_crates = Vec::new();
+        for cnum in list.iter().copied() {
+            if tcx.required_panic_strategy(cnum) != Some(PanicStrategy::ImmediateAbort) {
+                invalid_crates.push(cnum);
+                // If core is incompatible, it's very likely that we'd emit an error for every
+                // sysroot crate, so instead of doing that emit a single fatal error that suggests
+                // using build-std.
+                if tcx.crate_name(cnum) == sym::core {
+                    sess.dcx().emit_fatal(IncompatibleWithImmediateAbortCore);
+                }
+            }
         }
+        for cnum in invalid_crates {
+            sess.dcx()
+                .emit_err(IncompatibleWithImmediateAbort { crate_name: tcx.crate_name(cnum) });
+        }
+    }
 
+    let mut panic_runtime = None;
+    for cnum in list.iter().copied() {
         if tcx.is_panic_runtime(cnum) {
             if let Some((prev, _)) = panic_runtime {
                 let prev_name = tcx.crate_name(prev);
@@ -430,8 +460,6 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
     // only one, but we perform validation here that all the panic strategy
     // compilation modes for the whole DAG are valid.
     if let Some((runtime_cnum, found_strategy)) = panic_runtime {
-        let desired_strategy = sess.panic_strategy();
-
         // First up, validate that our selected panic runtime is indeed exactly
         // our same strategy.
         if found_strategy != desired_strategy {
@@ -445,10 +473,7 @@ fn verify_ok(tcx: TyCtxt<'_>, list: &DependencyList) {
         // strategy. If the dep isn't linked, we ignore it, and if our strategy
         // is abort then it's compatible with everything. Otherwise all crates'
         // panic strategy must match our own.
-        for (cnum, linkage) in list.iter_enumerated() {
-            if let Linkage::NotLinked = *linkage {
-                continue;
-            }
+        for cnum in list.iter().copied() {
             if cnum == runtime_cnum || tcx.is_compiler_builtins(cnum) {
                 continue;
             }
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index e5a4fd48353..abfd078f746 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -76,6 +76,16 @@ pub struct RequiredPanicStrategy {
 }
 
 #[derive(Diagnostic)]
+#[diag(metadata_incompatible_with_immediate_abort)]
+pub struct IncompatibleWithImmediateAbort {
+    pub crate_name: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(metadata_incompatible_with_immediate_abort_core)]
+pub struct IncompatibleWithImmediateAbortCore;
+
+#[derive(Diagnostic)]
 #[diag(metadata_incompatible_panic_in_drop_strategy)]
 pub struct IncompatiblePanicInDropStrategy {
     pub crate_name: Symbol,
diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs
index 93264f02cc2..a0e4c288c4a 100644
--- a/compiler/rustc_middle/src/middle/lang_items.rs
+++ b/compiler/rustc_middle/src/middle/lang_items.rs
@@ -98,5 +98,6 @@ pub fn required(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool {
             lang_item != LangItem::EhPersonality && lang_item != LangItem::EhCatchTypeinfo
         }
         PanicStrategy::Unwind => true,
+        PanicStrategy::ImmediateAbort => false,
     }
 }
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index c477e65f5d6..47b45c58b9f 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -16,7 +16,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
 use rustc_session::config::OptLevel;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 use rustc_target::callconv::FnAbi;
-use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, PanicStrategy, Target, X86Abi};
+use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi};
 use tracing::debug;
 use {rustc_abi as abi, rustc_hir as hir};
 
@@ -1198,7 +1198,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
         //
         // Note that this is true regardless ABI specified on the function -- a `extern "C-unwind"`
         // function defined in Rust is also required to abort.
-        if tcx.sess.panic_strategy() == PanicStrategy::Abort && !tcx.is_foreign_item(did) {
+        if !tcx.sess.panic_strategy().unwinds() && !tcx.is_foreign_item(did) {
             return false;
         }
 
@@ -1206,7 +1206,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
         //
         // This is not part of `codegen_fn_attrs` as it can differ between crates
         // and therefore cannot be computed in core.
-        if tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Abort
+        if !tcx.sess.opts.unstable_opts.panic_in_drop.unwinds()
             && tcx.is_lang_item(did, LangItem::DropInPlace)
         {
             return false;
@@ -1245,7 +1245,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
         | RiscvInterruptS
         | RustInvalid
         | Unadjusted => false,
-        Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
+        Rust | RustCall | RustCold => tcx.sess.panic_strategy().unwinds(),
     }
 }
 
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index c1cd2788348..c5cd06f170c 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -86,7 +86,6 @@ use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::source_map::dummy_spanned;
 use rustc_span::symbol::sym;
 use rustc_span::{DUMMY_SP, Span};
-use rustc_target::spec::PanicStrategy;
 use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
 use rustc_trait_selection::infer::TyCtxtInferExt as _;
 use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt};
@@ -1149,7 +1148,7 @@ fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, typing_env: ty::Typing
 
 fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
     // Nothing can unwind when landing pads are off.
-    if tcx.sess.panic_strategy() == PanicStrategy::Abort {
+    if !tcx.sess.panic_strategy().unwinds() {
         return false;
     }
 
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index abbff1c48dd..7c66783548e 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -101,12 +101,15 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
 }
 
 fn required_panic_strategy(tcx: TyCtxt<'_>, _: LocalCrate) -> Option<PanicStrategy> {
+    let local_strategy = tcx.sess.panic_strategy();
+
     if tcx.is_panic_runtime(LOCAL_CRATE) {
-        return Some(tcx.sess.panic_strategy());
+        return Some(local_strategy);
     }
 
-    if tcx.sess.panic_strategy() == PanicStrategy::Abort {
-        return Some(PanicStrategy::Abort);
+    match local_strategy {
+        PanicStrategy::Abort | PanicStrategy::ImmediateAbort => return Some(local_strategy),
+        _ => {}
     }
 
     for def_id in tcx.hir_body_owners() {
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 5b6d7ffb511..b53c1f6d202 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -1,7 +1,6 @@
 use rustc_index::bit_set::DenseBitSet;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
-use rustc_target::spec::PanicStrategy;
 use tracing::debug;
 
 use crate::patch::MirPatch;
@@ -13,7 +12,7 @@ pub(super) struct RemoveNoopLandingPads;
 
 impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        sess.panic_strategy() != PanicStrategy::Abort
+        sess.panic_strategy().unwinds()
     }
 
     fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 795cb2b2cfe..81ada79dd43 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -29,7 +29,8 @@ use rustc_span::{
     SourceFileHashAlgorithm, Symbol, sym,
 };
 use rustc_target::spec::{
-    FramePointer, LinkSelfContainedComponents, LinkerFeatures, SplitDebuginfo, Target, TargetTuple,
+    FramePointer, LinkSelfContainedComponents, LinkerFeatures, PanicStrategy, SplitDebuginfo,
+    Target, TargetTuple,
 };
 use tracing::debug;
 
@@ -2799,6 +2800,12 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         }
     }
 
+    if !unstable_options_enabled && cg.panic == Some(PanicStrategy::ImmediateAbort) {
+        early_dcx.early_fatal(
+            "`-Cpanic=immediate-abort` requires `-Zunstable-options` and a nightly compiler",
+        )
+    }
+
     let crate_name = matches.opt_str("crate-name");
     let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref());
     // Parse any `-l` flags, which link to native libraries.
diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs
index 7e970461ab7..f3d91ce4a5d 100644
--- a/compiler/rustc_session/src/config/cfg.rs
+++ b/compiler/rustc_session/src/config/cfg.rs
@@ -125,7 +125,9 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) {
                 None | Some(_),
             ) => disallow(cfg, "-Z sanitizer=cfi"),
             (sym::proc_macro, None) => disallow(cfg, "--crate-type proc-macro"),
-            (sym::panic, Some(sym::abort | sym::unwind)) => disallow(cfg, "-C panic"),
+            (sym::panic, Some(sym::abort | sym::unwind | sym::immediate_abort)) => {
+                disallow(cfg, "-C panic")
+            }
             (sym::target_feature, Some(_)) => disallow(cfg, "-C target-feature"),
             (sym::unix, None)
             | (sym::windows, None)
@@ -203,7 +205,14 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg {
         ins_none!(sym::overflow_checks);
     }
 
+    // We insert a cfg for the name of session's panic strategy.
+    // Since the ImmediateAbort strategy is new, it also sets cfg(panic="abort"), so that code
+    // which is trying to detect whether unwinding is enabled by checking for cfg(panic="abort")
+    // does not need to be updated.
     ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
+    if sess.panic_strategy() == PanicStrategy::ImmediateAbort {
+        ins_sym!(sym::panic, PanicStrategy::Abort.desc_symbol());
+    }
 
     // JUSTIFICATION: before wrapper fn is available
     #[allow(rustc::bad_opt_access)]
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 69facde6936..3b9d8117786 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -802,7 +802,7 @@ mod desc {
     pub(crate) const parse_threads: &str = parse_number;
     pub(crate) const parse_time_passes_format: &str = "`text` (default) or `json`";
     pub(crate) const parse_passes: &str = "a space-separated list of passes, or `all`";
-    pub(crate) const parse_panic_strategy: &str = "either `unwind` or `abort`";
+    pub(crate) const parse_panic_strategy: &str = "either `unwind`, `abort`, or `immediate-abort`";
     pub(crate) const parse_on_broken_pipe: &str = "either `kill`, `error`, or `inherit`";
     pub(crate) const parse_patchable_function_entry: &str = "either two comma separated integers (total_nops,prefix_nops), with prefix_nops <= total_nops, or one integer (total_nops)";
     pub(crate) const parse_opt_panic_strategy: &str = parse_panic_strategy;
@@ -1165,6 +1165,7 @@ pub mod parse {
         match v {
             Some("unwind") => *slot = Some(PanicStrategy::Unwind),
             Some("abort") => *slot = Some(PanicStrategy::Abort),
+            Some("immediate-abort") => *slot = Some(PanicStrategy::ImmediateAbort),
             _ => return false,
         }
         true
@@ -1174,6 +1175,7 @@ pub mod parse {
         match v {
             Some("unwind") => *slot = PanicStrategy::Unwind,
             Some("abort") => *slot = PanicStrategy::Abort,
+            Some("immediate-abort") => *slot = PanicStrategy::ImmediateAbort,
             _ => return false,
         }
         true
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index d0dd2cdac0c..25b46241c52 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -777,9 +777,11 @@ impl Session {
         // Otherwise, we can defer to the `-C force-unwind-tables=<yes/no>`
         // value, if it is provided, or disable them, if not.
         self.target.requires_uwtable
-            || self.opts.cg.force_unwind_tables.unwrap_or(
-                self.panic_strategy() == PanicStrategy::Unwind || self.target.default_uwtable,
-            )
+            || self
+                .opts
+                .cg
+                .force_unwind_tables
+                .unwrap_or(self.panic_strategy().unwinds() || self.target.default_uwtable)
     }
 
     /// Returns the number of query threads that should be used for this
@@ -1229,7 +1231,7 @@ fn validate_commandline_args_with_session_available(sess: &Session) {
     }
 
     // KCFI requires panic=abort
-    if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy() != PanicStrategy::Abort {
+    if sess.is_sanitizer_kcfi_enabled() && sess.panic_strategy().unwinds() {
         sess.dcx().emit_err(errors::SanitizerKcfiRequiresPanicAbort);
     }
 
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index a6ae58f87dc..4e48c96afd6 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1196,6 +1196,7 @@ symbols! {
         if_let_rescope,
         if_while_or_patterns,
         ignore,
+        immediate_abort: "immediate-abort",
         impl_header_lifetime_elision,
         impl_lint_pass,
         impl_trait_in_assoc_type,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index c40358af593..4a82a8bd888 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -834,6 +834,7 @@ crate::target_spec_enum! {
     pub enum PanicStrategy {
         Unwind = "unwind",
         Abort = "abort",
+        ImmediateAbort = "immediate-abort",
     }
 
     parse_error_type = "panic strategy";
@@ -852,8 +853,13 @@ impl PanicStrategy {
         match *self {
             PanicStrategy::Unwind => sym::unwind,
             PanicStrategy::Abort => sym::abort,
+            PanicStrategy::ImmediateAbort => sym::immediate_abort,
         }
     }
+
+    pub fn unwinds(self) -> bool {
+        matches!(self, PanicStrategy::Unwind)
+    }
 }
 
 crate::target_spec_enum! {
diff --git a/compiler/rustc_thread_pool/src/latch.rs b/compiler/rustc_thread_pool/src/latch.rs
index 18d654d9f78..58dabaf35c0 100644
--- a/compiler/rustc_thread_pool/src/latch.rs
+++ b/compiler/rustc_thread_pool/src/latch.rs
@@ -388,13 +388,17 @@ impl Latch for CountLatch {
     #[inline]
     unsafe fn set(this: *const Self) {
         if unsafe { (*this).counter.fetch_sub(1, Ordering::SeqCst) == 1 } {
-            // NOTE: Once we call `set` on the internal `latch`,
+            // SAFETY: Once we call `set` on the internal `latch`,
             // the target may proceed and invalidate `this`!
             match unsafe { &(*this).kind } {
                 CountLatchKind::Stealing { latch, registry, worker_index } => {
                     let registry = Arc::clone(registry);
+                    let worker_index = *worker_index;
+                    // SAFETY: We don't use any references from `this` after this call.
                     if unsafe { CoreLatch::set(latch) } {
-                        registry.notify_worker_latch_is_set(*worker_index);
+                        // We **must not** access any part of `this` anymore, which
+                        // is why we read and shadowed these fields beforehand.
+                        registry.notify_worker_latch_is_set(worker_index);
                     }
                 }
                 CountLatchKind::Blocking { latch } => unsafe { LockLatch::set(latch) },
diff --git a/compiler/rustc_windows_rc/Cargo.toml b/compiler/rustc_windows_rc/Cargo.toml
index 080acd35c38..13f716897fa 100644
--- a/compiler/rustc_windows_rc/Cargo.toml
+++ b/compiler/rustc_windows_rc/Cargo.toml
@@ -5,7 +5,5 @@ edition = "2024"
 
 [dependencies]
 #tidy-alphabetical-start
-# `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
-# per crate", so if you change this, you need to also change it in `rustc_llvm` and `rustc_codegen_ssa`.
-cc = "=1.2.16"
+find-msvc-tools = "0.1.2"
 #tidy-alphabetical-end
diff --git a/compiler/rustc_windows_rc/src/lib.rs b/compiler/rustc_windows_rc/src/lib.rs
index 5e95557501e..15afaf7b94b 100644
--- a/compiler/rustc_windows_rc/src/lib.rs
+++ b/compiler/rustc_windows_rc/src/lib.rs
@@ -2,9 +2,7 @@
 //!
 //! Uses values from the `CFG_VERSION` and `CFG_RELEASE` environment variables
 //! to set the product and file version information in the Windows resource file.
-use std::{env, ffi, fs, path, process};
-
-use cc::windows_registry;
+use std::{env, fs, path, process};
 
 /// The template for the Windows resource file.
 const RESOURCE_TEMPLATE: &str = include_str!("../rustc.rc.in");
@@ -38,7 +36,10 @@ pub fn compile_windows_resource_file(
     let resource_compiler = if let Ok(path) = env::var("RUSTC_WINDOWS_RC") {
         path.into()
     } else {
-        find_resource_compiler(&env::var("CARGO_CFG_TARGET_ARCH").unwrap()).expect("found rc.exe")
+        find_msvc_tools::find_tool(&env::var("CARGO_CFG_TARGET_ARCH").unwrap(), "rc.exe")
+            .expect("found rc.exe")
+            .path()
+            .to_owned()
     };
 
     let rc_path = resources_dir.join(file_stem.with_extension("rc"));
@@ -134,28 +135,3 @@ fn parse_version(version: &str) -> Option<ResourceVersion> {
         Some(ResourceVersion { major, minor, patch, build: 0 })
     }
 }
-
-/// Find the Windows SDK resource compiler `rc.exe` for the given architecture or target triple.
-/// Returns `None` if the tool could not be found.
-fn find_resource_compiler(arch_or_target: &str) -> Option<path::PathBuf> {
-    find_windows_sdk_tool(arch_or_target, "rc.exe")
-}
-
-/// Find a Windows SDK tool for the given architecture or target triple.
-/// Returns `None` if the tool could not be found.
-fn find_windows_sdk_tool(arch_or_target: &str, tool_name: &str) -> Option<path::PathBuf> {
-    // windows_registry::find_tool can only find MSVC tools, not Windows SDK tools, but
-    // cc does include the Windows SDK tools in the PATH environment of MSVC tools.
-
-    let msvc_linker = windows_registry::find_tool(arch_or_target, "link.exe")?;
-    let path = &msvc_linker.env().iter().find(|(k, _)| k == "PATH")?.1;
-    find_tool_in_path(tool_name, path)
-}
-
-/// Find a tool in the directories in a given PATH-like string.
-fn find_tool_in_path<P: AsRef<ffi::OsStr>>(tool_name: &str, path: P) -> Option<path::PathBuf> {
-    env::split_paths(path.as_ref()).find_map(|p| {
-        let tool_path = p.join(tool_name);
-        if tool_path.try_exists().unwrap_or(false) { Some(tool_path) } else { None }
-    })
-}
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 9ba7c5bd28a..fb1f8c86dbf 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -22,8 +22,6 @@ compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
 compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"]
-# Make panics and failed asserts immediately abort without formatting any message
-panic_immediate_abort = ["core/panic_immediate_abort"]
 # Choose algorithms that are optimized for binary size instead of runtime performance
 optimize_for_size = ["core/optimize_for_size"]
 
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 76630a746dd..65c8206e9d4 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -408,12 +408,12 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
         }
     }
 
-    #[cfg(not(feature = "panic_immediate_abort"))]
+    #[cfg(not(panic = "immediate-abort"))]
     {
         core::intrinsics::const_eval_select((layout,), ct_error, rt_error)
     }
 
-    #[cfg(feature = "panic_immediate_abort")]
+    #[cfg(panic = "immediate-abort")]
     ct_error(layout)
 }
 
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index b0027e964e4..b7c153b825d 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -23,7 +23,7 @@ mod tests;
 // ensure that the code generation related to these panics is minimal as there's
 // only one location which panics rather than a bunch throughout the module.
 #[cfg(not(no_global_oom_handling))]
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
 #[track_caller]
 fn capacity_overflow() -> ! {
     panic!("capacity overflow");
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 10c7ee4f6c8..ebdb86f98a8 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -2020,7 +2020,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn swap_remove(&mut self, index: usize) -> T {
         #[cold]
-        #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+        #[cfg_attr(not(panic = "immediate-abort"), inline(never))]
         #[track_caller]
         #[optimize(size)]
         fn assert_failed(index: usize, len: usize) -> ! {
@@ -2102,7 +2102,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[must_use = "if you don't need a reference to the value, use `Vec::insert` instead"]
     pub fn insert_mut(&mut self, index: usize, element: T) -> &mut T {
         #[cold]
-        #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+        #[cfg_attr(not(panic = "immediate-abort"), inline(never))]
         #[track_caller]
         #[optimize(size)]
         fn assert_failed(index: usize, len: usize) -> ! {
@@ -2166,7 +2166,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[rustc_confusables("delete", "take")]
     pub fn remove(&mut self, index: usize) -> T {
         #[cold]
-        #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+        #[cfg_attr(not(panic = "immediate-abort"), inline(never))]
         #[track_caller]
         #[optimize(size)]
         fn assert_failed(index: usize, len: usize) -> ! {
@@ -2955,7 +2955,7 @@ impl<T, A: Allocator> Vec<T, A> {
         A: Clone,
     {
         #[cold]
-        #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+        #[cfg_attr(not(panic = "immediate-abort"), inline(never))]
         #[track_caller]
         #[optimize(size)]
         fn assert_failed(at: usize, len: usize) -> ! {
diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml
index 3e34e03a61e..d094172b076 100644
--- a/library/core/Cargo.toml
+++ b/library/core/Cargo.toml
@@ -16,7 +16,7 @@ test = false
 bench = false
 
 [features]
-# Make panics and failed asserts immediately abort without formatting any message
+# Issue a compile error that says to use -Cpanic=immediate-abort
 panic_immediate_abort = []
 # Choose algorithms that are optimized for binary size instead of runtime performance
 optimize_for_size = []
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 9b53b75ebee..7d4a66640b1 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -778,7 +778,7 @@ impl Display for BorrowMutError {
 }
 
 // This ensures the panicking code is outlined from `borrow_mut` for `RefCell`.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
 #[track_caller]
 #[cold]
 const fn panic_already_borrowed(err: BorrowMutError) -> ! {
@@ -790,7 +790,7 @@ const fn panic_already_borrowed(err: BorrowMutError) -> ! {
 }
 
 // This ensures the panicking code is outlined from `borrow` for `RefCell`.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
 #[track_caller]
 #[cold]
 const fn panic_already_mutably_borrowed(err: BorrowError) -> ! {
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index a820045521b..c50f07ff6bb 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -779,7 +779,7 @@ impl<T> OneShot for result::IterMut<'_, T> {}
 impl<T> OneShot for Empty<T> {}
 impl<T> OneShot for array::IntoIter<T, 0> {}
 
-// These adaptors never increase the number of items.
+// These adapters never increase the number of items.
 // (There are more possible, but for now this matches BoundedSize above.)
 impl<I: OneShot> OneShot for Cloned<I> {}
 impl<I: OneShot> OneShot for Copied<I> {}
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index 54d5a63633c..c75ee11d15e 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -1387,8 +1387,8 @@ pub const fn can_not_overflow<T>(radix: u32, is_signed_ty: bool, digits: &[u8])
     radix <= 16 && digits.len() <= size_of::<T>() * 2 - is_signed_ty as usize
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[cold]
 #[track_caller]
 const fn from_ascii_radix_panic(radix: u32) -> ! {
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 886d581b0a6..430ee3470ac 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -2161,8 +2161,8 @@ impl<T, E> Option<Result<T, E>> {
     }
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[cold]
 #[track_caller]
 const fn unwrap_failed() -> ! {
@@ -2170,8 +2170,8 @@ const fn unwrap_failed() -> ! {
 }
 
 // This is a separate function to reduce the code size of .expect() itself.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[cold]
 #[track_caller]
 const fn expect_failed(msg: &str) -> ! {
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index 804a12ee477..3f30038dbc0 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -33,7 +33,10 @@ use crate::intrinsics::const_eval_select;
 use crate::panic::{Location, PanicInfo};
 
 #[cfg(feature = "panic_immediate_abort")]
-const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C panic=abort");
+compile_error!(
+    "panic_immediate_abort is now a real panic strategy! \
+    Enable it with the compiler flags `-Zunstable-options -Cpanic=immediate-abort`"
+);
 
 // First we define the two main entry points that all panics go through.
 // In the end both are just convenience wrappers around `panic_impl`.
@@ -44,16 +47,16 @@ const _: () = assert!(cfg!(panic = "abort"), "panic_immediate_abort requires -C
 /// site as much as possible (so that `panic!()` has as low an impact
 /// on (e.g.) the inlining of other functions as possible), by moving
 /// the actual formatting into this shared place.
-// If panic_immediate_abort, inline the abort call,
+// If panic=immediate-abort, inline the abort call,
 // otherwise avoid inlining because of it is cold path.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[lang = "panic_fmt"] // needed for const-evaluated panics
 #[rustc_do_not_const_check] // hooked by const-eval
 #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
 pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         super::intrinsics::abort()
     }
 
@@ -78,8 +81,8 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
 /// Like `panic_fmt`, but for non-unwinding panics.
 ///
 /// Has to be a separate function so that it can carry the `rustc_nounwind` attribute.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 // This attribute has the key side-effect that if the panic handler ignores `can_unwind`
 // and unwinds anyway, we will hit the "unwinding out of nounwind function" guard,
@@ -94,7 +97,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
             // We don't unwind anyway at compile-time so we can call the regular `panic_fmt`.
             panic_fmt(fmt)
         } else #[track_caller] {
-            if cfg!(feature = "panic_immediate_abort") {
+            if cfg!(panic = "immediate-abort") {
                 super::intrinsics::abort()
             }
 
@@ -123,10 +126,10 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
 // above.
 
 /// The underlying implementation of core's `panic!` macro when no formatting is used.
-// Never inline unless panic_immediate_abort to avoid code
+// Never inline unless panic=immediate-abort to avoid code
 // bloat at the call sites as much as possible.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
 #[lang = "panic"] // used by lints and miri for panics
@@ -158,10 +161,10 @@ macro_rules! panic_const {
         $(
             /// This is a panic called with a message that's a result of a MIR-produced Assert.
             //
-            // never inline unless panic_immediate_abort to avoid code
+            // never inline unless panic=immediate-abort to avoid code
             // bloat at the call sites as much as possible
-            #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-            #[cfg_attr(feature = "panic_immediate_abort", inline)]
+            #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+            #[cfg_attr(panic = "immediate-abort", inline)]
             #[track_caller]
             #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
             #[lang = stringify!($lang)]
@@ -216,8 +219,8 @@ pub mod panic_const {
 
 /// Like `panic`, but without unwinding and track_caller to reduce the impact on codesize on the caller.
 /// If you want `#[track_caller]` for nicer errors, call `panic_nounwind_fmt` directly.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[lang = "panic_nounwind"] // needed by codegen for non-unwinding panics
 #[rustc_nounwind]
 #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable
@@ -226,8 +229,8 @@ pub const fn panic_nounwind(expr: &'static str) -> ! {
 }
 
 /// Like `panic_nounwind`, but also inhibits showing a backtrace.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[rustc_nounwind]
 pub fn panic_nounwind_nobacktrace(expr: &'static str) -> ! {
     panic_nounwind_fmt(fmt::Arguments::new_const(&[expr]), /* force_no_backtrace */ true);
@@ -259,25 +262,25 @@ pub const fn panic_display<T: fmt::Display>(x: &T) -> ! {
     panic_fmt(format_args!("{}", *x));
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access
 fn panic_bounds_check(index: usize, len: usize) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         super::intrinsics::abort()
     }
 
     panic!("index out of bounds: the len is {len} but the index is {index}")
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[lang = "panic_misaligned_pointer_dereference"] // needed by codegen for panic on misaligned pointer deref
 #[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind
 fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         super::intrinsics::abort()
     }
 
@@ -289,13 +292,13 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! {
     )
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[lang = "panic_null_pointer_dereference"] // needed by codegen for panic on null pointer deref
 #[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind
 fn panic_null_pointer_dereference() -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         super::intrinsics::abort()
     }
 
@@ -305,13 +308,13 @@ fn panic_null_pointer_dereference() -> ! {
     )
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[lang = "panic_invalid_enum_construction"] // needed by codegen for panic on invalid enum construction.
 #[rustc_nounwind] // `CheckEnums` MIR pass requires this function to never unwind
 fn panic_invalid_enum_construction(source: u128) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         super::intrinsics::abort()
     }
 
@@ -328,8 +331,8 @@ fn panic_invalid_enum_construction(source: u128) -> ! {
 ///
 /// This function is called directly by the codegen backend, and must not have
 /// any extra arguments (including those synthesized by track_caller).
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[lang = "panic_cannot_unwind"] // needed by codegen for panic in nounwind function
 #[rustc_nounwind]
 fn panic_cannot_unwind() -> ! {
@@ -344,8 +347,8 @@ fn panic_cannot_unwind() -> ! {
 ///
 /// This function is called directly by the codegen backend, and must not have
 /// any extra arguments (including those synthesized by track_caller).
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[lang = "panic_in_cleanup"] // needed by codegen for panic in nounwind function
 #[rustc_nounwind]
 fn panic_in_cleanup() -> ! {
@@ -377,8 +380,8 @@ pub enum AssertKind {
 }
 
 /// Internal function for `assert_eq!` and `assert_ne!` macros
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[doc(hidden)]
 pub fn assert_failed<T, U>(
@@ -395,8 +398,8 @@ where
 }
 
 /// Internal function for `assert_match!`
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[doc(hidden)]
 pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
@@ -415,8 +418,8 @@ pub fn assert_matches_failed<T: fmt::Debug + ?Sized>(
 }
 
 /// Non-generic version of the above functions, to avoid code bloat.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 fn assert_failed_inner(
     kind: AssertKind,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 5c1f64bfe14..c69762a7285 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1847,7 +1847,7 @@ impl<T, E> Result<Result<T, E>, E> {
 }
 
 // This is a separate function to reduce the code size of the methods
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 #[inline(never)]
 #[cold]
 #[track_caller]
@@ -1859,7 +1859,7 @@ fn unwrap_failed(msg: &str, error: &dyn fmt::Debug) -> ! {
 // that gets immediately thrown away, since vtables don't get cleaned up
 // by dead code elimination if a trait object is constructed even if it goes
 // unused
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 #[inline]
 #[cold]
 #[track_caller]
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index d4c466201ed..de220e7e38a 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -31,8 +31,8 @@ where
     }
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 const fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
     if start > len {
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index dfbb3628350..f7f5ee819b2 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -3858,8 +3858,8 @@ impl<T> [T] {
     {
         // The panic code path was put into a cold function to not bloat the
         // call site.
-        #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-        #[cfg_attr(feature = "panic_immediate_abort", inline)]
+        #[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+        #[cfg_attr(panic = "immediate-abort", inline)]
         #[track_caller]
         const fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
             const_panic!(
diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs
index 400daba16c1..e555fce4408 100644
--- a/library/core/src/slice/sort/shared/smallsort.rs
+++ b/library/core/src/slice/sort/shared/smallsort.rs
@@ -840,8 +840,8 @@ unsafe fn bidirectional_merge<T: FreezeMarker, F: FnMut(&T, &T) -> bool>(
     }
 }
 
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 fn panic_on_ord_violation() -> ! {
     // This is indicative of a logic bug in the user-provided comparison function or Ord
     // implementation. They are expected to implement a total order as explained in the Ord
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 04fdaa8143e..2e473d348b0 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -64,12 +64,12 @@ pub use validations::{next_code_point, utf8_char_width};
 #[cold]
 #[track_caller]
 #[rustc_allow_const_fn_unstable(const_eval_select)]
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     crate::intrinsics::const_eval_select((s, begin, end), slice_error_fail_ct, slice_error_fail_rt)
 }
 
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 const fn slice_error_fail(s: &str, begin: usize, end: usize) -> ! {
     slice_error_fail_ct(s, begin, end)
 }
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index d28a7f0b460..958cafb8f3d 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -106,11 +106,6 @@ compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
 
-# Make panics and failed asserts immediately abort without formatting any message
-panic_immediate_abort = [
-    "core/panic_immediate_abort",
-    "alloc/panic_immediate_abort",
-]
 # Choose algorithms that are optimized for binary size instead of runtime performance
 optimize_for_size = ["core/optimize_for_size", "alloc/optimize_for_size"]
 
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index ff0e29e04c2..a45edd08e8c 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1081,7 +1081,7 @@ pub trait Read {
         default_read_buf_exact(self, cursor)
     }
 
-    /// Creates a "by reference" adaptor for this instance of `Read`.
+    /// Creates a "by reference" adapter for this instance of `Read`.
     ///
     /// The returned adapter also implements `Read` and will simply borrow this
     /// current reader.
diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs
index 8b7282c51d1..b7be869c4eb 100644
--- a/library/std/src/panicking.rs
+++ b/library/std/src/panicking.rs
@@ -331,7 +331,7 @@ fn default_hook(info: &PanicHookInfo<'_>) {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 #[unstable(feature = "update_panic_count", issue = "none")]
 pub mod panic_count {
     /// A reason for forcing an immediate abort on panic.
@@ -371,7 +371,7 @@ pub mod panic_count {
 
 #[cfg(not(test))]
 #[doc(hidden)]
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 #[unstable(feature = "update_panic_count", issue = "none")]
 pub mod panic_count {
     use crate::cell::Cell;
@@ -499,13 +499,13 @@ pub mod panic_count {
 pub use realstd::rt::panic_count;
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     Ok(f())
 }
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 pub unsafe fn catch_unwind<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<dyn Any + Send>> {
     union Data<F, R> {
         f: ManuallyDrop<F>,
@@ -720,14 +720,14 @@ pub fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! {
 #[unstable(feature = "libstd_sys_internals", reason = "used by the panic! macro", issue = "none")]
 #[cfg_attr(not(any(test, doctest)), lang = "begin_panic")]
 // lang item for CTFE panic support
-// never inline unless panic_immediate_abort to avoid code
+// never inline unless panic=immediate-abort to avoid code
 // bloat at the call sites as much as possible
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold, optimize(size))]
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never), cold, optimize(size))]
+#[cfg_attr(panic = "immediate-abort", inline)]
 #[track_caller]
 #[rustc_do_not_const_check] // hooked by const-eval
 pub const fn begin_panic<M: Any + Send>(msg: M) -> ! {
-    if cfg!(feature = "panic_immediate_abort") {
+    if cfg!(panic = "immediate-abort") {
         intrinsics::abort()
     }
 
@@ -861,7 +861,7 @@ fn panic_with_hook(
 
 /// This is the entry point for `resume_unwind`.
 /// It just forwards the payload to the panic runtime.
-#[cfg_attr(feature = "panic_immediate_abort", inline)]
+#[cfg_attr(panic = "immediate-abort", inline)]
 pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
     panic_count::increase(false);
 
@@ -890,16 +890,14 @@ pub fn resume_unwind(payload: Box<dyn Any + Send>) -> ! {
 /// on which to slap yer breakpoints.
 #[inline(never)]
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
-#[cfg(not(feature = "panic_immediate_abort"))]
+#[cfg(not(panic = "immediate-abort"))]
 fn rust_panic(msg: &mut dyn PanicPayload) -> ! {
     let code = unsafe { __rust_start_panic(msg) };
     rtabort!("failed to initiate panic, error {code}")
 }
 
 #[cfg_attr(not(test), rustc_std_internal_symbol)]
-#[cfg(feature = "panic_immediate_abort")]
+#[cfg(panic = "immediate-abort")]
 fn rust_panic(_: &mut dyn PanicPayload) -> ! {
-    unsafe {
-        crate::intrinsics::abort();
-    }
+    crate::intrinsics::abort();
 }
diff --git a/library/std/src/rt.rs b/library/std/src/rt.rs
index 8d95cc1fb57..2717b7b469c 100644
--- a/library/std/src/rt.rs
+++ b/library/std/src/rt.rs
@@ -39,11 +39,11 @@ fn __rust_abort() {
 // - nothing (so this macro is a no-op)
 macro_rules! rtprintpanic {
     ($($t:tt)*) => {
-        #[cfg(not(feature = "panic_immediate_abort"))]
+        #[cfg(not(panic = "immediate-abort"))]
         if let Some(mut out) = crate::sys::stdio::panic_output() {
             let _ = crate::io::Write::write_fmt(&mut out, format_args!($($t)*));
         }
-        #[cfg(feature = "panic_immediate_abort")]
+        #[cfg(panic = "immediate-abort")]
         {
             let _ = format_args!($($t)*);
         }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index 797feeb2bbb..0a6f2e5d508 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -230,7 +230,7 @@ impl fmt::Display for AccessError {
 impl Error for AccessError {}
 
 // This ensures the panicking code is outlined from `with` for `LocalKey`.
-#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
+#[cfg_attr(not(panic = "immediate-abort"), inline(never))]
 #[track_caller]
 #[cold]
 fn panic_access_error(err: AccessError) -> ! {
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 7b4aeed94e9..ee4aec61872 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -31,7 +31,6 @@ llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
 optimize_for_size = ["std/optimize_for_size"]
 panic-unwind = ["std/panic-unwind"]
-panic_immediate_abort = ["std/panic_immediate_abort"]
 profiler = ["dep:profiler_builtins"]
 std_detect_file_io = ["std/std_detect_file_io"]
 std_detect_dlsym_getauxval = ["std/std_detect_dlsym_getauxval"]
diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md
index 445b10188e3..0e340de4daa 100644
--- a/src/doc/rustc/src/codegen-options/index.md
+++ b/src/doc/rustc/src/codegen-options/index.md
@@ -471,11 +471,13 @@ If not specified, overflow checks are enabled if
 This option lets you control what happens when the code panics.
 
 * `abort`: terminate the process upon panic
+* `immediate-abort`: terminate the process upon panic, and do not call any panic hooks
 * `unwind`: unwind the stack upon panic
 
 If not specified, the default depends on the target.
 
 If any crate in the crate graph uses `abort`, the final binary (`bin`, `dylib`, `cdylib`, `staticlib`) must also use `abort`.
+If any crate in the crate graph uses `immediate-abort`, every crate in the graph must use `immediate-abort`.
 If `std` is used as a `dylib` with `unwind`, the final binary must also use `unwind`.
 
 ## passes
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index ab95aa2e5a1..32e712a48d7 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -144,7 +144,7 @@ def minor_version(version):
 INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"]
 subprocess.run(INSTALL_TOOLCHAIN + ["nightly"])
 
-LOWER_BOUND = 73
+LOWER_BOUND = 87
 NIGHTLY_VERSION = minor_version(subprocess.run(
     ["rustc", "+nightly", "--version"],
     capture_output=True,
@@ -201,6 +201,9 @@ The following table shows known good combinations of toolchain versions.
 | 1.65 - 1.69  |      15       |
 | 1.70 - 1.72  |      16       |
 | 1.73 - 1.77  |      17       |
-| 1.78         |      18       |
+| 1.78 - 1.81  |      18       |
+| 1.82 - 1.86  |      19       |
+| 1.87 - 1.90  |      20       |
+| 1.91 - 1.92  |      21       |
 
 Note that the compatibility policy for this feature might change in the future.
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 75febd6f737..3ea9de381ec 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -2227,11 +2227,18 @@ function preLoadCss(cssUrl) {
     });
 }());
 
-// This section is a bugfix for firefox: when copying text with `user-select: none`, it adds
-// extra backline characters.
+
+// Workaround for browser-specific bugs when copying code snippets.
+//
+// * In Firefox, copying text that includes elements with `user-select: none`
+//   inserts extra blank lines.
+//   - Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836
+//   - Rust issue: https://github.com/rust-lang/rust/issues/141464
 //
-// Rustdoc issue: Workaround for https://github.com/rust-lang/rust/issues/141464
-// Firefox issue: https://bugzilla.mozilla.org/show_bug.cgi?id=1273836
+// * In Chromium-based browsers, `document.getSelection()` includes elements
+//   with `user-select: none`, causing unwanted line numbers to be copied.
+//   - Chromium issue: https://issues.chromium.org/issues/446539520
+//   - Rust issue: https://github.com/rust-lang/rust/issues/146816
 (function() {
     document.body.addEventListener("copy", event => {
         let target = nonnull(event.target);
@@ -2248,9 +2255,13 @@ function preLoadCss(cssUrl) {
         if (!isInsideCode) {
             return;
         }
-        const selection = document.getSelection();
-         // @ts-expect-error
-        nonnull(event.clipboardData).setData("text/plain", selection.toString());
+        const selection = nonnull(document.getSelection());
+        const text = Array.from({ length: selection.rangeCount }, (_, i) => {
+            const fragment = selection.getRangeAt(i).cloneContents();
+            fragment.querySelectorAll("[data-nosnippet]").forEach(el => el.remove());
+            return fragment.textContent;
+        }).join("");
+        nonnull(event.clipboardData).setData("text/plain", text);
         event.preventDefault();
     });
 }());
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index cdada5a2230..6597c3c70f6 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -12,7 +12,7 @@ path = "src/bin/main.rs"
 
 [dependencies]
 # tidy-alphabetical-start
-anstyle-svg = "0.1.3"
+anstyle-svg = "0.1.11"
 build_helper = { path = "../../build_helper" }
 camino = "1"
 colored = "2"
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 1277fd225eb..e84a2278766 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -201,6 +201,8 @@ pub struct TestProps {
     /// Build and use `minicore` as `core` stub for `no_core` tests in cross-compilation scenarios
     /// that don't otherwise want/need `-Z build-std`.
     pub add_core_stubs: bool,
+    /// Add these flags to the build of `minicore`.
+    pub core_stubs_compile_flags: Vec<String>,
     /// Whether line annotatins are required for the given error kind.
     pub dont_require_annotations: HashSet<ErrorKind>,
     /// Whether pretty printers should be disabled in gdb.
@@ -253,6 +255,7 @@ mod directives {
     pub const FILECHECK_FLAGS: &'static str = "filecheck-flags";
     pub const NO_AUTO_CHECK_CFG: &'static str = "no-auto-check-cfg";
     pub const ADD_CORE_STUBS: &'static str = "add-core-stubs";
+    pub const CORE_STUBS_COMPILE_FLAGS: &'static str = "core-stubs-compile-flags";
     // This isn't a real directive, just one that is probably mistyped often
     pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
     pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers";
@@ -311,6 +314,7 @@ impl TestProps {
             no_auto_check_cfg: false,
             has_enzyme: false,
             add_core_stubs: false,
+            core_stubs_compile_flags: vec![],
             dont_require_annotations: Default::default(),
             disable_gdb_pretty_printers: false,
             compare_output_by_lines: false,
@@ -653,6 +657,21 @@ impl TestProps {
 
                     self.update_add_core_stubs(ln, config);
 
+                    if let Some(flags) = config.parse_name_value_directive(
+                        ln,
+                        directives::CORE_STUBS_COMPILE_FLAGS,
+                        testfile,
+                        line_number,
+                    ) {
+                        let flags = split_flags(&flags);
+                        for flag in &flags {
+                            if flag == "--edition" || flag.starts_with("--edition=") {
+                                panic!("you must use `//@ edition` to configure the edition");
+                            }
+                        }
+                        self.core_stubs_compile_flags.extend(flags);
+                    }
+
                     if let Some(err_kind) = config.parse_name_value_directive(
                         ln,
                         DONT_REQUIRE_ANNOTATIONS,
diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs
index 0ef84fb4594..4fef8992567 100644
--- a/src/tools/compiletest/src/directives/directive_names.rs
+++ b/src/tools/compiletest/src/directives/directive_names.rs
@@ -19,6 +19,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-test-line-numbers-match",
     "compare-output-by-lines",
     "compile-flags",
+    "core-stubs-compile-flags",
     "disable-gdb-pretty-printers",
     "doc-flags",
     "dont-check-compiler-stderr",
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 89fb8eb4357..29578acb404 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -1322,6 +1322,7 @@ impl<'test> TestCx<'test> {
 
         rustc.args(&["--crate-type", "rlib"]);
         rustc.arg("-Cpanic=abort");
+        rustc.args(self.props.core_stubs_compile_flags.clone());
 
         let res = self.compose_and_run(rustc, self.config.compile_lib_path.as_path(), None, None);
         if !res.status.success() {
@@ -1432,6 +1433,12 @@ impl<'test> TestCx<'test> {
 
         aux_rustc.arg("-L").arg(&aux_dir);
 
+        if aux_props.add_core_stubs {
+            let minicore_path = self.build_minicore();
+            aux_rustc.arg("--extern");
+            aux_rustc.arg(&format!("minicore={}", minicore_path));
+        }
+
         let auxres = aux_cx.compose_and_run(
             aux_rustc,
             aux_cx.config.compile_lib_path.as_path(),
@@ -1858,14 +1865,13 @@ impl<'test> TestCx<'test> {
             }
         }
 
-        rustc.args(&self.props.compile_flags);
-
         // FIXME(jieyouxu): we should report a fatal error or warning if user wrote `-Cpanic=` with
-        // something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`,
-        // however, by moving this last we should override previous `-Cpanic`s and
-        // `-Cforce-unwind-tables`s. Note that checking here is very fragile, because we'd have to
-        // account for all possible compile flag splittings (they have some... intricacies and are
-        // not yet normalized).
+        // something that's not `abort` and `-Cforce-unwind-tables` with a value that is not `yes`.
+        //
+        // We could apply these last and override any provided flags. That would ensure that the
+        // build works, but some tests want to exercise that mixing panic modes in specific ways is
+        // rejected. So we enable aborting panics and unwind tables before adding flags, just to
+        // change the default.
         //
         // `minicore` requires `#![no_std]` and `#![no_core]`, which means no unwinding panics.
         if self.props.add_core_stubs {
@@ -1873,6 +1879,8 @@ impl<'test> TestCx<'test> {
             rustc.arg("-Cforce-unwind-tables=yes");
         }
 
+        rustc.args(&self.props.compile_flags);
+
         rustc
     }
 
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index e275d3042cb..247080102fb 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -367,6 +367,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",
+    "find-msvc-tools",
     "flate2",
     "fluent-bundle",
     "fluent-langneg",
diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml b/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml
new file mode 100644
index 00000000000..3c61c12a84e
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-codegen/Cargo.toml
@@ -0,0 +1,12 @@
+cargo-features = ["profile-rustflags"]
+
+[package]
+name = "panic_scenarios"
+version = "0.1.0"
+edition = "2024"
+
+[lib]
+path = "lib.rs"
+
+[profile.release]
+rustflags = ["-Zmerge-functions=disabled", "-Zcodegen-source-order", "--emit=llvm-ir"]
diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs b/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs
new file mode 100644
index 00000000000..1e20da93ba8
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-codegen/lib.rs
@@ -0,0 +1,65 @@
+#![no_std]
+
+#[unsafe(no_mangle)]
+pub fn panic_noarg() {
+    // CHECK-LABEL: @panic_noarg(
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: tail call void @llvm.trap()
+    panic!();
+}
+
+#[unsafe(no_mangle)]
+pub fn panic_str() {
+    // CHECK-LABEL: @panic_str(
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: tail call void @llvm.trap()
+    panic!("ouch");
+}
+
+#[unsafe(no_mangle)]
+pub fn bounds_check(x: &[u8], idx: usize) -> &u8 {
+    // CHECK-LABEL: @bounds_check(
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: icmp ult
+    // CHECK-NEXT: br i1
+    // CHECK: bb1:
+    // CHECK-NEXT: getelementptr inbounds nuw i8
+    // CHECK-NEXT: ret ptr
+    // CHECK: panic:
+    // CHECK-NEXT: tail call void @llvm.trap()
+    &x[idx]
+}
+
+#[unsafe(no_mangle)]
+pub fn str_bounds_check(x: &str, idx: usize) -> &str {
+    // CHECK-LABEL: @str_bounds_check(
+    // CHECK-NOT: call
+    // CHECK: tail call void @llvm.trap()
+    // CHECK-NOT: call
+    &x[idx..]
+}
+
+#[unsafe(no_mangle)]
+pub fn unsigned_integer_div(x: u16, y: u16) -> u16 {
+    // CHECK-LABEL: @unsigned_integer_div(
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: icmp eq i16
+    // CHECK-NEXT: br i1
+    // CHECK: bb1:
+    // CHECK-NEXT: udiv i16
+    // CHECK-NEXT: ret i16
+    // CHECK: panic:
+    // CHECK-NEXT: tail call void @llvm.trap()
+    x / y
+}
+
+#[unsafe(no_mangle)]
+pub fn refcell_already_borrowed() {
+    // CHECK-LABEL: @refcell_already_borrowed(
+    // CHECK-NOT: call
+    // CHECK: tail call void @llvm.trap()
+    // CHECK-NOT: call
+    let r = core::cell::RefCell::new(0u8);
+    let _guard = r.borrow_mut();
+    r.borrow_mut();
+}
diff --git a/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs b/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs
new file mode 100644
index 00000000000..d7a7a8bfd8c
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-codegen/rmake.rs
@@ -0,0 +1,46 @@
+// This is a codegen test which checks that when code is compiled with panic=immediate-abort,
+// we get a `tail call void @llvm.trap()` in user code instead of a call into the standard
+// library's panic formatting code (such as panic_fmt) or one of the numerous panic outlining shims
+// (such as slice_index_fail).
+
+#![deny(warnings)]
+
+use run_make_support::{cargo, llvm_filecheck, path, rfs, target};
+
+fn main() {
+    let target_dir = path("target");
+
+    cargo()
+        .args(&[
+            "build",
+            "--release",
+            "--lib",
+            "--manifest-path",
+            "Cargo.toml",
+            "-Zbuild-std=core",
+            "--target",
+            &target(),
+        ])
+        .env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort")
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .env("RUSTC_BOOTSTRAP", "1")
+        // Visual Studio 2022 requires that the LIB env var be set so it can
+        // find the Windows SDK.
+        .env("LIB", std::env::var("LIB").unwrap_or_default())
+        .run();
+
+    let out_dir = target_dir.join(target()).join("release").join("deps");
+    let ir_file = rfs::read_dir(out_dir)
+        .find_map(|e| {
+            let path = e.unwrap().path();
+            let file_name = path.file_name().unwrap().to_str().unwrap();
+            if file_name.starts_with("panic_scenarios") && file_name.ends_with(".ll") {
+                Some(path)
+            } else {
+                None
+            }
+        })
+        .unwrap();
+
+    llvm_filecheck().patterns("lib.rs").input_file(ir_file).run();
+}
diff --git a/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml b/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml
new file mode 100644
index 00000000000..1e278d557c0
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-works/hello/Cargo.toml
@@ -0,0 +1,4 @@
+[package]
+name = "hello"
+version = "0.1.0"
+edition = "2024"
diff --git a/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs b/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs
new file mode 100644
index 00000000000..f328e4d9d04
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-works/hello/src/main.rs
@@ -0,0 +1 @@
+fn main() {}
diff --git a/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs b/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs
new file mode 100644
index 00000000000..3eeef38c962
--- /dev/null
+++ b/tests/run-make-cargo/panic-immediate-abort-works/rmake.rs
@@ -0,0 +1,39 @@
+// This test ensures we are able to compile and link a simple binary with panic=immediate-abort.
+// The test panic-immediate-abort-codegen checks that panic strategy produces the desired codegen,
+// but is based on compiling a library crate (which is the norm for codegen tests because it is
+// cleaner and more portable). So this test ensures that we didn't mix up a cfg or a compiler
+// implementation detail in a way that makes panic=immediate-abort encounter errors at link time.
+
+// Ideally this test would be run for most targets, but unfortunately:
+// This test is currently written using `fn main() {}` which requires std.
+// And since the default linker is only a linker for the host, we can't handle cross-compilation.
+// Both of these shortcomings could be addressed at the cost of making the test more complicated.
+//@ needs-target-std
+//@ ignore-cross-compile
+
+#![deny(warnings)]
+
+use run_make_support::{cargo, path, target};
+
+fn main() {
+    let target_dir = path("target");
+
+    cargo()
+        .current_dir("hello")
+        .args(&[
+            "build",
+            "--release",
+            "--manifest-path",
+            "Cargo.toml",
+            "-Zbuild-std",
+            "--target",
+            &target(),
+        ])
+        .env("RUSTFLAGS", "-Zunstable-options -Cpanic=immediate-abort")
+        .env("CARGO_TARGET_DIR", &target_dir)
+        .env("RUSTC_BOOTSTRAP", "1")
+        // Visual Studio 2022 requires that the LIB env var be set so it can
+        // find the Windows SDK.
+        .env("LIB", std::env::var("LIB").unwrap_or_default())
+        .run();
+}
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-3.rs b/tests/run-make/crate-loading/dep-2-reexport.rs
index 07444511472..07444511472 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions-3.rs
+++ b/tests/run-make/crate-loading/dep-2-reexport.rs
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-1.rs b/tests/run-make/crate-loading/dependency-1.rs
index bfeabccf5c1..bfeabccf5c1 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions-1.rs
+++ b/tests/run-make/crate-loading/dependency-1.rs
diff --git a/tests/run-make/crate-loading/multiple-dep-versions-2.rs b/tests/run-make/crate-loading/dependency-2.rs
index 682d1ff64b8..682d1ff64b8 100644
--- a/tests/run-make/crate-loading/multiple-dep-versions-2.rs
+++ b/tests/run-make/crate-loading/dependency-2.rs
diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs
index 6ad456e3e3e..8f257786123 100644
--- a/tests/run-make/crate-loading/rmake.rs
+++ b/tests/run-make/crate-loading/rmake.rs
@@ -6,12 +6,9 @@
 use run_make_support::{diff, rust_lib_name, rustc};
 
 fn main() {
-    rustc().input("multiple-dep-versions-1.rs").run();
-    rustc().input("multiple-dep-versions-2.rs").extra_filename("2").metadata("2").run();
-    rustc()
-        .input("multiple-dep-versions-3.rs")
-        .extern_("dependency", rust_lib_name("dependency2"))
-        .run();
+    rustc().input("dependency-1.rs").run();
+    rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run();
+    rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run();
 
     let out = rustc()
         .input("multiple-dep-versions.rs")
diff --git a/tests/rustdoc/reexport/private-mod-override-reexport.rs b/tests/rustdoc/reexport/private-mod-override-reexport.rs
new file mode 100644
index 00000000000..849acc5fdae
--- /dev/null
+++ b/tests/rustdoc/reexport/private-mod-override-reexport.rs
@@ -0,0 +1,13 @@
+// https://github.com/rust-lang/rust/issues/60926
+#![crate_name = "foo"]
+
+mod m1 {
+    pub mod m2 {
+        pub struct Foo;
+    }
+}
+
+pub use m1::*;
+use crate::m1::m2;
+
+//@ count foo/index.html '//a[@class="mod"]' 0
diff --git a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
index 989a01f2244..4b5fc91c7eb 100644
--- a/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
+++ b/tests/ui/check-cfg/report-in-external-macros.cargo.stderr
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
 LL |     cfg_macro::my_lib_macro_value!();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `panic` are: `abort` and `unwind`
+   = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind`
    = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
    = help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
    = help: the macro `cfg_macro::my_lib_macro_value` may come from an old version of the `cfg_macro` crate, try updating your dependency with `cargo update -p cfg_macro`
diff --git a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
index 95d10e014f3..0d99d061d28 100644
--- a/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
+++ b/tests/ui/check-cfg/report-in-external-macros.rustc.stderr
@@ -18,7 +18,7 @@ warning: unexpected `cfg` condition value: `UNEXPECTED_VALUE`
 LL |     cfg_macro::my_lib_macro_value!();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `panic` are: `abort` and `unwind`
+   = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind`
    = note: using a cfg inside a macro will use the cfgs from the destination crate and not the ones from the defining crate
    = help: try referring to `cfg_macro::my_lib_macro_value` crate for guidance on how handle this unexpected cfg
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index df2357696a3..e62f741b302 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -80,7 +80,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     panic = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `panic` are: `abort` and `unwind`
+   = note: expected values for `panic` are: `abort`, `immediate-abort`, and `unwind`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
index 1cedbf75e4b..7ffbc64b074 100644
--- a/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
+++ b/tests/ui/codemap_tests/huge_multispan_highlight.ascii.svg
@@ -1,7 +1,7 @@
-<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg">
+<svg width="740px" height="758px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-012 { fill: #5555FF }
     .container {
diff --git a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
index 36a33b74042..5f1fcdb3d50 100644
--- a/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
+++ b/tests/ui/codemap_tests/huge_multispan_highlight.unicode.svg
@@ -1,7 +1,7 @@
-<svg width="743px" height="758px" xmlns="http://www.w3.org/2000/svg">
+<svg width="740px" height="758px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-012 { fill: #5555FF }
     .container {
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.svg b/tests/ui/diagnostic-flags/colored-session-opt-error.svg
index 69f452f29f3..136c6fa5628 100644
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.svg
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.svg
@@ -1,7 +1,7 @@
-<svg width="750px" height="74px" xmlns="http://www.w3.org/2000/svg">
+<svg width="740px" height="74px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-yellow { fill: #AA5500 }
     .container {
       padding: 0 10px;
diff --git a/tests/ui/diagnostic-flags/terminal_urls.rs b/tests/ui/diagnostic-flags/terminal_urls.rs
index 3c74e992395..631512ab579 100644
--- a/tests/ui/diagnostic-flags/terminal_urls.rs
+++ b/tests/ui/diagnostic-flags/terminal_urls.rs
@@ -1,4 +1,4 @@
-//@ compile-flags: -Zterminal-urls=yes
+//@ compile-flags: -Zterminal-urls=yes --error-format=human --color=always
 fn main() {
-    let () = 4; //~ ERROR
+    let () = 4;
 }
diff --git a/tests/ui/diagnostic-flags/terminal_urls.stderr b/tests/ui/diagnostic-flags/terminal_urls.stderr
deleted file mode 100644
index e5dfcdf6431..00000000000
--- a/tests/ui/diagnostic-flags/terminal_urls.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error[]8;;https://doc.rust-lang.org/error_codes/E0308.htmlE0308]8;;]: mismatched types
-  --> $DIR/terminal_urls.rs:3:9
-   |
-LL |     let () = 4;
-   |         ^^   - this expression has type `{integer}`
-   |         |
-   |         expected integer, found `()`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/diagnostic-flags/terminal_urls.svg b/tests/ui/diagnostic-flags/terminal_urls.svg
new file mode 100644
index 00000000000..fcb65637c4a
--- /dev/null
+++ b/tests/ui/diagnostic-flags/terminal_urls.svg
@@ -0,0 +1,48 @@
+<svg width="740px" height="236px" xmlns="http://www.w3.org/2000/svg">
+  <style>
+    .fg { fill: #AAAAAA }
+    .bg { fill: #000000 }
+    .fg-ansi256-009 { fill: #FF5555 }
+    .fg-ansi256-012 { fill: #5555FF }
+    .container {
+      padding: 0 10px;
+      line-height: 18px;
+    }
+    .bold { font-weight: bold; }
+    tspan {
+      font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+      white-space: pre;
+      line-height: 18px;
+    }
+  </style>
+
+  <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
+
+  <text xml:space="preserve" class="container fg">
+    <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[</tspan><tspan class="fg-ansi256-009 bold"><a href="https://doc.rust-lang.org/error_codes/E0308.html">E0308</a></tspan><tspan class="fg-ansi256-009 bold">]</tspan><tspan class="bold">: mismatched types</tspan>
+</tspan>
+    <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-012 bold">--&gt; </tspan><tspan>$DIR/terminal_urls.rs:3:9</tspan>
+</tspan>
+    <tspan x="10px" y="64px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="82px"><tspan class="fg-ansi256-012 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>     let () = 4;</tspan>
+</tspan>
+    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">^^</tspan><tspan>   </tspan><tspan class="fg-ansi256-012 bold">-</tspan><tspan> </tspan><tspan class="fg-ansi256-012 bold">this expression has type `{integer}`</tspan>
+</tspan>
+    <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-012 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `()`</tspan>
+</tspan>
+    <tspan x="10px" y="154px">
+</tspan>
+    <tspan x="10px" y="172px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="bold">: aborting due to 1 previous error</tspan>
+</tspan>
+    <tspan x="10px" y="190px">
+</tspan>
+    <tspan x="10px" y="208px"><tspan class="bold">For more information about this error, try `rustc --explain E0308`.</tspan>
+</tspan>
+    <tspan x="10px" y="226px">
+</tspan>
+  </text>
+
+</svg>
diff --git a/tests/ui/diagnostic-flags/terminal_urls.windows.svg b/tests/ui/diagnostic-flags/terminal_urls.windows.svg
new file mode 100644
index 00000000000..e7b46638399
--- /dev/null
+++ b/tests/ui/diagnostic-flags/terminal_urls.windows.svg
@@ -0,0 +1,49 @@
+<svg width="740px" height="236px" xmlns="http://www.w3.org/2000/svg">
+  <style>
+    .fg { fill: #AAAAAA }
+    .bg { fill: #000000 }
+    .fg-ansi256-009 { fill: #FF5555 }
+    .fg-ansi256-014 { fill: #55FFFF }
+    .fg-ansi256-015 { fill: #FFFFFF }
+    .container {
+      padding: 0 10px;
+      line-height: 18px;
+    }
+    .bold { font-weight: bold; }
+    tspan {
+      font: 14px SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
+      white-space: pre;
+      line-height: 18px;
+    }
+  </style>
+
+  <rect width="100%" height="100%" y="0" rx="4.5" class="bg" />
+
+  <text xml:space="preserve" class="container fg">
+    <tspan x="10px" y="28px"><tspan class="fg-ansi256-009 bold">error[</tspan><tspan class="fg-ansi256-009 bold"><a href="https://doc.rust-lang.org/error_codes/E0308.html">E0308</a></tspan><tspan class="fg-ansi256-009 bold">]</tspan><tspan class="fg-ansi256-015 bold">: mismatched types</tspan>
+</tspan>
+    <tspan x="10px" y="46px"><tspan>  </tspan><tspan class="fg-ansi256-014 bold">--&gt; </tspan><tspan>$DIR/terminal_urls.rs:3:9</tspan>
+</tspan>
+    <tspan x="10px" y="64px"><tspan>   </tspan><tspan class="fg-ansi256-014 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="82px"><tspan class="fg-ansi256-014 bold">LL</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan>     let () = 4;</tspan>
+</tspan>
+    <tspan x="10px" y="100px"><tspan>   </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">^^</tspan><tspan>   </tspan><tspan class="fg-ansi256-014 bold">-</tspan><tspan> </tspan><tspan class="fg-ansi256-014 bold">this expression has type `{integer}`</tspan>
+</tspan>
+    <tspan x="10px" y="118px"><tspan>   </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">|</tspan>
+</tspan>
+    <tspan x="10px" y="136px"><tspan>   </tspan><tspan class="fg-ansi256-014 bold">|</tspan><tspan>         </tspan><tspan class="fg-ansi256-009 bold">expected integer, found `()`</tspan>
+</tspan>
+    <tspan x="10px" y="154px">
+</tspan>
+    <tspan x="10px" y="172px"><tspan class="fg-ansi256-009 bold">error</tspan><tspan class="fg-ansi256-015 bold">: aborting due to 1 previous error</tspan>
+</tspan>
+    <tspan x="10px" y="190px">
+</tspan>
+    <tspan x="10px" y="208px"><tspan class="fg-ansi256-015 bold">For more information about this error, try `rustc --explain E0308`.</tspan>
+</tspan>
+    <tspan x="10px" y="226px">
+</tspan>
+  </text>
+
+</svg>
diff --git a/tests/ui/error-emitter/E0308-clarification.svg b/tests/ui/error-emitter/E0308-clarification.svg
index 9432e3a4ee9..03ee973882d 100644
--- a/tests/ui/error-emitter/E0308-clarification.svg
+++ b/tests/ui/error-emitter/E0308-clarification.svg
@@ -1,7 +1,7 @@
 <svg width="740px" height="668px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-012 { fill: #5555FF }
     .fg-magenta { fill: #AA00AA }
diff --git a/tests/ui/error-emitter/highlighting.svg b/tests/ui/error-emitter/highlighting.svg
index 19818ab6146..d414f042f0a 100644
--- a/tests/ui/error-emitter/highlighting.svg
+++ b/tests/ui/error-emitter/highlighting.svg
@@ -1,7 +1,7 @@
 <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/error-emitter/highlighting.windows.svg b/tests/ui/error-emitter/highlighting.windows.svg
index f891bc1d2a6..92f9055cd1d 100644
--- a/tests/ui/error-emitter/highlighting.windows.svg
+++ b/tests/ui/error-emitter/highlighting.windows.svg
@@ -1,7 +1,7 @@
 <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-014 { fill: #55FFFF }
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.svg
index dd84234236d..5ffdc5a53fa 100644
--- a/tests/ui/error-emitter/multiline-multipart-suggestion.svg
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.svg
@@ -1,7 +1,7 @@
 <svg width="1306px" height="866px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg
index 144e57165da..37dc37e3e04 100644
--- a/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg
+++ b/tests/ui/error-emitter/multiline-multipart-suggestion.windows.svg
@@ -1,7 +1,7 @@
 <svg width="1306px" height="866px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-014 { fill: #55FFFF }
diff --git a/tests/ui/error-emitter/multiline-removal-suggestion.svg b/tests/ui/error-emitter/multiline-removal-suggestion.svg
index 7a88ac55b23..a774d558b58 100644
--- a/tests/ui/error-emitter/multiline-removal-suggestion.svg
+++ b/tests/ui/error-emitter/multiline-removal-suggestion.svg
@@ -1,7 +1,7 @@
-<svg width="2238px" height="3890px" xmlns="http://www.w3.org/2000/svg">
+<svg width="2288px" height="3890px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/error-emitter/unicode-output.svg b/tests/ui/error-emitter/unicode-output.svg
index b253fff643b..bda4d1a2f28 100644
--- a/tests/ui/error-emitter/unicode-output.svg
+++ b/tests/ui/error-emitter/unicode-output.svg
@@ -1,7 +1,7 @@
 <svg width="785px" height="434px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
index 73acb072ac5..6077dbdc200 100644
--- a/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
+++ b/tests/ui/impl-trait/diagnostics/highlight-difference-between-expected-trait-and-found-trait.svg
@@ -1,7 +1,7 @@
-<svg width="1188px" height="398px" xmlns="http://www.w3.org/2000/svg">
+<svg width="1096px" height="398px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/iterators/issue-58952-filter-type-length.rs b/tests/ui/iterators/issue-58952-filter-type-length.rs
index 6730865b6c7..525a2e39a91 100644
--- a/tests/ui/iterators/issue-58952-filter-type-length.rs
+++ b/tests/ui/iterators/issue-58952-filter-type-length.rs
@@ -2,7 +2,7 @@
 
 //! This snippet causes the type length to blowup exponentially,
 //! so check that we don't accidentally exceed the type length limit.
-// FIXME: Once the size of iterator adaptors is further reduced,
+// FIXME: Once the size of iterator adapters is further reduced,
 // increase the complexity of this test.
 use std::collections::VecDeque;
 
diff --git a/tests/ui/panic-runtime/auxiliary/needs-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-abort.rs
index 21f862e4b43..cba4907dbb6 100644
--- a/tests/ui/panic-runtime/auxiliary/needs-abort.rs
+++ b/tests/ui/panic-runtime/auxiliary/needs-abort.rs
@@ -1,5 +1,7 @@
 //@ compile-flags:-C panic=abort
 //@ no-prefer-dynamic
 
+#![feature(no_core)]
 #![crate_type = "rlib"]
 #![no_std]
+#![no_core]
diff --git a/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs
new file mode 100644
index 00000000000..4a41d16faa0
--- /dev/null
+++ b/tests/ui/panic-runtime/auxiliary/needs-immediate-abort.rs
@@ -0,0 +1,7 @@
+//@ compile-flags:-C panic=immediate-abort -Zunstable-options
+//@ no-prefer-dynamic
+
+#![feature(no_core)]
+#![crate_type = "rlib"]
+#![no_std]
+#![no_core]
diff --git a/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs b/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs
new file mode 100644
index 00000000000..295876fec52
--- /dev/null
+++ b/tests/ui/panic-runtime/auxiliary/needs-unwind-immediate-abort.rs
@@ -0,0 +1,18 @@
+//@ compile-flags:-C panic=unwind
+//@ no-prefer-dynamic
+//@ add-core-stubs
+
+#![crate_type = "rlib"]
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+
+extern crate minicore;
+
+extern "C-unwind" fn foo() {}
+
+#[inline]
+fn bar() {
+    let ptr: extern "C-unwind" fn() = foo;
+    ptr();
+}
diff --git a/tests/ui/panic-runtime/bad-panic-flag1.rs b/tests/ui/panic-runtime/bad-panic-flag1.rs
index 117935847cb..575e30f785c 100644
--- a/tests/ui/panic-runtime/bad-panic-flag1.rs
+++ b/tests/ui/panic-runtime/bad-panic-flag1.rs
@@ -2,4 +2,4 @@
 
 fn main() {}
 
-//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected
+//~? ERROR incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected
diff --git a/tests/ui/panic-runtime/bad-panic-flag1.stderr b/tests/ui/panic-runtime/bad-panic-flag1.stderr
index 013373c6f93..c30598bba53 100644
--- a/tests/ui/panic-runtime/bad-panic-flag1.stderr
+++ b/tests/ui/panic-runtime/bad-panic-flag1.stderr
@@ -1,2 +1,2 @@
-error: incorrect value `foo` for codegen option `panic` - either `unwind` or `abort` was expected
+error: incorrect value `foo` for codegen option `panic` - either `unwind`, `abort`, or `immediate-abort` was expected
 
diff --git a/tests/ui/panic-runtime/bad-panic-flag2.rs b/tests/ui/panic-runtime/bad-panic-flag2.rs
index b5d0442a033..4e34da217d7 100644
--- a/tests/ui/panic-runtime/bad-panic-flag2.rs
+++ b/tests/ui/panic-runtime/bad-panic-flag2.rs
@@ -2,4 +2,4 @@
 
 fn main() {}
 
-//~? ERROR codegen option `panic` requires either `unwind` or `abort`
+//~? ERROR codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort`
diff --git a/tests/ui/panic-runtime/bad-panic-flag2.stderr b/tests/ui/panic-runtime/bad-panic-flag2.stderr
index 6ab94ea704d..c8d12749c5d 100644
--- a/tests/ui/panic-runtime/bad-panic-flag2.stderr
+++ b/tests/ui/panic-runtime/bad-panic-flag2.stderr
@@ -1,2 +1,2 @@
-error: codegen option `panic` requires either `unwind` or `abort` (C panic=<value>)
+error: codegen option `panic` requires either `unwind`, `abort`, or `immediate-abort` (C panic=<value>)
 
diff --git a/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs b/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs
new file mode 100644
index 00000000000..94dc7c5671e
--- /dev/null
+++ b/tests/ui/panic-runtime/immediate-abort-default-sysroot.rs
@@ -0,0 +1,15 @@
+//@ build-fail
+//@ aux-build:needs-unwind.rs
+//@ compile-flags:-C panic=immediate-abort -Zunstable-options
+//@ no-prefer-dynamic
+
+extern crate needs_unwind;
+
+// immediate-abort does not require any panic runtime, so trying to build a binary crate with
+// panic=immediate-abort and the precompiled sysroot will fail to link, because no panic runtime
+// provides the panic entrypoints used by sysroot crates.
+// This test ensures that we get a clean compile error instead of a linker error.
+
+fn main() {}
+
+//~? ERROR the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
diff --git a/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr b/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr
new file mode 100644
index 00000000000..bd6bdd8b667
--- /dev/null
+++ b/tests/ui/panic-runtime/immediate-abort-default-sysroot.stderr
@@ -0,0 +1,4 @@
+error: the crate `core` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs b/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs
new file mode 100644
index 00000000000..78977c60be9
--- /dev/null
+++ b/tests/ui/panic-runtime/need-abort-got-immediate-abort.rs
@@ -0,0 +1,21 @@
+//@ build-fail
+//@ aux-build:needs-abort.rs
+//@ compile-flags:-Cpanic=immediate-abort -Zunstable-options
+//@ no-prefer-dynamic
+//@ add-core-stubs
+//@ core-stubs-compile-flags: -Cpanic=immediate-abort -Zunstable-options
+
+#![feature(no_core)]
+#![no_std]
+#![no_main]
+#![no_core]
+
+extern crate minicore;
+extern crate needs_abort;
+
+#[no_mangle]
+extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
+    0
+}
+
+//~? ERROR the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
diff --git a/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr b/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr
new file mode 100644
index 00000000000..65a26b676b9
--- /dev/null
+++ b/tests/ui/panic-runtime/need-abort-got-immediate-abort.stderr
@@ -0,0 +1,4 @@
+error: the crate `needs_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs b/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs
new file mode 100644
index 00000000000..1c5f597a3f9
--- /dev/null
+++ b/tests/ui/panic-runtime/need-immediate-abort-got-abort.rs
@@ -0,0 +1,20 @@
+//@ build-fail
+//@ aux-build:needs-immediate-abort.rs
+//@ compile-flags:-C panic=abort
+//@ no-prefer-dynamic
+//@ add-core-stubs
+//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
+
+#![feature(no_core)]
+#![no_std]
+#![no_main]
+#![no_core]
+
+extern crate minicore;
+extern crate needs_immediate_abort;
+
+extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 {
+    0
+}
+
+//~? ERROR the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr b/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr
new file mode 100644
index 00000000000..8dcf120cb9f
--- /dev/null
+++ b/tests/ui/panic-runtime/need-immediate-abort-got-abort.stderr
@@ -0,0 +1,4 @@
+error: the crate `need_immediate_abort_got_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs
new file mode 100644
index 00000000000..24d521230d4
--- /dev/null
+++ b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.rs
@@ -0,0 +1,20 @@
+//@ build-fail
+//@ needs-unwind
+//@ aux-build:needs-immediate-abort.rs
+//@ no-prefer-dynamic
+//@ add-core-stubs
+//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
+
+#![feature(no_core)]
+#![no_std]
+#![no_main]
+#![no_core]
+
+extern crate minicore;
+extern crate needs_immediate_abort;
+
+extern "C" fn main(argc: i32, argv: *const *const u8) -> i32 {
+    0
+}
+
+//~? ERROR the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort`
diff --git a/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr
new file mode 100644
index 00000000000..740fc80a77d
--- /dev/null
+++ b/tests/ui/panic-runtime/need-immediate-abort-got-unwind.stderr
@@ -0,0 +1,4 @@
+error: the crate `need_immediate_abort_got_unwind` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs
new file mode 100644
index 00000000000..5aec028a46c
--- /dev/null
+++ b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.rs
@@ -0,0 +1,21 @@
+//@ build-fail
+//@ aux-build:needs-unwind-immediate-abort.rs
+//@ compile-flags:-C panic=immediate-abort -Zunstable-options
+//@ no-prefer-dynamic
+//@ add-core-stubs
+//@ core-stubs-compile-flags: -Zunstable-options -Cpanic=immediate-abort
+
+#![feature(no_core)]
+#![no_std]
+#![no_main]
+#![no_core]
+
+extern crate minicore;
+extern crate needs_unwind_immediate_abort;
+
+#[no_mangle]
+extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 {
+    0
+}
+
+//~? ERROR the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
diff --git a/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr
new file mode 100644
index 00000000000..8b3747d644f
--- /dev/null
+++ b/tests/ui/panic-runtime/need-unwind-got-immediate-abort.stderr
@@ -0,0 +1,4 @@
+error: the crate `needs_unwind_immediate_abort` was compiled with a panic strategy which is incompatible with `immediate-abort`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/proc-macro/panic-abort.rs b/tests/ui/proc-macro/panic-abort.rs
index 58e1d006433..adedba4ebca 100644
--- a/tests/ui/proc-macro/panic-abort.rs
+++ b/tests/ui/proc-macro/panic-abort.rs
@@ -2,4 +2,4 @@
 //@ force-host
 //@ check-pass
 
-//~? WARN building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+//~? WARN building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
diff --git a/tests/ui/proc-macro/panic-abort.stderr b/tests/ui/proc-macro/panic-abort.stderr
index a6e18614f8f..3dd75768bc4 100644
--- a/tests/ui/proc-macro/panic-abort.stderr
+++ b/tests/ui/proc-macro/panic-abort.stderr
@@ -1,4 +1,4 @@
-warning: building proc macro crate with `panic=abort` may crash the compiler should the proc-macro panic
+warning: building proc macro crate with `panic=abort` or `panic=immediate-abort` may crash the compiler should the proc-macro panic
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/suggestions/incorrect-variant-literal.svg b/tests/ui/suggestions/incorrect-variant-literal.svg
index 2cab1f4b60f..4b952325cf7 100644
--- a/tests/ui/suggestions/incorrect-variant-literal.svg
+++ b/tests/ui/suggestions/incorrect-variant-literal.svg
@@ -1,7 +1,7 @@
 <svg width="886px" height="9524px" xmlns="http://www.w3.org/2000/svg">
   <style>
     .fg { fill: #AAAAAA }
-    .bg { background: #000000 }
+    .bg { fill: #000000 }
     .fg-ansi256-009 { fill: #FF5555 }
     .fg-ansi256-010 { fill: #55FF55 }
     .fg-ansi256-012 { fill: #5555FF }
diff --git a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs
index 6567f275240..2f108daf1e5 100644
--- a/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs
+++ b/tests/ui/traits/next-solver/typeck/normalize-in-upvar-collection.rs
@@ -1,7 +1,7 @@
 //@ compile-flags: -Znext-solver
 //@ check-pass
 
-// Fixes a regression in icu_provider_adaptors where we weren't normalizing the
+// Fixes a regression in icu_provider_adapters where we weren't normalizing the
 // return type of a function type before performing a `Ty::builtin_deref` call,
 // leading to an ICE.