about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock186
-rw-r--r--compiler/rustc_ast/src/token.rs73
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_borrowck/src/borrow_set.rs2
-rw-r--r--compiler/rustc_borrowck/src/borrowck_errors.rs2
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs6
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs1
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs10
-rw-r--r--compiler/rustc_borrowck/src/nll.rs1
-rw-r--r--compiler/rustc_borrowck/src/polonius/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs6
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs55
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs3
-rw-r--r--compiler/rustc_const_eval/messages.ftl2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs76
-rw-r--r--compiler/rustc_const_eval/src/errors.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/projection.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs10
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/errors.rs7
-rw-r--r--compiler/rustc_expand/src/expand.rs14
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs25
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs55
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs4
-rw-r--r--compiler/rustc_feature/src/lib.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs60
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/context/diagnostics.rs10
-rw-r--r--compiler/rustc_lint/src/lints.rs21
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs43
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs4
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs2
-rw-r--r--compiler/rustc_parse/messages.ftl9
-rw-r--r--compiler/rustc_parse/src/errors.rs31
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs28
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs64
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs21
-rw-r--r--compiler/rustc_passes/src/errors.rs11
-rw-r--r--compiler/rustc_resolve/src/macros.rs7
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/asm/arm.rs80
-rw-r--r--library/core/src/sync/atomic.rs50
-rw-r--r--library/std/src/sys/pal/unix/fs.rs50
-rw-r--r--library/std/src/sys/pal/unix/os.rs6
-rw-r--r--src/bootstrap/download-ci-llvm-stamp2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs2
-rw-r--r--src/bootstrap/src/core/builder.rs28
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
-rw-r--r--src/ci/docker/README.md16
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile35
-rw-r--r--src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig15
-rw-r--r--src/ci/docker/scripts/crosstool-ng-git.sh17
-rw-r--r--src/ci/github-actions/jobs.yml3
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rwxr-xr-xsrc/etc/pre-push.sh2
-rw-r--r--src/tools/build-manifest/README.md2
-rw-r--r--src/tools/build-manifest/src/main.rs2
-rw-r--r--src/tools/build_helper/src/util.rs28
-rw-r--r--src/tools/compiletest/src/header.rs1
-rw-r--r--src/tools/compiletest/src/header/needs.rs26
-rw-r--r--src/tools/miri/src/diagnostics.rs4
-rw-r--r--src/tools/miri/tests/fail/extern-type-field-offset.stderr4
-rw-r--r--src/tools/rustfmt/src/items.rs1
-rw-r--r--src/tools/rustfmt/src/overflow.rs15
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs6
-rw-r--r--src/tools/rustfmt/src/spanned.rs9
-rw-r--r--src/tools/rustfmt/src/types.rs26
-rw-r--r--src/tools/rustfmt/tests/source/precise-capturing.rs9
-rw-r--r--src/tools/rustfmt/tests/target/precise-capturing.rs55
-rw-r--r--src/tools/tidy/Cargo.toml1
-rw-r--r--src/tools/tidy/src/deps.rs14
-rw-r--r--src/tools/tidy/src/extdeps.rs15
-rw-r--r--tests/run-make/symlinked-extern/rmake.rs1
-rw-r--r--tests/run-make/symlinked-libraries/rmake.rs1
-rw-r--r--tests/run-make/symlinked-rlib/rmake.rs1
-rw-r--r--tests/ui/asm/arm-low-dreg.rs33
-rw-r--r--tests/ui/attributes/unsafe/double-unsafe-attributes.stderr12
-rw-r--r--tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr2
-rw-r--r--tests/ui/consts/const-eval/validation-ice-extern-type-field.rs15
-rw-r--r--tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr9
-rw-r--r--tests/ui/delegation/glob-traitless-qpath.rs11
-rw-r--r--tests/ui/delegation/glob-traitless-qpath.stderr14
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.fixed34
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.rs34
-rw-r--r--tests/ui/mismatched_types/mismatched-types-issue-126222.stderr51
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs9
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr21
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs12
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed61
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs61
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr93
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr13
-rw-r--r--tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs12
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr6
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr6
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.rs2
-rw-r--r--tests/ui/sized/stack-overflow-trait-infer-98842.stderr25
105 files changed, 1426 insertions, 563 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9d1481ec768..241a37588b4 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -266,7 +266,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -601,9 +601,9 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.5"
+version = "4.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2020fa13af48afc65a9a87335bda648309ab3d154cd03c7ff95b378c7ed39c4"
+checksum = "fbca90c87c2a04da41e95d1856e8bcd22f159bdbfa147314d2ce5218057b0e58"
 dependencies = [
  "clap",
 ]
@@ -617,7 +617,7 @@ dependencies = [
  "heck 0.5.0",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -644,7 +644,7 @@ dependencies = [
  "regex",
  "rustc_tools_util",
  "serde",
- "syn 2.0.66",
+ "syn 2.0.67",
  "tempfile",
  "termize",
  "tokio",
@@ -755,7 +755,7 @@ dependencies = [
  "nom",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -991,7 +991,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1002,7 +1002,7 @@ checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1028,7 +1028,7 @@ version = "0.1.81"
 dependencies = [
  "itertools",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1069,7 +1069,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1079,7 +1079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b"
 dependencies = [
  "derive_builder_core",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1090,7 +1090,7 @@ checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1102,7 +1102,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1180,13 +1180,13 @@ dependencies = [
 
 [[package]]
 name = "displaydoc"
-version = "0.2.4"
+version = "0.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
+checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1506,7 +1506,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1739,7 +1739,7 @@ dependencies = [
  "markup5ever",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1781,18 +1781,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "icu_collections"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
-dependencies = [
- "displaydoc",
- "yoke",
- "zerofrom",
- "zerovec",
-]
-
-[[package]]
 name = "icu_list"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1846,51 +1834,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e"
 
 [[package]]
-name = "icu_normalizer"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_normalizer_data",
- "icu_properties",
- "icu_provider",
- "smallvec",
- "utf16_iter",
- "utf8_iter",
- "write16",
- "zerovec",
-]
-
-[[package]]
-name = "icu_normalizer_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516"
-
-[[package]]
-name = "icu_properties"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036"
-dependencies = [
- "displaydoc",
- "icu_collections",
- "icu_locid_transform",
- "icu_properties_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_properties_data"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569"
-
-[[package]]
 name = "icu_provider"
 version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1928,7 +1871,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -1939,14 +1882,12 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "idna"
-version = "1.0.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
 dependencies = [
- "icu_normalizer",
- "icu_properties",
- "smallvec",
- "utf8_iter",
+ "unicode-bidi",
+ "unicode-normalization",
 ]
 
 [[package]]
@@ -2146,9 +2087,9 @@ dependencies = [
 
 [[package]]
 name = "lazy_static"
-version = "1.4.0"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
 
 [[package]]
 name = "leb128"
@@ -2521,9 +2462,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
+checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08"
 dependencies = [
  "adler",
  "compiler_builtins",
@@ -2949,7 +2890,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -3141,9 +3082,9 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.85"
+version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
+checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
 dependencies = [
  "unicode-ident",
 ]
@@ -4045,7 +3986,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "unic-langid",
 ]
 
@@ -4179,7 +4120,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -4326,7 +4267,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "synstructure",
 ]
 
@@ -4905,7 +4846,7 @@ version = "0.0.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "synstructure",
 ]
 
@@ -5003,7 +4944,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -5153,7 +5094,7 @@ checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -5446,9 +5387,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.66"
+version = "2.0.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
+checksum = "ff8655ed1d86f3af4ee3fd3263786bc14245ad17c4c7e85ba7187fb3ae028c90"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -5463,7 +5404,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -5640,7 +5581,7 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -5678,6 +5619,7 @@ dependencies = [
 name = "tidy"
 version = "0.1.0"
 dependencies = [
+ "build_helper",
  "cargo_metadata 0.15.4",
  "fluent-syntax",
  "ignore",
@@ -5854,7 +5796,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -6054,7 +5996,7 @@ checksum = "1ed7f4237ba393424195053097c1516bd4590dc82b84f2f97c5c69e12704555b"
 dependencies = [
  "proc-macro-hack",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "unic-langid-impl",
 ]
 
@@ -6075,6 +6017,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "unicode-bidi"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
+
+[[package]]
 name = "unicode-ident"
 version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6175,9 +6123,9 @@ dependencies = [
 
 [[package]]
 name = "url"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56"
+checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -6191,24 +6139,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
-name = "utf16_iter"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
-
-[[package]]
 name = "utf8-width"
 version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3"
 
 [[package]]
-name = "utf8_iter"
-version = "1.0.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
-
-[[package]]
 name = "utf8parse"
 version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6292,7 +6228,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "wasm-bindgen-shared",
 ]
 
@@ -6314,7 +6250,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -6395,7 +6331,7 @@ dependencies = [
  "rayon",
  "serde",
  "serde_json",
- "syn 2.0.66",
+ "syn 2.0.67",
  "windows-metadata",
 ]
 
@@ -6572,12 +6508,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "write16"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
-
-[[package]]
 name = "writeable"
 version = "0.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -6647,7 +6577,7 @@ checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "synstructure",
 ]
 
@@ -6668,7 +6598,7 @@ checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
 
 [[package]]
@@ -6688,7 +6618,7 @@ checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
  "synstructure",
 ]
 
@@ -6711,5 +6641,5 @@ checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.66",
+ "syn 2.0.67",
 ]
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index cc66cc87652..efe19566152 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -1,6 +1,8 @@
 pub use BinOpToken::*;
 pub use LitKind::*;
 pub use Nonterminal::*;
+pub use NtExprKind::*;
+pub use NtPatKind::*;
 pub use TokenKind::*;
 
 use crate::ast;
@@ -871,6 +873,27 @@ impl PartialEq<TokenKind> for Token {
     }
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
+pub enum NtPatKind {
+    // Matches or-patterns. Was written using `pat` in edition 2021 or later.
+    PatWithOr,
+    // Doesn't match or-patterns.
+    // - `inferred`: was written using `pat` in edition 2015 or 2018.
+    // - `!inferred`: was written using `pat_param`.
+    PatParam { inferred: bool },
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable)]
+pub enum NtExprKind {
+    // Matches expressions using the post-edition 2024. Was written using
+    // `expr` in edition 2024 or later.
+    Expr,
+    // Matches expressions using the pre-edition 2024 rules.
+    // - `inferred`: was written using `expr` in edition 2021 or earlier.
+    // - `!inferred`: was written using `expr_2021`.
+    Expr2021 { inferred: bool },
+}
+
 #[derive(Clone, Encodable, Decodable)]
 /// For interpolation during macro expansion.
 pub enum Nonterminal {
@@ -892,19 +915,8 @@ pub enum NonterminalKind {
     Item,
     Block,
     Stmt,
-    PatParam {
-        /// Keep track of whether the user used `:pat_param` or `:pat` and we inferred it from the
-        /// edition of the span. This is used for diagnostics.
-        inferred: bool,
-    },
-    PatWithOr,
-    Expr,
-    /// Matches an expression using the rules from edition 2021 and earlier.
-    Expr2021 {
-        /// Keep track of whether the user used `:expr` or `:expr_2021` and we inferred it from the
-        /// edition of the span. This is used for diagnostics AND feature gating.
-        inferred: bool,
-    },
+    Pat(NtPatKind),
+    Expr(NtExprKind),
     Ty,
     Ident,
     Lifetime,
@@ -926,20 +938,22 @@ impl NonterminalKind {
             sym::item => NonterminalKind::Item,
             sym::block => NonterminalKind::Block,
             sym::stmt => NonterminalKind::Stmt,
-            sym::pat => match edition() {
-                Edition::Edition2015 | Edition::Edition2018 => {
-                    NonterminalKind::PatParam { inferred: true }
+            sym::pat => {
+                if edition().at_least_rust_2021() {
+                    NonterminalKind::Pat(PatWithOr)
+                } else {
+                    NonterminalKind::Pat(PatParam { inferred: true })
                 }
-                Edition::Edition2021 | Edition::Edition2024 => NonterminalKind::PatWithOr,
-            },
-            sym::pat_param => NonterminalKind::PatParam { inferred: false },
-            sym::expr => match edition() {
-                Edition::Edition2015 | Edition::Edition2018 | Edition::Edition2021 => {
-                    NonterminalKind::Expr2021 { inferred: true }
+            }
+            sym::pat_param => NonterminalKind::Pat(PatParam { inferred: false }),
+            sym::expr => {
+                if edition().at_least_rust_2024() {
+                    NonterminalKind::Expr(Expr)
+                } else {
+                    NonterminalKind::Expr(Expr2021 { inferred: true })
                 }
-                Edition::Edition2024 => NonterminalKind::Expr,
-            },
-            sym::expr_2021 => NonterminalKind::Expr2021 { inferred: false },
+            }
+            sym::expr_2021 => NonterminalKind::Expr(Expr2021 { inferred: false }),
             sym::ty => NonterminalKind::Ty,
             sym::ident => NonterminalKind::Ident,
             sym::lifetime => NonterminalKind::Lifetime,
@@ -951,15 +965,16 @@ impl NonterminalKind {
             _ => return None,
         })
     }
+
     fn symbol(self) -> Symbol {
         match self {
             NonterminalKind::Item => sym::item,
             NonterminalKind::Block => sym::block,
             NonterminalKind::Stmt => sym::stmt,
-            NonterminalKind::PatParam { inferred: false } => sym::pat_param,
-            NonterminalKind::PatParam { inferred: true } | NonterminalKind::PatWithOr => sym::pat,
-            NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: true } => sym::expr,
-            NonterminalKind::Expr2021 { inferred: false } => sym::expr_2021,
+            NonterminalKind::Pat(PatParam { inferred: true } | PatWithOr) => sym::pat,
+            NonterminalKind::Pat(PatParam { inferred: false }) => sym::pat_param,
+            NonterminalKind::Expr(Expr2021 { inferred: true } | Expr) => sym::expr,
+            NonterminalKind::Expr(Expr2021 { inferred: false }) => sym::expr_2021,
             NonterminalKind::Ty => sym::ty,
             NonterminalKind::Ident => sym::ident,
             NonterminalKind::Lifetime => sym::lifetime,
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 79717c969d7..941bb78c0dd 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -899,7 +899,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
 
 impl<'a> Visitor<'a> for AstValidator<'a> {
     fn visit_attribute(&mut self, attr: &Attribute) {
-        validate_attr::check_attr(&self.session.psess, attr);
+        validate_attr::check_attr(&self.features, &self.session.psess, attr);
     }
 
     fn visit_ty(&mut self, ty: &'a Ty) {
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 3e6d0311b27..0bae1bd07a2 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -126,7 +126,7 @@ impl<'tcx> BorrowSet<'tcx> {
     ) -> Self {
         let mut visitor = GatherBorrows {
             tcx,
-            body: body,
+            body,
             location_map: Default::default(),
             activation_map: Default::default(),
             local_map: Default::default(),
diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs
index c1f75328272..8a2936c2657 100644
--- a/compiler/rustc_borrowck/src/borrowck_errors.rs
+++ b/compiler/rustc_borrowck/src/borrowck_errors.rs
@@ -213,7 +213,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> {
             via(msg_old),
         );
 
-        if msg_new == "" {
+        if msg_new.is_empty() {
             // If `msg_new` is empty, then this isn't a borrow of a union field.
             err.span_label(span, format!("{kind_new} borrow occurs here"));
             err.span_label(old_span, format!("{kind_old} borrow occurs here"));
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index ec7d4582a60..f2b5ddcd782 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -43,9 +43,9 @@ impl<'mir, 'tcx> ResultsVisitable<'tcx> for BorrowckResults<'mir, 'tcx> {
     }
 
     fn reset_to_block_entry(&self, state: &mut Self::FlowState, block: BasicBlock) {
-        state.borrows.clone_from(&self.borrows.entry_set_for_block(block));
-        state.uninits.clone_from(&self.uninits.entry_set_for_block(block));
-        state.ever_inits.clone_from(&self.ever_inits.entry_set_for_block(block));
+        state.borrows.clone_from(self.borrows.entry_set_for_block(block));
+        state.uninits.clone_from(self.uninits.entry_set_for_block(block));
+        state.ever_inits.clone_from(self.ever_inits.entry_set_for_block(block));
     }
 
     fn reconstruct_before_statement_effect(
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index 67c11ff4a5b..c214c52880a 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -895,7 +895,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
             for alias_ty in alias_tys {
                 if alias_ty.span.desugaring_kind().is_some() {
                     // Skip `async` desugaring `impl Future`.
-                    ()
                 }
                 if let TyKind::TraitObject(_, lt, _) = alias_ty.kind {
                     if lt.ident.name == kw::Empty {
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index 77fb9fb4315..25a0d40218b 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -519,7 +519,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                     }
 
                     // Otherwise, let's descend into the referent types.
-                    search_stack.push((*referent_ty, &referent_hir_ty.ty));
+                    search_stack.push((*referent_ty, referent_hir_ty.ty));
                 }
 
                 // Match up something like `Foo<'1>`
@@ -558,7 +558,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 }
 
                 (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => {
-                    search_stack.push((*mut_ty, &mut_hir_ty.ty));
+                    search_stack.push((*mut_ty, mut_hir_ty.ty));
                 }
 
                 _ => {
@@ -652,7 +652,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         let upvar_index = self.regioncx.get_upvar_index_for_region(self.infcx.tcx, fr)?;
         let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
             self.infcx.tcx,
-            &self.upvars,
+            self.upvars,
             upvar_index,
         );
         let region_name = self.synthesize_region_name();
@@ -717,7 +717,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                             .output;
                         span = output.span();
                         if let hir::FnRetTy::Return(ret) = output {
-                            hir_ty = Some(self.get_future_inner_return_ty(*ret));
+                            hir_ty = Some(self.get_future_inner_return_ty(ret));
                         }
                         " of async function"
                     }
@@ -958,7 +958,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         {
             let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region(
                 self.infcx.tcx,
-                &self.upvars,
+                self.upvars,
                 upvar_index,
             );
             let region_name = self.synthesize_region_name();
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index 5d7ce548469..923cf7e9405 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -114,7 +114,6 @@ pub(crate) fn compute_regions<'cx, 'tcx>(
             move_data,
             elements,
             upvars,
-            polonius_input,
         );
 
     // Create the region inference context, taking ownership of the
diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs
index 9984f76e6d4..c590104978c 100644
--- a/compiler/rustc_borrowck/src/polonius/mod.rs
+++ b/compiler/rustc_borrowck/src/polonius/mod.rs
@@ -43,8 +43,8 @@ pub(crate) fn emit_facts<'tcx>(
     emit_universal_region_facts(
         all_facts,
         borrow_set,
-        &universal_regions,
-        &universal_region_relations,
+        universal_regions,
+        universal_region_relations,
     );
     emit_cfg_and_loan_kills_facts(all_facts, tcx, location_table, body, borrow_set);
     emit_loan_invalidations_facts(all_facts, tcx, location_table, body, borrow_set);
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index bf1c1b1433e..c56eaaff076 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -344,7 +344,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
 
     for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
         let reg_var = ty::RegionVid::from_usize(reg_var_idx);
-        let origin = var_to_origin.get(&reg_var).unwrap_or_else(|| &RegionCtxt::Unknown);
+        let origin = var_to_origin.get(&reg_var).unwrap_or(&RegionCtxt::Unknown);
         components[scc_idx.as_usize()].insert((reg_var, *origin));
     }
 
@@ -2216,7 +2216,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         // #114907 where this happens via liveness and dropck outlives results.
         // Therefore, we return a default value in case that happens, which should at worst emit a
         // suboptimal error, instead of the ICE.
-        self.universe_causes.get(&universe).cloned().unwrap_or_else(|| UniverseInfo::other())
+        self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other)
     }
 
     /// Tries to find the terminator of the loop in which the region 'r' resides.
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 51c3648d730..67e5c8352df 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -418,9 +418,7 @@ fn check_opaque_type_parameter_valid<'tcx>(
             let opaque_param = opaque_generics.param_at(i, tcx);
             let kind = opaque_param.kind.descr();
 
-            if let Err(guar) = opaque_env.param_is_error(i) {
-                return Err(guar);
-            }
+            opaque_env.param_is_error(i)?;
 
             return Err(tcx.dcx().emit_err(NonGenericOpaqueTypeParam {
                 ty: arg,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index 8b863efad6c..b777e01f7a6 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -12,9 +12,7 @@ use rustc_mir_dataflow::ResultsCursor;
 use std::rc::Rc;
 
 use crate::{
-    constraints::OutlivesConstraintSet,
-    facts::{AllFacts, AllFactsExt},
-    region_infer::values::LivenessValues,
+    constraints::OutlivesConstraintSet, region_infer::values::LivenessValues,
     universal_regions::UniversalRegions,
 };
 
@@ -38,7 +36,6 @@ pub(super) fn generate<'mir, 'tcx>(
     elements: &Rc<DenseLocationMap>,
     flow_inits: &mut ResultsCursor<'mir, 'tcx, MaybeInitializedPlaces<'mir, 'tcx>>,
     move_data: &MoveData<'tcx>,
-    use_polonius: bool,
 ) {
     debug!("liveness::generate");
 
@@ -49,11 +46,8 @@ pub(super) fn generate<'mir, 'tcx>(
     );
     let (relevant_live_locals, boring_locals) =
         compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
-    let facts_enabled = use_polonius || AllFacts::enabled(typeck.tcx());
 
-    if facts_enabled {
-        polonius::populate_access_facts(typeck, body, move_data);
-    };
+    polonius::populate_access_facts(typeck, body, move_data);
 
     trace::trace(
         typeck,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index d8f03a07a63..a009e28a0dd 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -87,10 +87,10 @@ pub(super) fn populate_access_facts<'a, 'tcx>(
     body: &Body<'tcx>,
     move_data: &MoveData<'tcx>,
 ) {
-    debug!("populate_access_facts()");
-    let location_table = typeck.borrowck_context.location_table;
-
     if let Some(facts) = typeck.borrowck_context.all_facts.as_mut() {
+        debug!("populate_access_facts()");
+        let location_table = typeck.borrowck_context.location_table;
+
         let mut extractor = UseFactsExtractor {
             var_defined_at: &mut facts.var_defined_at,
             var_used_at: &mut facts.var_used_at,
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 50843c602cc..359c4ea0eb1 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -217,35 +217,52 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
     /// Add facts for all locals with free regions, since regions may outlive
     /// the function body only at certain nodes in the CFG.
     fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) -> Option<()> {
-        let drop_used = self
-            .cx
-            .typeck
-            .borrowck_context
-            .all_facts
-            .as_ref()
-            .map(|facts| facts.var_dropped_at.clone())?;
+        // This collect is more necessary than immediately apparent
+        // because these facts go into `add_drop_live_facts_for()`,
+        // which also writes to `all_facts`, and so this is genuinely
+        // a simulatneous overlapping mutable borrow.
+        // FIXME for future hackers: investigate whether this is
+        // actually necessary; these facts come from Polonius
+        // and probably maybe plausibly does not need to go back in.
+        // It may be necessary to just pick out the parts of
+        // `add_drop_live_facts_for()` that make sense.
+        let facts_to_add: Vec<_> = {
+            let drop_used = &self.cx.typeck.borrowck_context.all_facts.as_ref()?.var_dropped_at;
+
+            let relevant_live_locals: FxIndexSet<_> =
+                relevant_live_locals.iter().copied().collect();
+
+            drop_used
+                .iter()
+                .filter_map(|(local, location_index)| {
+                    let local_ty = self.cx.body.local_decls[*local].ty;
+                    if relevant_live_locals.contains(local) || !local_ty.has_free_regions() {
+                        return None;
+                    }
 
-        let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect();
-
-        let locations = IntervalSet::new(self.cx.elements.num_points());
-
-        for (local, location_index) in drop_used {
-            if !relevant_live_locals.contains(&local) {
-                let local_ty = self.cx.body.local_decls[local].ty;
-                if local_ty.has_free_regions() {
                     let location = match self
                         .cx
                         .typeck
                         .borrowck_context
                         .location_table
-                        .to_location(location_index)
+                        .to_location(*location_index)
                     {
                         RichLocation::Start(l) => l,
                         RichLocation::Mid(l) => l,
                     };
-                    self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
-                }
-            }
+
+                    Some((*local, local_ty, location))
+                })
+                .collect()
+        };
+
+        // FIXME: these locations seem to have a special meaning (e.g. everywhere, at the end, ...), but I don't know which one. Please help me rename it to something descriptive!
+        // Also, if this IntervalSet is used in many places, it maybe should have a newtype'd
+        // name with a description of what it means for future mortals passing by.
+        let locations = IntervalSet::new(self.cx.elements.num_points());
+
+        for (local, local_ty, location) in facts_to_add {
+            self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
         }
         Some(())
     }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c7c1b2af6a7..81bde14a82f 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -133,7 +133,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
     move_data: &MoveData<'tcx>,
     elements: &Rc<DenseLocationMap>,
     upvars: &[&ty::CapturedPlace<'tcx>],
-    use_polonius: bool,
 ) -> MirTypeckResults<'tcx> {
     let implicit_region_bound = ty::Region::new_var(infcx.tcx, universal_regions.fr_fn_body);
     let mut constraints = MirTypeckRegionConstraints {
@@ -189,7 +188,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
     checker.equate_inputs_and_outputs(body, universal_regions, &normalized_inputs_and_output);
     checker.check_signature_annotation(body);
 
-    liveness::generate(&mut checker, body, elements, flow_inits, move_data, use_polonius);
+    liveness::generate(&mut checker, body, elements, flow_inits, move_data);
 
     translate_outlives_facts(&mut checker);
     let opaque_type_values = infcx.take_opaque_types();
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 1476fe285ef..cd269810741 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -89,6 +89,8 @@ const_eval_exact_div_has_remainder =
 
 const_eval_extern_static =
     cannot access extern static ({$did})
+const_eval_extern_type_field = `extern type` field does not have a known offset
+
 const_eval_fn_ptr_call =
     function pointers need an RFC before allowed to be called in {const_eval_const_context}s
 const_eval_for_loop_into_iter_non_const =
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index c60df06bb0e..d8efaa66415 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -386,33 +386,8 @@ fn eval_in_interpreter<'tcx, R: InterpretationResult<'tcx>>(
         CompileTimeMachine::new(CanAccessMutGlobal::from(is_static), CheckAlignment::Error),
     );
     let res = ecx.load_mir(cid.instance.def, cid.promoted);
-    res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body)).map_err(|error| {
-        let (error, backtrace) = error.into_parts();
-        backtrace.print_backtrace();
-
-        let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) {
-            ("static", String::new())
-        } else {
-            // If the current item has generics, we'd like to enrich the message with the
-            // instance and its args: to show the actual compile-time values, in addition to
-            // the expression, leading to the const eval error.
-            let instance = &cid.instance;
-            if !instance.args.is_empty() {
-                let instance = with_no_trimmed_paths!(instance.to_string());
-                ("const_with_path", instance)
-            } else {
-                ("const", String::new())
-            }
-        };
-
-        super::report(
-            *ecx.tcx,
-            error,
-            DUMMY_SP,
-            || super::get_span_and_frames(ecx.tcx, ecx.stack()),
-            |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
-        )
-    })
+    res.and_then(|body| eval_body_using_ecx(&mut ecx, cid, body))
+        .map_err(|error| report_eval_error(&ecx, cid, error))
 }
 
 #[inline(always)]
@@ -438,24 +413,61 @@ fn const_validate_mplace<'tcx>(
         ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)
             // Instead of just reporting the `InterpError` via the usual machinery, we give a more targeted
             // error about the validation failure.
-            .map_err(|error| report_validation_error(&ecx, error, alloc_id))?;
+            .map_err(|error| report_validation_error(&ecx, cid, error, alloc_id))?;
         inner = true;
     }
 
     Ok(())
 }
 
-#[inline(always)]
+#[inline(never)]
+fn report_eval_error<'tcx>(
+    ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    cid: GlobalId<'tcx>,
+    error: InterpErrorInfo<'tcx>,
+) -> ErrorHandled {
+    let (error, backtrace) = error.into_parts();
+    backtrace.print_backtrace();
+
+    let (kind, instance) = if ecx.tcx.is_static(cid.instance.def_id()) {
+        ("static", String::new())
+    } else {
+        // If the current item has generics, we'd like to enrich the message with the
+        // instance and its args: to show the actual compile-time values, in addition to
+        // the expression, leading to the const eval error.
+        let instance = &cid.instance;
+        if !instance.args.is_empty() {
+            let instance = with_no_trimmed_paths!(instance.to_string());
+            ("const_with_path", instance)
+        } else {
+            ("const", String::new())
+        }
+    };
+
+    super::report(
+        *ecx.tcx,
+        error,
+        DUMMY_SP,
+        || super::get_span_and_frames(ecx.tcx, ecx.stack()),
+        |span, frames| ConstEvalError { span, error_kind: kind, instance, frame_notes: frames },
+    )
+}
+
+#[inline(never)]
 fn report_validation_error<'tcx>(
     ecx: &InterpCx<'tcx, CompileTimeMachine<'tcx>>,
+    cid: GlobalId<'tcx>,
     error: InterpErrorInfo<'tcx>,
     alloc_id: AllocId,
 ) -> ErrorHandled {
+    if !matches!(error.kind(), InterpError::UndefinedBehavior(_)) {
+        // Some other error happened during validation, e.g. an unsupported operation.
+        return report_eval_error(ecx, cid, error);
+    }
+
     let (error, backtrace) = error.into_parts();
     backtrace.print_backtrace();
 
-    let ub_note = matches!(error, InterpError::UndefinedBehavior(_)).then(|| {});
-
     let bytes = ecx.print_alloc_bytes_for_diagnostics(alloc_id);
     let (size, align, _) = ecx.get_alloc_info(alloc_id);
     let raw_bytes = errors::RawBytesNote { size: size.bytes(), align: align.bytes(), bytes };
@@ -465,6 +477,6 @@ fn report_validation_error<'tcx>(
         error,
         DUMMY_SP,
         || crate::const_eval::get_span_and_frames(ecx.tcx, ecx.stack()),
-        move |span, frames| errors::ValidationFailure { span, ub_note, frames, raw_bytes },
+        move |span, frames| errors::ValidationFailure { span, ub_note: (), frames, raw_bytes },
     )
 }
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index 5fa48a59794..292d6ba9d08 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -425,7 +425,7 @@ pub struct ValidationFailure {
     #[primary_span]
     pub span: Span,
     #[note(const_eval_validation_failure_note)]
-    pub ub_note: Option<()>,
+    pub ub_note: (),
     #[subdiagnostic]
     pub frames: Vec<FrameNote>,
     #[subdiagnostic]
@@ -825,6 +825,7 @@ impl ReportErrorExt for UnsupportedOpInfo {
         use crate::fluent_generated::*;
         match self {
             UnsupportedOpInfo::Unsupported(s) => s.clone().into(),
+            UnsupportedOpInfo::ExternTypeField => const_eval_extern_type_field,
             UnsupportedOpInfo::UnsizedLocal => const_eval_unsized_local,
             UnsupportedOpInfo::OverwritePartialPointer(_) => const_eval_partial_pointer_overwrite,
             UnsupportedOpInfo::ReadPartialPointer(_) => const_eval_partial_pointer_copy,
@@ -845,7 +846,10 @@ impl ReportErrorExt for UnsupportedOpInfo {
             // `ReadPointerAsInt(Some(info))` is never printed anyway, it only serves as an error to
             // be further processed by validity checking which then turns it into something nice to
             // print. So it's not worth the effort of having diagnostics that can print the `info`.
-            UnsizedLocal | Unsupported(_) | ReadPointerAsInt(_) => {}
+            UnsizedLocal
+            | UnsupportedOpInfo::ExternTypeField
+            | Unsupported(_)
+            | ReadPointerAsInt(_) => {}
             OverwritePartialPointer(ptr) | ReadPartialPointer(ptr) => {
                 diag.arg("ptr", ptr);
             }
diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs
index efa01b54342..cfa814c810a 100644
--- a/compiler/rustc_const_eval/src/interpret/projection.rs
+++ b/compiler/rustc_const_eval/src/interpret/projection.rs
@@ -21,7 +21,7 @@ use rustc_target::abi::{self, VariantIdx};
 use tracing::{debug, instrument};
 
 use super::{
-    throw_ub, throw_unsup_format, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
+    throw_ub, throw_unsup, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
     Provenance, Scalar,
 };
 
@@ -186,8 +186,8 @@ where
                     (base_meta, offset)
                 }
                 None => {
-                    // We don't know the alignment of this field, so we cannot adjust.
-                    throw_unsup_format!("`extern type` does not have a known offset")
+                    // We cannot know the alignment of this field, so we cannot adjust.
+                    throw_unsup!(ExternTypeField)
                 }
             }
         } else {
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index ca8b9884933..add48e1b186 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -5,6 +5,7 @@
 //! to be const-safe.
 
 use std::fmt::Write;
+use std::hash::Hash;
 use std::num::NonZero;
 
 use either::{Left, Right};
@@ -17,7 +18,8 @@ use rustc_hir as hir;
 use rustc_middle::bug;
 use rustc_middle::mir::interpret::{
     ExpectedKind, InterpError, InvalidMetaKind, Misalignment, PointerKind, Provenance,
-    ValidationErrorInfo, ValidationErrorKind, ValidationErrorKind::*,
+    UnsupportedOpInfo, ValidationErrorInfo,
+    ValidationErrorKind::{self, *},
 };
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
@@ -26,8 +28,6 @@ use rustc_target::abi::{
     Abi, FieldIdx, Scalar as ScalarAbi, Size, VariantIdx, Variants, WrappingRange,
 };
 
-use std::hash::Hash;
-
 use super::{
     err_ub, format_interp_error, machine::AllocMap, throw_ub, AllocId, AllocKind, CheckInAllocMsg,
     GlobalAlloc, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemPlaceMeta, OpTy,
@@ -1028,7 +1028,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             Err(err)
                 if matches!(
                     err.kind(),
-                    err_ub!(ValidationError { .. }) | InterpError::InvalidProgram(_)
+                    err_ub!(ValidationError { .. })
+                        | InterpError::InvalidProgram(_)
+                        | InterpError::Unsupported(UnsupportedOpInfo::ExternTypeField)
                 ) =>
             {
                 Err(err)
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 6113580491e..cc0b110d2bc 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -61,6 +61,9 @@ expand_feature_removed =
 expand_glob_delegation_outside_impls =
     glob delegation is only supported in impls
 
+expand_glob_delegation_traitless_qpath =
+    qualified path without a trait in glob delegation
+
 expand_helper_attribute_name_invalid =
     `{$name}` cannot be a name of derive helper attribute
 
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index c883121fb40..0be7403f25b 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -449,6 +449,13 @@ pub(crate) struct GlobDelegationOutsideImpls {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(expand_glob_delegation_traitless_qpath)]
+pub(crate) struct GlobDelegationTraitlessQpath {
+    #[primary_span]
+    pub span: Span,
+}
+
 // This used to be the `proc_macro_back_compat` lint (#83125). It was later
 // turned into a hard error.
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 716bfc8c26b..26fc77c7f33 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -1,8 +1,9 @@
 use crate::base::*;
 use crate::config::StripUnconfigured;
 use crate::errors::{
-    EmptyDelegationMac, GlobDelegationOutsideImpls, IncompleteParse, RecursionLimitReached,
-    RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue, WrongFragmentKind,
+    EmptyDelegationMac, GlobDelegationOutsideImpls, GlobDelegationTraitlessQpath, IncompleteParse,
+    RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported, UnsupportedKeyValue,
+    WrongFragmentKind,
 };
 use crate::mbe::diagnostics::annotate_err_with_kind;
 use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
@@ -1882,7 +1883,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         let mut span: Option<Span> = None;
         while let Some(attr) = attrs.next() {
             rustc_ast_passes::feature_gate::check_attribute(attr, self.cx.sess, features);
-            validate_attr::check_attr(&self.cx.sess.psess, attr);
+            validate_attr::check_attr(features, &self.cx.sess.psess, attr);
 
             let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
             span = Some(current_span);
@@ -1989,6 +1990,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 }
                 None if let Some((deleg, item)) = node.delegation() => {
                     let Some(suffixes) = &deleg.suffixes else {
+                        let traitless_qself =
+                            matches!(&deleg.qself, Some(qself) if qself.position == 0);
                         let item = match node.to_annotatable() {
                             Annotatable::ImplItem(item) => item,
                             ann @ (Annotatable::Item(_)
@@ -2000,6 +2003,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                             }
                             _ => unreachable!(),
                         };
+                        if traitless_qself {
+                            let span = item.span;
+                            self.cx.dcx().emit_err(GlobDelegationTraitlessQpath { span });
+                            return Default::default();
+                        }
                         return self.collect_glob_delegation(item, Node::KIND).make_ast::<Node>();
                     };
 
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 0050ff10539..e43ba7c3a5a 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -10,7 +10,9 @@ use crate::mbe::transcribe::transcribe;
 
 use ast::token::IdentIsRaw;
 use rustc_ast as ast;
-use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind, TokenKind::*};
+use rustc_ast::token::{
+    self, Delimiter, NonterminalKind, NtPatKind::*, Token, TokenKind, TokenKind::*,
+};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream};
 use rustc_ast::{NodeId, DUMMY_NODE_ID};
 use rustc_ast_pretty::pprust;
@@ -1145,14 +1147,17 @@ fn check_matcher_core<'tt>(
                     // Macros defined in the current crate have a real node id,
                     // whereas macros from an external crate have a dummy id.
                     if def.id != DUMMY_NODE_ID
-                        && matches!(kind, NonterminalKind::PatParam { inferred: true })
-                        && matches!(next_token, TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or))
+                        && matches!(kind, NonterminalKind::Pat(PatParam { inferred: true }))
+                        && matches!(
+                            next_token,
+                            TokenTree::Token(token) if token.kind == BinOp(token::BinOpToken::Or)
+                        )
                     {
                         // It is suggestion to use pat_param, for example: $x:pat -> $x:pat_param.
                         let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
                             span,
                             name,
-                            Some(NonterminalKind::PatParam { inferred: false }),
+                            Some(NonterminalKind::Pat(PatParam { inferred: false })),
                         ));
                         sess.psess.buffer_lint(
                             RUST_2021_INCOMPATIBLE_OR_PATTERNS,
@@ -1185,14 +1190,14 @@ fn check_matcher_core<'tt>(
                             );
                             err.span_label(sp, format!("not allowed after `{kind}` fragments"));
 
-                            if kind == NonterminalKind::PatWithOr
+                            if kind == NonterminalKind::Pat(PatWithOr)
                                 && sess.psess.edition.at_least_rust_2021()
                                 && next_token.is_token(&BinOp(token::BinOpToken::Or))
                             {
                                 let suggestion = quoted_tt_to_string(&TokenTree::MetaVarDecl(
                                     span,
                                     name,
-                                    Some(NonterminalKind::PatParam { inferred: false }),
+                                    Some(NonterminalKind::Pat(PatParam { inferred: false })),
                                 ));
                                 err.span_suggestion(
                                     span,
@@ -1292,9 +1297,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                 // maintain
                 IsInFollow::Yes
             }
-            NonterminalKind::Stmt
-            | NonterminalKind::Expr
-            | NonterminalKind::Expr2021 { inferred: _ } => {
+            NonterminalKind::Stmt | NonterminalKind::Expr(_) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`;`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1304,7 +1307,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatParam { .. } => {
+            NonterminalKind::Pat(PatParam { .. }) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`|`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
@@ -1317,7 +1320,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatWithOr => {
+            NonterminalKind::Pat(PatWithOr) => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index fdf187438d3..9c480f17b42 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -2,7 +2,7 @@ use crate::errors;
 use crate::mbe::macro_parser::count_metavar_decls;
 use crate::mbe::{Delimited, KleeneOp, KleeneToken, MetaVarExpr, SequenceRepetition, TokenTree};
 
-use rustc_ast::token::{self, Delimiter, IdentIsRaw, Token};
+use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, NtExprKind::*, Token};
 use rustc_ast::{tokenstream, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_feature::Features;
@@ -85,36 +85,31 @@ pub(super) fn parse(
                                             span.edition()
                                         }
                                     };
-                                    let kind =
-                                        token::NonterminalKind::from_symbol(fragment.name, edition)
-                                            .unwrap_or_else(|| {
-                                                let help = match fragment.name {
-                                                    sym::expr_2021 => {
-                                                        format!(
-                                                            "fragment specifier `expr_2021` \
-                                                             requires Rust 2021 or later\n\
-                                                             {VALID_FRAGMENT_NAMES_MSG}"
-                                                        )
-                                                    }
-                                                    _ if edition().at_least_rust_2021()
-                                                        && features
-                                                            .expr_fragment_specifier_2024 =>
-                                                    {
-                                                        VALID_FRAGMENT_NAMES_MSG_2021.into()
-                                                    }
-                                                    _ => VALID_FRAGMENT_NAMES_MSG.into(),
-                                                };
-                                                sess.dcx().emit_err(
-                                                    errors::InvalidFragmentSpecifier {
-                                                        span,
-                                                        fragment,
-                                                        help,
-                                                    },
-                                                );
-                                                token::NonterminalKind::Ident
+                                    let kind = NonterminalKind::from_symbol(fragment.name, edition)
+                                        .unwrap_or_else(|| {
+                                            let help = match fragment.name {
+                                                sym::expr_2021 => {
+                                                    format!(
+                                                        "fragment specifier `expr_2021` \
+                                                         requires Rust 2021 or later\n\
+                                                         {VALID_FRAGMENT_NAMES_MSG}"
+                                                    )
+                                                }
+                                                _ if edition().at_least_rust_2021()
+                                                    && features.expr_fragment_specifier_2024 =>
+                                                {
+                                                    VALID_FRAGMENT_NAMES_MSG_2021.into()
+                                                }
+                                                _ => VALID_FRAGMENT_NAMES_MSG.into(),
+                                            };
+                                            sess.dcx().emit_err(errors::InvalidFragmentSpecifier {
+                                                span,
+                                                fragment,
+                                                help,
                                             });
-                                    if kind
-                                        == (token::NonterminalKind::Expr2021 { inferred: false })
+                                            NonterminalKind::Ident
+                                        });
+                                    if kind == NonterminalKind::Expr(Expr2021 { inferred: false })
                                         && !features.expr_fragment_specifier_2024
                                     {
                                         rustc_session::parse::feature_err(
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 9e2756f07ed..5e83e0d27e1 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -1145,10 +1145,6 @@ pub fn is_valid_for_get_attr(name: Symbol) -> bool {
     })
 }
 
-pub fn is_unsafe_attr(name: Symbol) -> bool {
-    BUILTIN_ATTRIBUTE_MAP.get(&name).is_some_and(|attr| attr.safety == AttributeSafety::Unsafe)
-}
-
 pub static BUILTIN_ATTRIBUTE_MAP: LazyLock<FxHashMap<Symbol, &BuiltinAttribute>> =
     LazyLock::new(|| {
         let mut map = FxHashMap::default();
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index fb3b7c0a127..bf429364318 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -125,7 +125,7 @@ pub use accepted::ACCEPTED_FEATURES;
 pub use builtin_attrs::AttributeDuplicates;
 pub use builtin_attrs::{
     deprecated_attributes, encode_cross_crate, find_gated_cfg, is_builtin_attr_name,
-    is_unsafe_attr, is_valid_for_get_attr, AttributeGate, AttributeTemplate, AttributeType,
+    is_valid_for_get_attr, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
     BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
 };
 pub use removed::REMOVED_FEATURES;
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index fbd67657e3b..f66c9604cbe 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -629,7 +629,7 @@ declare_features! (
     /// Allows unsafe on extern declarations and safety qualifiers over internal items.
     (unstable, unsafe_extern_blocks, "1.80.0", Some(123743)),
     /// Allows unsized fn parameters.
-    (unstable, unsized_fn_params, "1.49.0", Some(48055)),
+    (internal, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
     (incomplete, unsized_locals, "1.30.0", Some(48055)),
     /// Allows unsized tuple coercion.
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 9dd82868adc..b3ebc0621cb 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -26,10 +26,8 @@ use rustc_middle::lint::in_external_macro;
 use rustc_middle::middle::stability::EvalResult;
 use rustc_middle::span_bug;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{
-    self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt,
-    Upcast,
-};
+use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};
+use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Ident};
@@ -1111,12 +1109,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
             )
         {
-            err.multipart_suggestion(
+            // When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.
+            // For example:
+            // fn mismatch_types() -> i32 {
+            //     match 1 {
+            //         x => dbg!(x),
+            //     }
+            //     todo!()
+            // }
+            // -------------^^^^^^^-
+            // Don't add semicolon `;` at the end of `dbg!(x)` expr
+            fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
+                for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
+                    match node {
+                        hir::Node::Block(block) => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        hir::Node::Arm(arm) => {
+                            if let hir::ExprKind::Block(block, _) = arm.body.kind
+                                && let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                return true;
+                            }
+                        }
+                        hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => {
+                            if let Some(ret) = block.expr
+                                && ret.hir_id == expr.hir_id
+                            {
+                                continue;
+                            }
+                        }
+                        _ => {
+                            return false;
+                        }
+                    }
+                }
+
+                false
+            }
+            let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())];
+            if !is_in_arm(expr, self.tcx) {
+                suggs.push((span.shrink_to_hi(), ";".to_string()));
+            }
+            err.multipart_suggestion_verbose(
                 "you might have meant to return this value",
-                vec![
-                    (span.shrink_to_lo(), "return ".to_string()),
-                    (span.shrink_to_hi(), ";".to_string()),
-                ],
+                suggs,
                 Applicability::MaybeIncorrect,
             );
         }
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index fdedf2c2e6d..eac5083ffbf 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -825,6 +825,10 @@ lint_unnameable_test_items = cannot test inner items
 lint_unnecessary_qualification = unnecessary qualification
     .suggestion = remove the unnecessary path segments
 
+lint_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
+    .label = usage of unsafe attribute
+lint_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
+
 lint_unsupported_group = `{$lint_group}` lint group is not supported with ´--force-warn´
 
 lint_untranslatable_diag = diagnostics should be created using translatable messages
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index 290bb5173db..adb2a3275c0 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -319,6 +319,16 @@ pub(super) fn decorate_lint(sess: &Session, diagnostic: BuiltinLintDiag, diag: &
         BuiltinLintDiag::UnusedQualifications { removal_span } => {
             lints::UnusedQualifications { removal_span }.decorate_lint(diag);
         }
+        BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+            attribute_name_span,
+            sugg_spans: (left, right),
+        } => {
+            lints::UnsafeAttrOutsideUnsafe {
+                span: attribute_name_span,
+                suggestion: lints::UnsafeAttrOutsideUnsafeSuggestion { left, right },
+            }
+            .decorate_lint(diag);
+        }
         BuiltinLintDiag::AssociatedConstElidedLifetime {
             elided,
             span: lt_span,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index b26d04d0618..6df3a11deb0 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2890,3 +2890,24 @@ pub struct RedundantImportVisibility {
     pub import_vis: String,
     pub max_vis: String,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(lint_unsafe_attr_outside_unsafe)]
+pub struct UnsafeAttrOutsideUnsafe {
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_unsafe_attr_outside_unsafe_suggestion,
+    applicability = "machine-applicable"
+)]
+pub struct UnsafeAttrOutsideUnsafeSuggestion {
+    #[suggestion_part(code = "unsafe(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 1913b9d6a1c..265779c9374 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -115,6 +115,7 @@ declare_lint_pass! {
         UNNAMEABLE_TYPES,
         UNREACHABLE_CODE,
         UNREACHABLE_PATTERNS,
+        UNSAFE_ATTR_OUTSIDE_UNSAFE,
         UNSAFE_OP_IN_UNSAFE_FN,
         UNSTABLE_NAME_COLLISIONS,
         UNSTABLE_SYNTAX_PRE_EXPANSION,
@@ -4902,3 +4903,45 @@ declare_lint! {
         reference: "issue #123743 <https://github.com/rust-lang/rust/issues/123743>",
     };
 }
+
+declare_lint! {
+    /// The `unsafe_attr_outside_unsafe` lint detects a missing unsafe keyword
+    /// on attributes considered unsafe.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(unsafe_attributes)]
+    /// #![warn(unsafe_attr_outside_unsafe)]
+    ///
+    /// #[no_mangle]
+    /// extern "C" fn foo() {}
+    ///
+    /// fn main() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Some attributes (e.g. `no_mangle`, `export_name`, `link_section` -- see
+    /// [issue #82499] for a more complete list) are considered "unsafe" attributes.
+    /// An unsafe attribute must only be used inside unsafe(...).
+    ///
+    /// This lint can automatically wrap the attributes in `unsafe(...)` , but this
+    /// obviously cannot verify that the preconditions of the `unsafe`
+    /// attributes are fulfilled, so that is still up to the user.
+    ///
+    /// The lint is currently "allow" by default, but that might change in the
+    /// future.
+    ///
+    /// [editions]: https://doc.rust-lang.org/edition-guide/
+    /// [issue #82499]: https://github.com/rust-lang/rust/issues/82499
+    pub UNSAFE_ATTR_OUTSIDE_UNSAFE,
+    Allow,
+    "detects unsafe attributes outside of unsafe",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "issue #123757 <https://github.com/rust-lang/rust/issues/123757>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index b3838f915f6..f33aadfbbc8 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -691,6 +691,10 @@ pub enum BuiltinLintDiag {
         /// The span of the unnecessarily-qualified path to remove.
         removal_span: Span,
     },
+    UnsafeAttrOutsideUnsafe {
+        attribute_name_span: Span,
+        sugg_spans: (Span, Span),
+    },
     AssociatedConstElidedLifetime {
         elided: bool,
         span: Span,
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index 23680f14397..6a8498abaf9 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -520,6 +520,8 @@ pub enum UnsupportedOpInfo {
     Unsupported(String),
     /// Unsized local variables.
     UnsizedLocal,
+    /// Extern type field with an indeterminate offset.
+    ExternTypeField,
     //
     // The variants below are only reachable from CTFE/const prop, miri will never emit them.
     //
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index efb9526eabc..f08efe60d96 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -366,6 +366,10 @@ parse_inner_doc_comment_not_permitted = expected outer doc comment
     .label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
     .sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
 
+parse_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
+    .suggestion = remove the `unsafe(...)`
+    .note = extraneous unsafe is not allowed in attributes
+
 parse_invalid_block_macro_segment = cannot use a `block` macro fragment here
     .label = the `block` fragment is within this context
     .suggestion = wrap this in another block
@@ -866,6 +870,11 @@ parse_unmatched_angle_brackets = {$num_extra_brackets ->
            *[other] remove extra angle brackets
         }
 
+parse_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
+    .label = usage of unsafe attribute
+parse_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
+
+
 parse_unskipped_whitespace = whitespace symbol '{$ch}' is not skipped
     .label = {parse_unskipped_whitespace}
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 46e15734853..8d49887f164 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2997,3 +2997,34 @@ pub(crate) struct DotDotRangeAttribute {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(parse_invalid_attr_unsafe)]
+#[note]
+pub struct InvalidAttrUnsafe {
+    #[primary_span]
+    pub span: Span,
+    pub name: Path,
+}
+
+#[derive(Diagnostic)]
+#[diag(parse_unsafe_attr_outside_unsafe)]
+pub struct UnsafeAttrOutsideUnsafe {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    parse_unsafe_attr_outside_unsafe_suggestion,
+    applicability = "machine-applicable"
+)]
+pub struct UnsafeAttrOutsideUnsafeSuggestion {
+    #[suggestion_part(code = "unsafe(")]
+    pub left: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index 59f6eff07b3..4a78b427832 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,7 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
+use rustc_ast::token::{
+    self, Delimiter, Nonterminal::*, NonterminalKind, NtExprKind::*, NtPatKind::*, Token,
+};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
@@ -36,14 +38,14 @@ impl<'a> Parser<'a> {
         }
 
         match kind {
-            NonterminalKind::Expr2021 { inferred: _ } => {
+            NonterminalKind::Expr(Expr2021 { .. }) => {
                 token.can_begin_expr()
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Let)
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Const)
             }
-            NonterminalKind::Expr => {
+            NonterminalKind::Expr(Expr) => {
                 token.can_begin_expr()
                 // This exception is here for backwards compatibility.
                 && !token.is_keyword(kw::Let)
@@ -74,7 +76,7 @@ impl<'a> Parser<'a> {
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => match &token.kind {
+            NonterminalKind::Pat(pat_kind) => match &token.kind {
                 // box, ref, mut, and other identifiers (can stricten)
                 token::Ident(..) | token::NtIdent(..) |
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
@@ -89,7 +91,7 @@ impl<'a> Parser<'a> {
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
+                token::BinOp(token::Or) => matches!(pat_kind, PatWithOr),
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
@@ -135,31 +137,25 @@ impl<'a> Parser<'a> {
                         .create_err(UnexpectedNonterminal::Statement(self.token.span)));
                 }
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
-                NtPat(self.collect_tokens_no_attrs(|this| match kind {
-                    NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
-                    NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt(
+            NonterminalKind::Pat(pat_kind) => {
+                NtPat(self.collect_tokens_no_attrs(|this| match pat_kind {
+                    PatParam { .. } => this.parse_pat_no_top_alt(None, None),
+                    PatWithOr => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
                         RecoverColon::No,
                         CommaRecoveryMode::EitherTupleOrPipe,
                     ),
-                    _ => unreachable!(),
                 })?)
             }
-
-            NonterminalKind::Expr | NonterminalKind::Expr2021 { inferred: _ } => {
-                NtExpr(self.parse_expr_force_collect()?)
-            }
+            NonterminalKind::Expr(_) => NtExpr(self.parse_expr_force_collect()?),
             NonterminalKind::Literal => {
                 // The `:literal` matcher does not support attributes
                 NtLiteral(self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?)
             }
-
             NonterminalKind::Ty => {
                 NtTy(self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?)
             }
-
             // this could be handled like a token, since it is one
             NonterminalKind::Ident => {
                 return if let Some((ident, is_raw)) = get_macro_ident(&self.token) {
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 4ca52146039..bcb1131cc19 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -5,21 +5,73 @@ use crate::{errors, parse_in};
 use rustc_ast::token::Delimiter;
 use rustc_ast::tokenstream::DelimSpan;
 use rustc_ast::MetaItemKind;
-use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem};
+use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
 use rustc_errors::{Applicability, FatalError, PResult};
-use rustc_feature::{AttributeTemplate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
+use rustc_feature::{
+    AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
+};
 use rustc_session::errors::report_lit_error;
-use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
+use rustc_session::lint::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNSAFE_ATTR_OUTSIDE_UNSAFE};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::parse::ParseSess;
-use rustc_span::{sym, Span, Symbol};
+use rustc_span::{sym, BytePos, Span, Symbol};
 
-pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
+pub fn check_attr(features: &Features, psess: &ParseSess, attr: &Attribute) {
     if attr.is_doc_comment() {
         return;
     }
 
     let attr_info = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
+    let attr_item = attr.get_normal_item();
+
+    let is_unsafe_attr = attr_info.is_some_and(|attr| attr.safety == AttributeSafety::Unsafe);
+
+    if features.unsafe_attributes {
+        if is_unsafe_attr {
+            if let ast::Safety::Default = attr_item.unsafety {
+                let path_span = attr_item.path.span;
+
+                // If the `attr_item`'s span is not from a macro, then just suggest
+                // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
+                // `unsafe(`, `)` right after and right before the opening and closing
+                // square bracket respectively.
+                let diag_span = if attr_item.span().can_be_used_for_suggestions() {
+                    attr_item.span()
+                } else {
+                    attr.span
+                        .with_lo(attr.span.lo() + BytePos(2))
+                        .with_hi(attr.span.hi() - BytePos(1))
+                };
+
+                if attr.span.at_least_rust_2024() {
+                    psess.dcx().emit_err(errors::UnsafeAttrOutsideUnsafe {
+                        span: path_span,
+                        suggestion: errors::UnsafeAttrOutsideUnsafeSuggestion {
+                            left: diag_span.shrink_to_lo(),
+                            right: diag_span.shrink_to_hi(),
+                        },
+                    });
+                } else {
+                    psess.buffer_lint(
+                        UNSAFE_ATTR_OUTSIDE_UNSAFE,
+                        path_span,
+                        ast::CRATE_NODE_ID,
+                        BuiltinLintDiag::UnsafeAttrOutsideUnsafe {
+                            attribute_name_span: path_span,
+                            sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
+                        },
+                    );
+                }
+            }
+        } else {
+            if let Safety::Unsafe(unsafe_span) = attr_item.unsafety {
+                psess.dcx().emit_err(errors::InvalidAttrUnsafe {
+                    span: unsafe_span,
+                    name: attr_item.path.clone(),
+                });
+            }
+        }
+    }
 
     // Check input tokens for built-in and key-value attributes.
     match attr_info {
@@ -32,7 +84,7 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
                 }
             }
         }
-        _ if let AttrArgs::Eq(..) = attr.get_normal_item().args => {
+        _ if let AttrArgs::Eq(..) = attr_item.args => {
             // All key-value attributes are restricted to meta-item syntax.
             match parse_meta(psess, attr) {
                 Ok(_) => {}
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 84c71c4bed2..9a830b0f49b 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -384,10 +384,6 @@ passes_invalid_attr_at_crate_level =
 passes_invalid_attr_at_crate_level_item =
     the inner attribute doesn't annotate this {$kind}
 
-passes_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
-    .suggestion = remove the `unsafe(...)`
-    .note = extraneous unsafe is not allowed in attributes
-
 passes_invalid_macro_export_arguments = `{$name}` isn't a valid `#[macro_export]` argument
 
 passes_invalid_macro_export_arguments_too_many_items = `#[macro_export]` can only take 1 or 0 arguments
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index a0b3470df6d..2ed5bba85c6 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -10,9 +10,7 @@ use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{Applicability, IntoDiagArg, MultiSpan};
 use rustc_errors::{DiagCtxtHandle, StashKey};
-use rustc_feature::{
-    is_unsafe_attr, AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP,
-};
+use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir};
@@ -116,8 +114,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         let mut seen = FxHashMap::default();
         let attrs = self.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            self.check_unsafe_attr(attr);
-
             match attr.path().as_slice() {
                 [sym::diagnostic, sym::do_not_recommend] => {
                     self.check_do_not_recommend(attr.span, hir_id, target)
@@ -312,21 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         true
     }
 
-    /// Checks if `unsafe()` is applied to an invalid attribute.
-    fn check_unsafe_attr(&self, attr: &Attribute) {
-        if !attr.is_doc_comment() {
-            let attr_item = attr.get_normal_item();
-            if let ast::Safety::Unsafe(unsafe_span) = attr_item.unsafety {
-                if !is_unsafe_attr(attr.name_or_empty()) {
-                    self.dcx().emit_err(errors::InvalidAttrUnsafe {
-                        span: unsafe_span,
-                        name: attr_item.path.clone(),
-                    });
-                }
-            }
-        }
-    }
-
     /// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
     fn check_diagnostic_on_unimplemented(
         &self,
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index d27b94ebd22..f0596568092 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use crate::fluent_generated as fluent;
-use rustc_ast::{ast, Label};
+use rustc_ast::Label;
 use rustc_errors::{
     codes::*, Applicability, Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, EmissionGuarantee,
     Level, MultiSpan, SubdiagMessageOp, Subdiagnostic,
@@ -863,15 +863,6 @@ pub struct InvalidAttrAtCrateLevel {
     pub item: Option<ItemFollowingInnerAttr>,
 }
 
-#[derive(Diagnostic)]
-#[diag(passes_invalid_attr_unsafe)]
-#[note]
-pub struct InvalidAttrUnsafe {
-    #[primary_span]
-    pub span: Span,
-    pub name: ast::Path,
-}
-
 #[derive(Clone, Copy)]
 pub struct ItemFollowingInnerAttr {
     pub span: Span,
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 87794d11cea..8763e7aec43 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -140,9 +140,10 @@ pub(crate) fn registered_tools(tcx: TyCtxt<'_>, (): ()) -> RegisteredTools {
             }
         }
     }
-    // We implicitly add `rustfmt`, `clippy`, `diagnostic` to known tools,
-    // but it's not an error to register them explicitly.
-    let predefined_tools = [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri];
+    // We implicitly add `rustfmt`, `clippy`, `diagnostic`, `miri` and `rust_analyzer` to known
+    // tools, but it's not an error to register them explicitly.
+    let predefined_tools =
+        [sym::clippy, sym::rustfmt, sym::diagnostic, sym::miri, sym::rust_analyzer];
     registered_tools.extend(predefined_tools.iter().cloned().map(Ident::with_dummy_span));
     registered_tools
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 8d8f4927e99..ab0538ff282 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1559,6 +1559,7 @@ symbols! {
         rust_2018_preview,
         rust_2021,
         rust_2024,
+        rust_analyzer,
         rust_begin_unwind,
         rust_cold_cc,
         rust_eh_catch_typeinfo,
diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs
index 9d79faadd61..70fcaab1847 100644
--- a/compiler/rustc_target/src/asm/arm.rs
+++ b/compiler/rustc_target/src/asm/arm.rs
@@ -148,22 +148,22 @@ def_regs! {
         r11: reg = ["r11", "fp"] % frame_pointer_r11,
         r12: reg = ["r12", "ip"] % not_thumb1,
         r14: reg = ["r14", "lr"] % not_thumb1,
-        s0: sreg, sreg_low16 = ["s0"],
-        s1: sreg, sreg_low16 = ["s1"],
-        s2: sreg, sreg_low16 = ["s2"],
-        s3: sreg, sreg_low16 = ["s3"],
-        s4: sreg, sreg_low16 = ["s4"],
-        s5: sreg, sreg_low16 = ["s5"],
-        s6: sreg, sreg_low16 = ["s6"],
-        s7: sreg, sreg_low16 = ["s7"],
-        s8: sreg, sreg_low16 = ["s8"],
-        s9: sreg, sreg_low16 = ["s9"],
-        s10: sreg, sreg_low16 = ["s10"],
-        s11: sreg, sreg_low16 = ["s11"],
-        s12: sreg, sreg_low16 = ["s12"],
-        s13: sreg, sreg_low16 = ["s13"],
-        s14: sreg, sreg_low16 = ["s14"],
-        s15: sreg, sreg_low16 = ["s15"],
+        s0: sreg_low16, sreg = ["s0"],
+        s1: sreg_low16, sreg = ["s1"],
+        s2: sreg_low16, sreg = ["s2"],
+        s3: sreg_low16, sreg = ["s3"],
+        s4: sreg_low16, sreg = ["s4"],
+        s5: sreg_low16, sreg = ["s5"],
+        s6: sreg_low16, sreg = ["s6"],
+        s7: sreg_low16, sreg = ["s7"],
+        s8: sreg_low16, sreg = ["s8"],
+        s9: sreg_low16, sreg = ["s9"],
+        s10: sreg_low16, sreg = ["s10"],
+        s11: sreg_low16, sreg = ["s11"],
+        s12: sreg_low16, sreg = ["s12"],
+        s13: sreg_low16, sreg = ["s13"],
+        s14: sreg_low16, sreg = ["s14"],
+        s15: sreg_low16, sreg = ["s15"],
         s16: sreg = ["s16"],
         s17: sreg = ["s17"],
         s18: sreg = ["s18"],
@@ -180,22 +180,22 @@ def_regs! {
         s29: sreg = ["s29"],
         s30: sreg = ["s30"],
         s31: sreg = ["s31"],
-        d0: dreg, dreg_low16, dreg_low8 = ["d0"],
-        d1: dreg, dreg_low16, dreg_low8 = ["d1"],
-        d2: dreg, dreg_low16, dreg_low8 = ["d2"],
-        d3: dreg, dreg_low16, dreg_low8 = ["d3"],
-        d4: dreg, dreg_low16, dreg_low8 = ["d4"],
-        d5: dreg, dreg_low16, dreg_low8 = ["d5"],
-        d6: dreg, dreg_low16, dreg_low8 = ["d6"],
-        d7: dreg, dreg_low16, dreg_low8 = ["d7"],
-        d8: dreg, dreg_low16 = ["d8"],
-        d9: dreg, dreg_low16 = ["d9"],
-        d10: dreg, dreg_low16 = ["d10"],
-        d11: dreg, dreg_low16 = ["d11"],
-        d12: dreg, dreg_low16 = ["d12"],
-        d13: dreg, dreg_low16 = ["d13"],
-        d14: dreg, dreg_low16 = ["d14"],
-        d15: dreg, dreg_low16 = ["d15"],
+        d0: dreg_low8, dreg_low16, dreg = ["d0"],
+        d1: dreg_low8, dreg_low16, dreg = ["d1"],
+        d2: dreg_low8, dreg_low16, dreg = ["d2"],
+        d3: dreg_low8, dreg_low16, dreg = ["d3"],
+        d4: dreg_low8, dreg_low16, dreg = ["d4"],
+        d5: dreg_low8, dreg_low16, dreg = ["d5"],
+        d6: dreg_low8, dreg_low16, dreg = ["d6"],
+        d7: dreg_low8, dreg_low16, dreg = ["d7"],
+        d8: dreg_low16, dreg = ["d8"],
+        d9: dreg_low16, dreg = ["d9"],
+        d10: dreg_low16, dreg = ["d10"],
+        d11: dreg_low16, dreg = ["d11"],
+        d12: dreg_low16, dreg = ["d12"],
+        d13: dreg_low16, dreg = ["d13"],
+        d14: dreg_low16, dreg = ["d14"],
+        d15: dreg_low16, dreg = ["d15"],
         d16: dreg = ["d16"],
         d17: dreg = ["d17"],
         d18: dreg = ["d18"],
@@ -212,14 +212,14 @@ def_regs! {
         d29: dreg = ["d29"],
         d30: dreg = ["d30"],
         d31: dreg = ["d31"],
-        q0: qreg, qreg_low8, qreg_low4 = ["q0"],
-        q1: qreg, qreg_low8, qreg_low4 = ["q1"],
-        q2: qreg, qreg_low8, qreg_low4 = ["q2"],
-        q3: qreg, qreg_low8, qreg_low4 = ["q3"],
-        q4: qreg, qreg_low8 = ["q4"],
-        q5: qreg, qreg_low8 = ["q5"],
-        q6: qreg, qreg_low8 = ["q6"],
-        q7: qreg, qreg_low8 = ["q7"],
+        q0: qreg_low4, qreg_low8, qreg = ["q0"],
+        q1: qreg_low4, qreg_low8, qreg = ["q1"],
+        q2: qreg_low4, qreg_low8, qreg = ["q2"],
+        q3: qreg_low4, qreg_low8, qreg = ["q3"],
+        q4: qreg_low8, qreg = ["q4"],
+        q5: qreg_low8, qreg = ["q5"],
+        q6: qreg_low8, qreg = ["q6"],
+        q7: qreg_low8, qreg = ["q7"],
         q8: qreg = ["q8"],
         q9: qreg = ["q9"],
         q10: qreg = ["q10"],
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index c709ea2a15d..1d19c985f23 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -443,8 +443,8 @@ impl AtomicBool {
     ///
     /// # Safety
     ///
-    /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that on some platforms this can
-    ///   be bigger than `align_of::<bool>()`).
+    /// * `ptr` must be aligned to `align_of::<AtomicBool>()` (note that this is always true, since
+    ///   `align_of::<AtomicBool>() == 1`).
     /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
     /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
     ///   allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
@@ -2091,10 +2091,10 @@ impl<T> From<*mut T> for AtomicPtr<T> {
 }
 
 #[allow(unused_macros)] // This macro ends up being unused on some architectures.
-macro_rules! if_not_8_bit {
-    (u8, $($tt:tt)*) => { "" };
-    (i8, $($tt:tt)*) => { "" };
-    ($_:ident, $($tt:tt)*) => { $($tt)* };
+macro_rules! if_8_bit {
+    (u8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
+    (i8, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($yes)*)?) };
+    ($_:ident, $( yes = [$($yes:tt)*], )? $( no = [$($no:tt)*], )? ) => { concat!("", $($($no)*)?) };
 }
 
 #[cfg(target_has_atomic_load_store)]
@@ -2116,18 +2116,24 @@ macro_rules! atomic_int {
      $int_type:ident $atomic_type:ident) => {
         /// An integer type which can be safely shared between threads.
         ///
-        /// This type has the same size and bit validity as the underlying
-        /// integer type, [`
+        /// This type has the same
+        #[doc = if_8_bit!(
+            $int_type,
+            yes = ["size, alignment, and bit validity"],
+            no = ["size and bit validity"],
+        )]
+        /// as the underlying integer type, [`
         #[doc = $s_int_type]
         /// `].
-        #[doc = if_not_8_bit! {
+        #[doc = if_8_bit! {
             $int_type,
-            concat!(
+            no = [
                 "However, the alignment of this type is always equal to its ",
                 "size, even on targets where [`", $s_int_type, "`] has a ",
                 "lesser alignment."
-            )
+            ],
         }]
+        ///
         /// For more about the differences between atomic types and
         /// non-atomic types as well as information about the portability of
         /// this type, please see the [module-level documentation].
@@ -2220,9 +2226,19 @@ macro_rules! atomic_int {
             ///
             /// # Safety
             ///
-            #[doc = concat!(" * `ptr` must be aligned to \
-                `align_of::<", stringify!($atomic_type), ">()` (note that on some platforms this \
-                can be bigger than `align_of::<", stringify!($int_type), ">()`).")]
+            /// * `ptr` must be aligned to
+            #[doc = concat!("  `align_of::<", stringify!($atomic_type), ">()`")]
+            #[doc = if_8_bit!{
+                $int_type,
+                yes = [
+                    "  (note that this is always true, since `align_of::<",
+                    stringify!($atomic_type), ">() == 1`)."
+                ],
+                no = [
+                    "  (note that on some platforms this can be bigger than `align_of::<",
+                    stringify!($int_type), ">()`)."
+                ],
+            }]
             /// * `ptr` must be [valid] for both reads and writes for the whole lifetime `'a`.
             /// * You must adhere to the [Memory model for atomic accesses]. In particular, it is not
             ///   allowed to mix atomic and non-atomic accesses, or atomic accesses of different sizes,
@@ -2261,12 +2277,12 @@ macro_rules! atomic_int {
 
             #[doc = concat!("Get atomic access to a `&mut ", stringify!($int_type), "`.")]
             ///
-            #[doc = if_not_8_bit! {
+            #[doc = if_8_bit! {
                 $int_type,
-                concat!(
+                no = [
                     "**Note:** This function is only available on targets where `",
                     stringify!($int_type), "` has an alignment of ", $align, " bytes."
-                )
+                ],
             }]
             ///
             /// # Examples
diff --git a/library/std/src/sys/pal/unix/fs.rs b/library/std/src/sys/pal/unix/fs.rs
index 5c4ccd32850..92c76ec4303 100644
--- a/library/std/src/sys/pal/unix/fs.rs
+++ b/library/std/src/sys/pal/unix/fs.rs
@@ -20,14 +20,14 @@ use crate::sys::time::SystemTime;
 use crate::sys::{cvt, cvt_r};
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 
-#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 use crate::sys::weak::syscall;
 #[cfg(target_os = "android")]
 use crate::sys::weak::weak;
 
 use libc::{c_int, mode_t};
 
-#[cfg(any(all(target_os = "linux", target_env = "gnu"), target_vendor = "apple"))]
+#[cfg(all(target_os = "linux", target_env = "gnu"))]
 use libc::c_char;
 #[cfg(any(
     all(target_os = "linux", not(target_env = "musl")),
@@ -1891,8 +1891,6 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
 
 #[cfg(target_vendor = "apple")]
 pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
-    use crate::sync::atomic::{AtomicBool, Ordering};
-
     const COPYFILE_ALL: libc::copyfile_flags_t = libc::COPYFILE_METADATA | libc::COPYFILE_DATA;
 
     struct FreeOnDrop(libc::copyfile_state_t);
@@ -1907,39 +1905,21 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
         }
     }
 
-    // MacOS prior to 10.12 don't support `fclonefileat`
-    // We store the availability in a global to avoid unnecessary syscalls
-    static HAS_FCLONEFILEAT: AtomicBool = AtomicBool::new(true);
-    syscall! {
-        // Mirrors `libc::fclonefileat`
-        fn fclonefileat(
-            srcfd: libc::c_int,
-            dst_dirfd: libc::c_int,
-            dst: *const c_char,
-            flags: libc::c_int
-        ) -> libc::c_int
-    }
-
     let (reader, reader_metadata) = open_from(from)?;
 
-    // Opportunistically attempt to create a copy-on-write clone of `from`
-    // using `fclonefileat`.
-    if HAS_FCLONEFILEAT.load(Ordering::Relaxed) {
-        let clonefile_result = run_path_with_cstr(to, &|to| {
-            cvt(unsafe { fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
-        });
-        match clonefile_result {
-            Ok(_) => return Ok(reader_metadata.len()),
-            Err(err) => match err.raw_os_error() {
-                // `fclonefileat` will fail on non-APFS volumes, if the
-                // destination already exists, or if the source and destination
-                // are on different devices. In all these cases `fcopyfile`
-                // should succeed.
-                Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),
-                Some(libc::ENOSYS) => HAS_FCLONEFILEAT.store(false, Ordering::Relaxed),
-                _ => return Err(err),
-            },
-        }
+    let clonefile_result = run_path_with_cstr(to, &|to| {
+        cvt(unsafe { libc::fclonefileat(reader.as_raw_fd(), libc::AT_FDCWD, to.as_ptr(), 0) })
+    });
+    match clonefile_result {
+        Ok(_) => return Ok(reader_metadata.len()),
+        Err(e) => match e.raw_os_error() {
+            // `fclonefileat` will fail on non-APFS volumes, if the
+            // destination already exists, or if the source and destination
+            // are on different devices. In all these cases `fcopyfile`
+            // should succeed.
+            Some(libc::ENOTSUP) | Some(libc::EEXIST) | Some(libc::EXDEV) => (),
+            _ => return Err(e),
+        },
     }
 
     // Fall back to using `fcopyfile` if `fclonefileat` does not succeed.
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 2e71ceceb58..40e2d1403ef 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -738,17 +738,17 @@ pub fn home_dir() -> Option<PathBuf> {
             n => n as usize,
         };
         let mut buf = Vec::with_capacity(amt);
-        let mut passwd: libc::passwd = mem::zeroed();
+        let mut p = mem::MaybeUninit::<libc::passwd>::uninit();
         let mut result = ptr::null_mut();
         match libc::getpwuid_r(
             libc::getuid(),
-            &mut passwd,
+            p.as_mut_ptr(),
             buf.as_mut_ptr(),
             buf.capacity(),
             &mut result,
         ) {
             0 if !result.is_null() => {
-                let ptr = passwd.pw_dir as *const _;
+                let ptr = (*result).pw_dir as *const _;
                 let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
                 Some(OsStringExt::from_vec(bytes))
             }
diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp
index e4dbd3a13fe..258a0347451 100644
--- a/src/bootstrap/download-ci-llvm-stamp
+++ b/src/bootstrap/download-ci-llvm-stamp
@@ -1,4 +1,4 @@
 Change this file to make users of the `download-ci-llvm` configuration download
 a new version of LLVM from CI, even if the LLVM submodule hasn’t changed.
 
-Last change is for: https://github.com/rust-lang/rust/pull/125141
+Last change is for: https://github.com/rust-lang/rust/pull/126298
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index cc5b0073213..5b18cb3f7e1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1290,15 +1290,21 @@ fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
 pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
 
 fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
-    if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) {
+    let path = path.path.to_str().unwrap();
+
+    let is_explicitly_called = |p| -> bool { run.builder.paths.contains(p) };
+    let should_enforce = run.builder.kind == Kind::Dist || run.builder.kind == Kind::Install;
+
+    if path.contains(CODEGEN_BACKEND_PREFIX) {
         let mut needs_codegen_backend_config = true;
         for backend in run.builder.config.codegen_backends(run.target) {
-            if path.path.to_str().unwrap().ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend))
-            {
+            if path.ends_with(&(CODEGEN_BACKEND_PREFIX.to_owned() + backend)) {
                 needs_codegen_backend_config = false;
             }
         }
-        if needs_codegen_backend_config {
+        if (is_explicitly_called(&PathBuf::from(path)) || should_enforce)
+            && needs_codegen_backend_config
+        {
             run.builder.info(
                 "WARNING: no codegen-backends config matched the requested path to build a codegen backend. \
                 HELP: add backend to codegen-backends in config.toml.",
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 4fb64595504..2dc7cd7de6a 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1018,7 +1018,7 @@ impl Step for PlainSourceTarball {
             // perhaps it should be removed in favor of making `dist` perform the `vendor` step?
 
             // Ensure we have all submodules from src and other directories checked out.
-            for submodule in builder.get_all_submodules() {
+            for submodule in build_helper::util::parse_gitmodules(&builder.src) {
                 builder.update_submodule(Path::new(submodule));
             }
 
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index f90403d2ec4..8b379d3be5c 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -217,6 +217,7 @@ pub(crate) fn is_ci_llvm_available(config: &Config, asserts: bool) -> bool {
         ("arm-unknown-linux-gnueabihf", false),
         ("armv7-unknown-linux-gnueabihf", false),
         ("loongarch64-unknown-linux-gnu", false),
+        ("loongarch64-unknown-linux-musl", false),
         ("mips-unknown-linux-gnu", false),
         ("mips64-unknown-linux-gnuabi64", false),
         ("mips64el-unknown-linux-gnuabi64", false),
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 8a2bc3b9d48..efc09c41bf4 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1048,8 +1048,6 @@ impl Step for Tidy {
     /// Once tidy passes, this step also runs `fmt --check` if tests are being run
     /// for the `dev` or `nightly` channels.
     fn run(self, builder: &Builder<'_>) {
-        builder.build.update_submodule(Path::new("src/tools/rustc-perf"));
-
         let mut cmd = builder.tool_cmd(Tool::Tidy);
         cmd.arg(&builder.src);
         cmd.arg(&builder.initial_cargo);
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 2e9c04624c7..14ccbfe0267 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -4,13 +4,11 @@ use std::collections::BTreeSet;
 use std::env;
 use std::ffi::{OsStr, OsString};
 use std::fmt::{Debug, Write};
-use std::fs::{self, File};
+use std::fs;
 use std::hash::Hash;
-use std::io::{BufRead, BufReader};
 use std::ops::Deref;
 use std::path::{Path, PathBuf};
 use std::process::Command;
-use std::sync::OnceLock;
 use std::time::{Duration, Instant};
 
 use crate::core::build_steps::tool::{self, SourceType};
@@ -594,7 +592,7 @@ impl<'a> ShouldRun<'a> {
     ///
     /// [`path`]: ShouldRun::path
     pub fn paths(mut self, paths: &[&str]) -> Self {
-        let submodules_paths = self.builder.get_all_submodules();
+        let submodules_paths = build_helper::util::parse_gitmodules(&self.builder.src);
 
         self.paths.insert(PathSet::Set(
             paths
@@ -2243,28 +2241,6 @@ impl<'a> Builder<'a> {
         out
     }
 
-    /// Return paths of all submodules.
-    pub fn get_all_submodules(&self) -> &[String] {
-        static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
-
-        let init_submodules_paths = |src: &PathBuf| {
-            let file = File::open(src.join(".gitmodules")).unwrap();
-
-            let mut submodules_paths = vec![];
-            for line in BufReader::new(file).lines().map_while(Result::ok) {
-                let line = line.trim();
-                if line.starts_with("path") {
-                    let actual_path = line.split(' ').last().expect("Couldn't get value of path");
-                    submodules_paths.push(actual_path.to_owned());
-                }
-            }
-
-            submodules_paths
-        };
-
-        SUBMODULES_PATHS.get_or_init(|| init_submodules_paths(&self.src))
-    }
-
     /// Ensure that a given step is built *only if it's supposed to be built by default*, returning
     /// its output. This will cache the step, so it's safe (and good!) to call this as often as
     /// needed to ensure that all dependencies are build.
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 4b6dc45b436..59b29eedb79 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -135,7 +135,7 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
     if config.dry_run() {
         return Ok(());
     }
-    let _ = fs::remove_dir(link);
+    let _ = fs::remove_dir_all(link);
     return symlink_dir_inner(original, link);
 
     #[cfg(not(windows))]
diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md
index 824c904e17f..985e3b37422 100644
--- a/src/ci/docker/README.md
+++ b/src/ci/docker/README.md
@@ -271,6 +271,22 @@ For targets: `loongarch64-unknown-linux-gnu`
 - C compiler > gcc version = 13.2.0
 - C compiler > C++ = ENABLE -- to cross compile LLVM
 
+### `loongarch64-linux-musl.defconfig`
+
+For targets: `loongarch64-unknown-linux-musl`
+
+- Path and misc options > Prefix directory = /x-tools/${CT\_TARGET}
+- Path and misc options > Use a mirror = ENABLE
+- Path and misc options > Base URL = https://ci-mirrors.rust-lang.org/rustc
+- Target options > Target Architecture = loongarch
+- Target options > Bitness = 64-bit
+- Operating System > Target OS = linux
+- Operating System > Linux kernel version = 5.19.16
+- Binary utilities > Version of binutils = 2.41
+- C-library > musl version = 1.2.5
+- C compiler > gcc version = 13.2.0
+- C compiler > C++ = ENABLE -- to cross compile LLVM
+
 ### `mips-linux-gnu.defconfig`
 
 For targets: `mips-unknown-linux-gnu`
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile
new file mode 100644
index 00000000000..560adf971ba
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/Dockerfile
@@ -0,0 +1,35 @@
+FROM ubuntu:22.04
+
+COPY scripts/cross-apt-packages.sh /scripts/
+RUN sh /scripts/cross-apt-packages.sh
+
+COPY scripts/crosstool-ng-git.sh /scripts/
+RUN sh /scripts/crosstool-ng-git.sh
+
+COPY scripts/rustbuild-setup.sh /scripts/
+RUN sh /scripts/rustbuild-setup.sh
+WORKDIR /tmp
+
+COPY scripts/crosstool-ng-build.sh /scripts/
+COPY host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig /tmp/crosstool.defconfig
+RUN /scripts/crosstool-ng-build.sh
+
+COPY scripts/sccache.sh /scripts/
+RUN sh /scripts/sccache.sh
+
+ENV PATH=$PATH:/x-tools/loongarch64-unknown-linux-musl/bin
+
+ENV CC_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-gcc \
+    AR_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-ar \
+    CXX_loongarch64_unknown_linux_musl=loongarch64-unknown-linux-musl-g++
+
+ENV HOSTS=loongarch64-unknown-linux-musl
+
+ENV RUST_CONFIGURE_ARGS \
+      --enable-extended \
+      --enable-lld \
+      --disable-docs \
+      --set target.loongarch64-unknown-linux-musl.crt-static=false \
+      --musl-root-loongarch64=/x-tools/loongarch64-unknown-linux-musl/loongarch64-unknown-linux-musl/sysroot/usr
+
+ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig
new file mode 100644
index 00000000000..3ab676ed971
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-loongarch64-musl/loongarch64-unknown-linux-musl.defconfig
@@ -0,0 +1,15 @@
+CT_CONFIG_VERSION="4"
+CT_EXPERIMENTAL=y
+CT_PREFIX_DIR="/x-tools/${CT_TARGET}"
+CT_USE_MIRROR=y
+CT_MIRROR_BASE_URL="https://ci-mirrors.rust-lang.org/rustc"
+CT_ARCH_LOONGARCH=y
+# CT_DEMULTILIB is not set
+CT_ARCH_USE_MMU=y
+CT_ARCH_ARCH="loongarch64"
+CT_KERNEL_LINUX=y
+CT_LINUX_V_5_19=y
+CT_LIBC_MUSL=y
+CT_CC_GCC_ENABLE_DEFAULT_PIE=y
+CT_CC_LANG_CXX=y
+CT_GETTEXT_NEEDED=y
diff --git a/src/ci/docker/scripts/crosstool-ng-git.sh b/src/ci/docker/scripts/crosstool-ng-git.sh
new file mode 100644
index 00000000000..2a10e262df8
--- /dev/null
+++ b/src/ci/docker/scripts/crosstool-ng-git.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+set -ex
+
+URL=https://github.com/crosstool-ng/crosstool-ng
+REV=c64500d94be92ed1bcdfdef911048a14e216a5e1
+
+mkdir crosstool-ng
+cd crosstool-ng
+git init
+git fetch --depth=1 ${URL} ${REV}
+git reset --hard FETCH_HEAD
+./bootstrap
+./configure --prefix=/usr/local
+make -j$(nproc)
+make install
+cd ..
+rm -rf crosstool-ng
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 4366a92fbcd..e3903c3dd5a 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -144,6 +144,9 @@ auto:
   - image: dist-loongarch64-linux
     <<: *job-linux-4c
 
+  - image: dist-loongarch64-musl
+    <<: *job-linux-4c
+
   - image: dist-ohos
     <<: *job-linux-4c
 
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 537c88cd22b..71dc8c4ca0f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -93,6 +93,7 @@ target | notes
 `arm-unknown-linux-gnueabihf` | Armv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
 `armv7-unknown-linux-gnueabihf` | Armv7-A Linux, hardfloat (kernel 3.2, glibc 2.17)
 [`loongarch64-unknown-linux-gnu`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, glibc 2.36)
+[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5)
 `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17)
 `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
 `powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
@@ -118,7 +119,7 @@ The `std` column in the table below has the following meanings:
 
 * ✓ indicates the full standard library is available.
 * \* indicates the target only supports [`no_std`] development.
-* ? indicates the standard library support is unknown or a work-in-progress.
+* ? indicates the standard library support is a work-in-progress.
 
 [`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html
 
@@ -305,7 +306,6 @@ target | std | host | notes
 `i686-uwp-windows-msvc` | ✓ |  | [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 `i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
-[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
 `mips-unknown-linux-musl` | ✓ |  | MIPS Linux with musl 1.2.3
diff --git a/src/etc/pre-push.sh b/src/etc/pre-push.sh
index c9e1a2733fd..6f86c7ab8a4 100755
--- a/src/etc/pre-push.sh
+++ b/src/etc/pre-push.sh
@@ -7,8 +7,6 @@
 
 set -Euo pipefail
 
-# https://github.com/rust-lang/rust/issues/77620#issuecomment-705144570
-unset GIT_DIR
 ROOT_DIR="$(git rev-parse --show-toplevel)"
 
 echo "Running pre-push script $ROOT_DIR/x test tidy"
diff --git a/src/tools/build-manifest/README.md b/src/tools/build-manifest/README.md
index 9d30c554186..2ea1bffb35f 100644
--- a/src/tools/build-manifest/README.md
+++ b/src/tools/build-manifest/README.md
@@ -4,7 +4,7 @@ This tool generates the manifests uploaded to static.rust-lang.org and used by r
 You can see a full list of all manifests at <https://static.rust-lang.org/manifests.txt>.
 This listing is updated by <https://github.com/rust-lang/generate-manifest-list> every 7 days.
 
-This gets called by `promote-release` <https://github.com/rust-lang/promote-release> via `x.py dist hash-and-sign`.
+This gets called by `promote-release` <https://github.com/rust-lang/promote-release>. `promote-release` downloads a pre-built binary of `build-manifest` which is generated in the dist-x86_64-linux builder and uploaded to s3.
 
 ## Adding a new component
 
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index a709aab7ce2..a2e7907b532 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -25,6 +25,7 @@ static HOSTS: &[&str] = &[
     "i686-pc-windows-msvc",
     "i686-unknown-linux-gnu",
     "loongarch64-unknown-linux-gnu",
+    "loongarch64-unknown-linux-musl",
     "mips-unknown-linux-gnu",
     "mips64-unknown-linux-gnuabi64",
     "mips64el-unknown-linux-gnuabi64",
@@ -106,6 +107,7 @@ static TARGETS: &[&str] = &[
     "i686-unknown-redox",
     "i686-unknown-uefi",
     "loongarch64-unknown-linux-gnu",
+    "loongarch64-unknown-linux-musl",
     "loongarch64-unknown-none",
     "loongarch64-unknown-none-softfloat",
     "m68k-unknown-linux-gnu",
diff --git a/src/tools/build_helper/src/util.rs b/src/tools/build_helper/src/util.rs
index 5801a8648f2..72c05c4c48a 100644
--- a/src/tools/build_helper/src/util.rs
+++ b/src/tools/build_helper/src/util.rs
@@ -1,4 +1,8 @@
+use std::fs::File;
+use std::io::{BufRead, BufReader};
+use std::path::Path;
 use std::process::Command;
+use std::sync::OnceLock;
 
 /// Invokes `build_helper::util::detail_exit` with `cfg!(test)`
 ///
@@ -45,3 +49,27 @@ pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
         Ok(())
     }
 }
+
+/// Returns the submodule paths from the `.gitmodules` file in the given directory.
+pub fn parse_gitmodules(target_dir: &Path) -> &[String] {
+    static SUBMODULES_PATHS: OnceLock<Vec<String>> = OnceLock::new();
+    let gitmodules = target_dir.join(".gitmodules");
+    assert!(gitmodules.exists(), "'{}' file is missing.", gitmodules.display());
+
+    let init_submodules_paths = || {
+        let file = File::open(gitmodules).unwrap();
+
+        let mut submodules_paths = vec![];
+        for line in BufReader::new(file).lines().map_while(Result::ok) {
+            let line = line.trim();
+            if line.starts_with("path") {
+                let actual_path = line.split(' ').last().expect("Couldn't get value of path");
+                submodules_paths.push(actual_path.to_owned());
+            }
+        }
+
+        submodules_paths
+    };
+
+    SUBMODULES_PATHS.get_or_init(|| init_submodules_paths())
+}
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 82d80fcc19c..31ae0deb7ec 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -877,6 +877,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "needs-sanitizer-shadow-call-stack",
     "needs-sanitizer-support",
     "needs-sanitizer-thread",
+    "needs-symlink",
     "needs-threads",
     "needs-unwind",
     "needs-wasmtime",
diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index b96832db67b..5b2665f7d0b 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -144,6 +144,11 @@ pub(super) fn handle_needs(
             condition: config.runner.as_ref().is_some_and(|r| r.contains("wasmtime")),
             ignore_reason: "ignored when wasmtime runner is not available",
         },
+        Need {
+            name: "needs-symlink",
+            condition: cache.symlinks,
+            ignore_reason: "ignored if symlinks are unavailable",
+        },
     ];
 
     let (name, comment) = match ln.split_once([':', ' ']) {
@@ -209,6 +214,7 @@ pub(super) struct CachedNeedsConditions {
     xray: bool,
     rust_lld: bool,
     dlltool: bool,
+    symlinks: bool,
 }
 
 impl CachedNeedsConditions {
@@ -253,6 +259,7 @@ impl CachedNeedsConditions {
                 .exists(),
 
             dlltool: find_dlltool(&config),
+            symlinks: has_symlinks(),
         }
     }
 }
@@ -279,3 +286,22 @@ fn find_dlltool(config: &Config) -> bool {
     };
     dlltool_found
 }
+
+#[cfg(windows)]
+fn has_symlinks() -> bool {
+    if std::env::var_os("CI").is_some() {
+        return true;
+    }
+    let link = std::env::temp_dir().join("RUST_COMPILETEST_SYMLINK_CHECK");
+    if std::os::windows::fs::symlink_file("DOES NOT EXIST", &link).is_ok() {
+        std::fs::remove_file(&link).unwrap();
+        true
+    } else {
+        false
+    }
+}
+
+#[cfg(not(windows))]
+fn has_symlinks() -> bool {
+    true
+}
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 12fb76f3972..1b70a1a1cf0 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -311,7 +311,9 @@ pub fn report_error<'tcx>(
             ResourceExhaustion(_) => "resource exhaustion",
             Unsupported(
                 // We list only the ones that can actually happen.
-                UnsupportedOpInfo::Unsupported(_) | UnsupportedOpInfo::UnsizedLocal,
+                UnsupportedOpInfo::Unsupported(_)
+                | UnsupportedOpInfo::UnsizedLocal
+                | UnsupportedOpInfo::ExternTypeField,
             ) => "unsupported operation",
             InvalidProgram(
                 // We list only the ones that can actually happen.
diff --git a/src/tools/miri/tests/fail/extern-type-field-offset.stderr b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
index e0d6e9ebf1d..3ed5732b4eb 100644
--- a/src/tools/miri/tests/fail/extern-type-field-offset.stderr
+++ b/src/tools/miri/tests/fail/extern-type-field-offset.stderr
@@ -1,8 +1,8 @@
-error: unsupported operation: `extern type` does not have a known offset
+error: unsupported operation: `extern type` field does not have a known offset
   --> $DIR/extern-type-field-offset.rs:LL:CC
    |
 LL |     let _field = &x.a;
-   |                  ^^^^ `extern type` does not have a known offset
+   |                  ^^^^ `extern type` field does not have a known offset
    |
    = help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
    = note: BACKTRACE:
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index c8ea104e9d6..eb11604b277 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1994,7 +1994,6 @@ fn rewrite_static(
     static_parts: &StaticParts<'_>,
     offset: Indent,
 ) -> Option<String> {
-    println!("rewriting static");
     let colon = colon_spaces(context.config);
     let mut prefix = format!(
         "{}{}{}{} {}{}{}",
diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs
index c44f3788d97..a1de71a35be 100644
--- a/src/tools/rustfmt/src/overflow.rs
+++ b/src/tools/rustfmt/src/overflow.rs
@@ -83,6 +83,7 @@ pub(crate) enum OverflowableItem<'a> {
     TuplePatField(&'a TuplePatField<'a>),
     Ty(&'a ast::Ty),
     Pat(&'a ast::Pat),
+    PreciseCapturingArg(&'a ast::PreciseCapturingArg),
 }
 
 impl<'a> Rewrite for OverflowableItem<'a> {
@@ -123,6 +124,7 @@ impl<'a> OverflowableItem<'a> {
             OverflowableItem::TuplePatField(pat) => f(*pat),
             OverflowableItem::Ty(ty) => f(*ty),
             OverflowableItem::Pat(pat) => f(*pat),
+            OverflowableItem::PreciseCapturingArg(arg) => f(*arg),
         }
     }
 
@@ -137,6 +139,9 @@ impl<'a> OverflowableItem<'a> {
                     matches!(meta_item.kind, ast::MetaItemKind::Word)
                 }
             },
+            // FIXME: Why don't we consider `SegmentParam` to be simple?
+            // FIXME: If we also fix `SegmentParam`, then we should apply the same
+            // heuristic to `PreciseCapturingArg`.
             _ => false,
         }
     }
@@ -244,7 +249,15 @@ macro_rules! impl_into_overflowable_item_for_rustfmt_types {
     }
 }
 
-impl_into_overflowable_item_for_ast_node!(Expr, GenericParam, NestedMetaItem, FieldDef, Ty, Pat);
+impl_into_overflowable_item_for_ast_node!(
+    Expr,
+    GenericParam,
+    NestedMetaItem,
+    FieldDef,
+    Ty,
+    Pat,
+    PreciseCapturingArg
+);
 impl_into_overflowable_item_for_rustfmt_types!([MacroArg], [SegmentParam, TuplePatField]);
 
 pub(crate) fn into_overflowable_list<'a, T>(
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index 89169e10715..60c827fd03b 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -1,4 +1,4 @@
-use rustc_ast::token::{Delimiter, NonterminalKind, TokenKind};
+use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ast, ptr};
 use rustc_parse::parser::{ForceCollect, Parser, Recovery};
@@ -48,7 +48,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
 
     parse_macro_arg!(
         Expr,
-        NonterminalKind::Expr,
+        NonterminalKind::Expr(Expr),
         |parser: &mut Parser<'b>| parser.parse_expr(),
         |x: ptr::P<ast::Expr>| Some(x)
     );
@@ -60,7 +60,7 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
     );
     parse_macro_arg!(
         Pat,
-        NonterminalKind::PatParam { inferred: false },
+        NonterminalKind::Pat(PatParam { inferred: false }),
         |parser: &mut Parser<'b>| parser.parse_pat_no_top_alt(None, None),
         |x: ptr::P<ast::Pat>| Some(x)
     );
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index 28911f8af1d..1ee691b4ade 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -203,3 +203,12 @@ impl Spanned for ast::NestedMetaItem {
         self.span()
     }
 }
+
+impl Spanned for ast::PreciseCapturingArg {
+    fn span(&self) -> Span {
+        match self {
+            ast::PreciseCapturingArg::Lifetime(lt) => lt.ident.span,
+            ast::PreciseCapturingArg::Arg(path, _) => path.span,
+        }
+    }
+}
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index c12f271bc5d..c0bf9482b11 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -177,6 +177,17 @@ impl<'a> Rewrite for SegmentParam<'a> {
     }
 }
 
+impl Rewrite for ast::PreciseCapturingArg {
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        match self {
+            ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite(context, shape),
+            ast::PreciseCapturingArg::Arg(p, _) => {
+                rewrite_path(context, PathContext::Type, &None, p, shape)
+            }
+        }
+    }
+}
+
 impl Rewrite for ast::AssocItemConstraint {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         use ast::AssocItemConstraintKind::{Bound, Equality};
@@ -564,9 +575,10 @@ impl Rewrite for ast::GenericBound {
                     .map(|s| format!("{constness}{asyncness}{polarity}{s}"))
                     .map(|s| if has_paren { format!("({})", s) } else { s })
             }
+            ast::GenericBound::Use(ref args, span) => {
+                overflow::rewrite_with_angle_brackets(context, "use", args.iter(), shape, span)
+            }
             ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape),
-            // FIXME(precise_capturing): Should implement formatting before stabilization.
-            ast::GenericBound::Use(..) => None,
         }
     }
 }
@@ -933,9 +945,7 @@ fn rewrite_bare_fn(
 fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool {
     let is_trait = |b: &ast::GenericBound| match b {
         ast::GenericBound::Outlives(..) => false,
-        ast::GenericBound::Trait(..) => true,
-        // FIXME(precise_capturing): This ordering fn should be reworked.
-        ast::GenericBound::Use(..) => false,
+        ast::GenericBound::Trait(..) | ast::GenericBound::Use(..) => true,
     };
     let is_lifetime = |b: &ast::GenericBound| !is_trait(b);
     let last_trait_index = generic_bounds.iter().rposition(is_trait);
@@ -969,9 +979,8 @@ fn join_bounds_inner(
     let generic_bounds_in_order = is_generic_bounds_in_order(items);
     let is_bound_extendable = |s: &str, b: &ast::GenericBound| match b {
         ast::GenericBound::Outlives(..) => true,
-        ast::GenericBound::Trait(..) => last_line_extendable(s),
-        // FIXME(precise_capturing): This ordering fn should be reworked.
-        ast::GenericBound::Use(..) => true,
+        // We treat `use<>` like a trait bound here.
+        ast::GenericBound::Trait(..) | ast::GenericBound::Use(..) => last_line_extendable(s),
     };
 
     // Whether a GenericBound item is a PathSegment segment that includes internal array
@@ -993,6 +1002,7 @@ fn join_bounds_inner(
                 }
             }
         }
+        ast::GenericBound::Use(args, _) => args.len() > 1,
         _ => false,
     };
 
diff --git a/src/tools/rustfmt/tests/source/precise-capturing.rs b/src/tools/rustfmt/tests/source/precise-capturing.rs
new file mode 100644
index 00000000000..b61cceeffe8
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/precise-capturing.rs
@@ -0,0 +1,9 @@
+fn hello() -> impl
+use<'a> + Sized {}
+
+fn all_three() -> impl Sized + use<'a> + 'a;
+
+fn pathological() -> impl use<'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a,
+'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a,
+'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 
+'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a, 'a> + Sized {}
diff --git a/src/tools/rustfmt/tests/target/precise-capturing.rs b/src/tools/rustfmt/tests/target/precise-capturing.rs
new file mode 100644
index 00000000000..d21374f44c1
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/precise-capturing.rs
@@ -0,0 +1,55 @@
+fn hello() -> impl use<'a> + Sized {}
+
+fn all_three() -> impl Sized + use<'a> + 'a;
+
+fn pathological() -> impl use<
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+    'a,
+> + Sized {
+}
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index f39438bd9ac..0b05d5add52 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 autobins = false
 
 [dependencies]
+build_helper = { path = "../build_helper" }
 cargo_metadata = "0.15"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 7337c9843c7..aa119819aaa 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,7 +1,9 @@
 //! Checks the licenses of third-party dependencies.
 
+use build_helper::ci::CiEnv;
 use cargo_metadata::{Metadata, Package, PackageId};
 use std::collections::HashSet;
+use std::fs::read_dir;
 use std::path::Path;
 
 /// These are licenses that are allowed for all crates, including the runtime,
@@ -514,7 +516,19 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
 pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
     let mut checked_runtime_licenses = false;
 
+    let submodules = build_helper::util::parse_gitmodules(root);
     for &(workspace, exceptions, permitted_deps) in WORKSPACES {
+        // Skip if it's a submodule, not in a CI environment, and not initialized.
+        //
+        // This prevents enforcing developers to fetch submodules for tidy.
+        if submodules.contains(&workspace.into())
+            && !CiEnv::is_ci()
+            // If the directory is empty, we can consider it as an uninitialized submodule.
+            && read_dir(root.join(workspace)).unwrap().next().is_none()
+        {
+            continue;
+        }
+
         if !root.join(workspace).join("Cargo.lock").exists() {
             tidy_error!(bad, "the `{workspace}` workspace doesn't have a Cargo.lock");
             continue;
diff --git a/src/tools/tidy/src/extdeps.rs b/src/tools/tidy/src/extdeps.rs
index 2118de5f204..8bb80f11711 100644
--- a/src/tools/tidy/src/extdeps.rs
+++ b/src/tools/tidy/src/extdeps.rs
@@ -1,6 +1,7 @@
 //! Check for external package sources. Allow only vendorable packages.
 
-use std::fs;
+use build_helper::ci::CiEnv;
+use std::fs::{self, read_dir};
 use std::path::Path;
 
 /// List of allowed sources for packages.
@@ -13,7 +14,19 @@ const ALLOWED_SOURCES: &[&str] = &[
 /// Checks for external package sources. `root` is the path to the directory that contains the
 /// workspace `Cargo.toml`.
 pub fn check(root: &Path, bad: &mut bool) {
+    let submodules = build_helper::util::parse_gitmodules(root);
     for &(workspace, _, _) in crate::deps::WORKSPACES {
+        // Skip if it's a submodule, not in a CI environment, and not initialized.
+        //
+        // This prevents enforcing developers to fetch submodules for tidy.
+        if submodules.contains(&workspace.into())
+            && !CiEnv::is_ci()
+            // If the directory is empty, we can consider it as an uninitialized submodule.
+            && read_dir(root.join(workspace)).unwrap().next().is_none()
+        {
+            continue;
+        }
+
         // FIXME check other workspaces too
         // `Cargo.lock` of rust.
         let path = root.join(workspace).join("Cargo.lock");
diff --git a/tests/run-make/symlinked-extern/rmake.rs b/tests/run-make/symlinked-extern/rmake.rs
index 98f69aefbe6..9ed5b76edcb 100644
--- a/tests/run-make/symlinked-extern/rmake.rs
+++ b/tests/run-make/symlinked-extern/rmake.rs
@@ -9,6 +9,7 @@
 // can result in successful compilation.
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, cwd, fs_wrapper, rustc};
 
diff --git a/tests/run-make/symlinked-libraries/rmake.rs b/tests/run-make/symlinked-libraries/rmake.rs
index 3f02f19ccd5..1d1dce5b5cf 100644
--- a/tests/run-make/symlinked-libraries/rmake.rs
+++ b/tests/run-make/symlinked-libraries/rmake.rs
@@ -6,6 +6,7 @@
 // See https://github.com/rust-lang/rust/issues/12459
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, dynamic_lib_name, fs_wrapper, rustc};
 
diff --git a/tests/run-make/symlinked-rlib/rmake.rs b/tests/run-make/symlinked-rlib/rmake.rs
index 3759ca25928..65ebb191428 100644
--- a/tests/run-make/symlinked-rlib/rmake.rs
+++ b/tests/run-make/symlinked-rlib/rmake.rs
@@ -6,6 +6,7 @@
 // See https://github.com/rust-lang/rust/pull/32828
 
 //@ ignore-cross-compile
+//@ needs-symlink
 
 use run_make_support::{create_symlink, cwd, rustc};
 
diff --git a/tests/ui/asm/arm-low-dreg.rs b/tests/ui/asm/arm-low-dreg.rs
new file mode 100644
index 00000000000..e9ff0117e2d
--- /dev/null
+++ b/tests/ui/asm/arm-low-dreg.rs
@@ -0,0 +1,33 @@
+//@ build-pass
+//@ compile-flags: --target=armv7-unknown-linux-gnueabihf
+//@ needs-llvm-components: arm
+#![feature(no_core, rustc_attrs, decl_macro, lang_items)]
+#![crate_type = "rlib"]
+#![no_std]
+#![no_core]
+
+// We accidentally classified "d0"..="d15" as dregs, even though they are in dreg_low16,
+// and thus didn't compile them on platforms with only 16 dregs.
+// Highlighted in https://github.com/rust-lang/rust/issues/126797
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for f64 {}
+
+#[rustc_builtin_macro]
+pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) {
+    /* compiler built-in */
+}
+
+
+fn f(x: f64) -> f64 {
+    let out: f64;
+    unsafe {
+        asm!("vmov.f64 d1, d0", out("d1") out, in("d0") x);
+    }
+    out
+}
diff --git a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
index 1c07a5bf8ba..ea82bac6df0 100644
--- a/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
+++ b/tests/ui/attributes/unsafe/double-unsafe-attributes.stderr
@@ -9,12 +9,6 @@ help: escape `unsafe` to use it as an identifier
 LL | #[unsafe(r#unsafe(no_mangle))]
    |          ++
 
-error: cannot find attribute `r#unsafe` in this scope
-  --> $DIR/double-unsafe-attributes.rs:3:10
-   |
-LL | #[unsafe(unsafe(no_mangle))]
-   |          ^^^^^^
-
 error: `r#unsafe` is not an unsafe attribute
   --> $DIR/double-unsafe-attributes.rs:3:3
    |
@@ -23,5 +17,11 @@ LL | #[unsafe(unsafe(no_mangle))]
    |
    = note: extraneous unsafe is not allowed in attributes
 
+error: cannot find attribute `r#unsafe` in this scope
+  --> $DIR/double-unsafe-attributes.rs:3:10
+   |
+LL | #[unsafe(unsafe(no_mangle))]
+   |          ^^^^^^
+
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
index 99f37fedd3d..54d45ee8ffb 100644
--- a/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
+++ b/tests/ui/consts/const-eval/issue-91827-extern-types-field-offset.stderr
@@ -2,7 +2,7 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/issue-91827-extern-types-field-offset.rs:38:17
    |
 LL |     let field = &x.a;
-   |                 ^^^^ `extern type` does not have a known offset
+   |                 ^^^^ `extern type` field does not have a known offset
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs
new file mode 100644
index 00000000000..3502409d576
--- /dev/null
+++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.rs
@@ -0,0 +1,15 @@
+#![feature(extern_types)]
+
+extern {
+    type Opaque;
+}
+
+struct ThinDst {
+    x: u8,
+    tail: Opaque,
+}
+
+const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) };
+//~^ERROR: evaluation of constant value failed
+
+fn main() {}
diff --git a/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr
new file mode 100644
index 00000000000..1ec36abc2ec
--- /dev/null
+++ b/tests/ui/consts/const-eval/validation-ice-extern-type-field.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/validation-ice-extern-type-field.rs:12:1
+   |
+LL | const C1: &ThinDst = unsafe { std::mem::transmute(b"d".as_ptr()) };
+   | ^^^^^^^^^^^^^^^^^^ `extern type` field does not have a known offset
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/delegation/glob-traitless-qpath.rs b/tests/ui/delegation/glob-traitless-qpath.rs
new file mode 100644
index 00000000000..abf4b3180ed
--- /dev/null
+++ b/tests/ui/delegation/glob-traitless-qpath.rs
@@ -0,0 +1,11 @@
+#![feature(fn_delegation)]
+#![allow(incomplete_features)]
+
+struct S;
+
+impl S {
+    reuse <u8>::*; //~ ERROR qualified path without a trait in glob delegation
+    reuse <()>::*; //~ ERROR qualified path without a trait in glob delegation
+}
+
+fn main() {}
diff --git a/tests/ui/delegation/glob-traitless-qpath.stderr b/tests/ui/delegation/glob-traitless-qpath.stderr
new file mode 100644
index 00000000000..e3257de347a
--- /dev/null
+++ b/tests/ui/delegation/glob-traitless-qpath.stderr
@@ -0,0 +1,14 @@
+error: qualified path without a trait in glob delegation
+  --> $DIR/glob-traitless-qpath.rs:7:5
+   |
+LL |     reuse <u8>::*;
+   |     ^^^^^^^^^^^^^^
+
+error: qualified path without a trait in glob delegation
+  --> $DIR/glob-traitless-qpath.rs:8:5
+   |
+LL |     reuse <()>::*;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed
new file mode 100644
index 00000000000..30fd0028f19
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.fixed
@@ -0,0 +1,34 @@
+//@ run-rustfix
+#![allow(unreachable_code, dead_code)]
+
+fn main() {
+    fn mismatch_types1() -> i32 {
+        match 1 {
+            x => return dbg!(x), //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types2() -> i32 {
+        match 2 {
+            x => {
+                return dbg!(x) //~ ERROR mismatched types
+            }
+        }
+        todo!()
+    }
+
+    fn mismatch_types3() -> i32 {
+        match 1 {
+            _ => return dbg!(1) //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types4() -> i32 {
+        match 1 {
+            _ => {return dbg!(1)} //~ ERROR mismatched types
+        }
+        todo!()
+    }
+}
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.rs b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs
new file mode 100644
index 00000000000..59178702489
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.rs
@@ -0,0 +1,34 @@
+//@ run-rustfix
+#![allow(unreachable_code, dead_code)]
+
+fn main() {
+    fn mismatch_types1() -> i32 {
+        match 1 {
+            x => dbg!(x), //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types2() -> i32 {
+        match 2 {
+            x => {
+                dbg!(x) //~ ERROR mismatched types
+            }
+        }
+        todo!()
+    }
+
+    fn mismatch_types3() -> i32 {
+        match 1 {
+            _ => dbg!(1) //~ ERROR mismatched types
+        }
+        todo!()
+    }
+
+    fn mismatch_types4() -> i32 {
+        match 1 {
+            _ => {dbg!(1)} //~ ERROR mismatched types
+        }
+        todo!()
+    }
+}
diff --git a/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr
new file mode 100644
index 00000000000..2a8f9867abb
--- /dev/null
+++ b/tests/ui/mismatched_types/mismatched-types-issue-126222.stderr
@@ -0,0 +1,51 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:7:18
+   |
+LL |             x => dbg!(x),
+   |                  ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             x => return dbg!(x),
+   |                  ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:15:17
+   |
+LL |                 dbg!(x)
+   |                 ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |                 return dbg!(x)
+   |                 ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:23:18
+   |
+LL |             _ => dbg!(1)
+   |                  ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             _ => return dbg!(1)
+   |                  ++++++
+
+error[E0308]: mismatched types
+  --> $DIR/mismatched-types-issue-126222.rs:30:19
+   |
+LL |             _ => {dbg!(1)}
+   |                   ^^^^^^^ expected `()`, found integer
+   |
+   = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have meant to return this value
+   |
+LL |             _ => {return dbg!(1)}
+   |                   ++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs
new file mode 100644
index 00000000000..c6f9115cde7
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.rs
@@ -0,0 +1,9 @@
+#![deny(rust_2024_compatibility)]
+#![feature(unsafe_attributes)]
+
+#[no_mangle]
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+extern "C" fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr
new file mode 100644
index 00000000000..f0689d9883c
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/in_2024_compatibility.stderr
@@ -0,0 +1,21 @@
+error: unsafe attribute used without unsafe
+  --> $DIR/in_2024_compatibility.rs:4:3
+   |
+LL | #[no_mangle]
+   |   ^^^^^^^^^ usage of unsafe attribute
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+note: the lint level is defined here
+  --> $DIR/in_2024_compatibility.rs:1:9
+   |
+LL | #![deny(rust_2024_compatibility)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: `#[deny(unsafe_attr_outside_unsafe)]` implied by `#[deny(rust_2024_compatibility)]`
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | #[unsafe(no_mangle)]
+   |   +++++++         +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs
new file mode 100644
index 00000000000..279ced2525a
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attribute-marked.rs
@@ -0,0 +1,12 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+//@ check-pass
+
+#![feature(unsafe_attributes)]
+
+#[unsafe(no_mangle)]
+extern "C" fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed
new file mode 100644
index 00000000000..6ebdff0334c
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.fixed
@@ -0,0 +1,61 @@
+//@ run-rustfix
+#![feature(unsafe_attributes)]
+#![deny(unsafe_attr_outside_unsafe)]
+
+macro_rules! tt {
+    ($e:tt) => {
+        #$e
+        extern fn foo() {}
+    }
+}
+
+macro_rules! ident {
+    ($e:ident) => {
+        #[unsafe($e)]
+        //~^ ERROR: unsafe attribute used without unsafe
+        //~| WARN this is accepted in the current edition
+        extern fn bar() {}
+    }
+}
+
+macro_rules! ident2 {
+    ($e:ident, $l:literal) => {
+        #[unsafe($e = $l)]
+        //~^ ERROR: unsafe attribute used without unsafe
+        //~| WARN this is accepted in the current edition
+        extern fn bars() {}
+    }
+}
+
+macro_rules! meta {
+    ($m:meta) => {
+        #[$m]
+        extern fn baz() {}
+    }
+}
+
+macro_rules! meta2 {
+    ($m:meta) => {
+        #[$m]
+        extern fn baw() {}
+    }
+}
+
+tt!([unsafe(no_mangle)]);
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+ident!(no_mangle);
+meta!(unsafe(no_mangle));
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+meta2!(unsafe(export_name = "baw"));
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+ident2!(export_name, "bars");
+
+#[unsafe(no_mangle)]
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+extern "C" fn one() {}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs
new file mode 100644
index 00000000000..c78ff45ea4c
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.rs
@@ -0,0 +1,61 @@
+//@ run-rustfix
+#![feature(unsafe_attributes)]
+#![deny(unsafe_attr_outside_unsafe)]
+
+macro_rules! tt {
+    ($e:tt) => {
+        #$e
+        extern fn foo() {}
+    }
+}
+
+macro_rules! ident {
+    ($e:ident) => {
+        #[$e]
+        //~^ ERROR: unsafe attribute used without unsafe
+        //~| WARN this is accepted in the current edition
+        extern fn bar() {}
+    }
+}
+
+macro_rules! ident2 {
+    ($e:ident, $l:literal) => {
+        #[$e = $l]
+        //~^ ERROR: unsafe attribute used without unsafe
+        //~| WARN this is accepted in the current edition
+        extern fn bars() {}
+    }
+}
+
+macro_rules! meta {
+    ($m:meta) => {
+        #[$m]
+        extern fn baz() {}
+    }
+}
+
+macro_rules! meta2 {
+    ($m:meta) => {
+        #[$m]
+        extern fn baw() {}
+    }
+}
+
+tt!([no_mangle]);
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+ident!(no_mangle);
+meta!(no_mangle);
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+meta2!(export_name = "baw");
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+ident2!(export_name, "bars");
+
+#[no_mangle]
+//~^ ERROR: unsafe attribute used without unsafe
+//~| WARN this is accepted in the current edition
+extern "C" fn one() {}
+
+fn main() {}
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr
new file mode 100644
index 00000000000..c95984f58ec
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr
@@ -0,0 +1,93 @@
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:44:6
+   |
+LL | tt!([no_mangle]);
+   |      ^^^^^^^^^ usage of unsafe attribute
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+note: the lint level is defined here
+  --> $DIR/unsafe-attributes-fix.rs:3:9
+   |
+LL | #![deny(unsafe_attr_outside_unsafe)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | tt!([unsafe(no_mangle)]);
+   |      +++++++         +
+
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:14:11
+   |
+LL |         #[$e]
+   |           ^^ usage of unsafe attribute
+...
+LL | ident!(no_mangle);
+   | ----------------- in this macro invocation
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+   = note: this error originates in the macro `ident` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: wrap the attribute in `unsafe(...)`
+   |
+LL |         #[unsafe($e)]
+   |           +++++++  +
+
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:48:7
+   |
+LL | meta!(no_mangle);
+   |       ^^^^^^^^^ usage of unsafe attribute
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | meta!(unsafe(no_mangle));
+   |       +++++++         +
+
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:51:8
+   |
+LL | meta2!(export_name = "baw");
+   |        ^^^^^^^^^^^ usage of unsafe attribute
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | meta2!(unsafe(export_name = "baw"));
+   |        +++++++                   +
+
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:23:11
+   |
+LL |         #[$e = $l]
+   |           ^^ usage of unsafe attribute
+...
+LL | ident2!(export_name, "bars");
+   | ---------------------------- in this macro invocation
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+   = note: this error originates in the macro `ident2` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: wrap the attribute in `unsafe(...)`
+   |
+LL |         #[unsafe($e = $l)]
+   |           +++++++       +
+
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes-fix.rs:56:3
+   |
+LL | #[no_mangle]
+   |   ^^^^^^^^^ usage of unsafe attribute
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
+   = note: for more information, see issue #123757 <https://github.com/rust-lang/rust/issues/123757>
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | #[unsafe(no_mangle)]
+   |   +++++++         +
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr
new file mode 100644
index 00000000000..35475d66716
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.edition2024.stderr
@@ -0,0 +1,13 @@
+error: unsafe attribute used without unsafe
+  --> $DIR/unsafe-attributes.rs:9:3
+   |
+LL | #[no_mangle]
+   |   ^^^^^^^^^ usage of unsafe attribute
+   |
+help: wrap the attribute in `unsafe(...)`
+   |
+LL | #[unsafe(no_mangle)]
+   |   +++++++         +
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs
new file mode 100644
index 00000000000..3a6af9dfb2b
--- /dev/null
+++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes.rs
@@ -0,0 +1,12 @@
+//@ revisions: edition2021 edition2024
+//@[edition2021] edition:2021
+//@[edition2021] check-pass
+//@[edition2024] edition:2024
+//@[edition2024] compile-flags: -Zunstable-options
+
+#![feature(unsafe_attributes)]
+
+#[no_mangle] //[edition2024]~ ERROR: unsafe attribute used without unsafe
+extern "C" fn foo() {}
+
+fn main() {}
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
index 3f8011d961a..6bbd81ae3e1 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.32bit.stderr
@@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0080]: it is undefined behavior to use this value
+error[E0080]: evaluation of constant value failed
   --> $DIR/stack-overflow-trait-infer-98842.rs:15:1
    |
 LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 4, align: 4) {
-               00 00 00 00                                     │ ....
-           }
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
index 04e2c4483bf..6bbd81ae3e1 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.64bit.stderr
@@ -9,15 +9,11 @@ LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
-error[E0080]: it is undefined behavior to use this value
+error[E0080]: evaluation of constant value failed
   --> $DIR/stack-overflow-trait-infer-98842.rs:15:1
    |
 LL | const _: *const Foo = 0 as _;
    | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 8, align: 8) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.rs b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
index 54d50346cc8..be4807b2e4a 100644
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.rs
+++ b/tests/ui/sized/stack-overflow-trait-infer-98842.rs
@@ -13,6 +13,6 @@ struct Foo(<&'static Foo as ::core::ops::Deref>::Target);
 // and it will infinitely recurse somewhere trying to figure out the
 // size of this pointer (is my guess):
 const _: *const Foo = 0 as _;
-//~^ ERROR it is undefined behavior to use this value
+//~^ ERROR evaluation of constant value failed
 
 pub fn main() {}
diff --git a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr b/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
deleted file mode 100644
index 8ddddeb5bf2..00000000000
--- a/tests/ui/sized/stack-overflow-trait-infer-98842.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0391]: cycle detected when computing layout of `Foo`
-   |
-   = note: ...which requires computing layout of `<&'static Foo as core::ops::deref::Deref>::Target`...
-   = note: ...which again requires computing layout of `Foo`, completing the cycle
-note: cycle used when const-evaluating + checking `_`
-  --> $DIR/stack-overflow-trait-infer-98842.rs:13:1
-   |
-LL | const _: *const Foo = 0 as _;
-   | ^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0080]: it is undefined behavior to use this value
-  --> $DIR/stack-overflow-trait-infer-98842.rs:13:1
-   |
-LL | const _: *const Foo = 0 as _;
-   | ^^^^^^^^^^^^^^^^^^^ a cycle occurred during layout computation
-   |
-   = note: the raw bytes of the constant (size: 8, align: 8) {
-               00 00 00 00 00 00 00 00                         │ ........
-           }
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0080, E0391.
-For more information about an error, try `rustc --explain E0080`.