about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock18
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs12
-rw-r--r--compiler/rustc_attr_data_structures/src/encode_cross_crate.rs4
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs139
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs118
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs37
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs150
-rw-r--r--compiler/rustc_expand/messages.ftl27
-rw-r--r--compiler/rustc_expand/src/base.rs110
-rw-r--r--compiler/rustc_expand/src/errors.rs66
-rw-r--r--compiler/rustc_expand/src/expand.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs19
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs17
-rw-r--r--compiler/rustc_middle/src/ty/context.rs35
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs5
-rw-r--r--compiler/rustc_middle/src/ty/region.rs2
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs10
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs38
-rw-r--r--compiler/rustc_passes/src/check_attr.rs27
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs81
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs4
-rw-r--r--compiler/rustc_resolve/src/imports.rs19
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs6
-rw-r--r--compiler/rustc_resolve/src/lib.rs43
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_span/src/hygiene.rs16
-rw-r--r--compiler/rustc_span/src/lib.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_type_ir/src/relate.rs16
-rw-r--r--library/alloc/Cargo.toml2
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/env.rs2
-rw-r--r--library/std/src/sys/pal/unix/os.rs5
-rw-r--r--library/sysroot/Cargo.toml2
-rw-r--r--library/windows_targets/src/lib.rs16
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs6
-rw-r--r--src/bootstrap/src/utils/shared_helpers.rs22
-rw-r--r--src/bootstrap/src/utils/tests/mod.rs4
-rw-r--r--src/bootstrap/src/utils/tests/shared_helpers_tests.rs (renamed from src/bootstrap/src/utils/shared_helpers/tests.rs)7
-rw-r--r--src/ci/docker/host-x86_64/pr-check-1/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile5
-rwxr-xr-xsrc/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py140
-rw-r--r--src/librustdoc/clean/mod.rs51
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs4
-rw-r--r--src/tools/compiletest/src/directives.rs1
-rw-r--r--src/tools/generate-copyright/Cargo.toml2
-rw-r--r--src/tools/generate-copyright/src/cargo_metadata.rs3
-rw-r--r--src/tools/tidy/Cargo.toml2
-rw-r--r--src/tools/tidy/src/deps.rs18
-rw-r--r--tests/assembly-llvm/asm/aarch64-outline-atomics.rs2
-rw-r--r--tests/codegen-llvm/cffi/c-variadic-ffi.rs86
-rw-r--r--tests/codegen-llvm/enum/enum-transparent-extract.rs31
-rw-r--r--tests/codegen-llvm/intrinsics/transmute-simd.rs176
-rw-r--r--tests/codegen-llvm/intrinsics/transmute.rs26
-rw-r--r--tests/coverage/async_closure.cov-map21
-rw-r--r--tests/crashes/121176.rs9
-rw-r--r--tests/crashes/129109.rs10
-rw-r--r--tests/crashes/130970.rs9
-rw-r--r--tests/crashes/131347.rs9
-rw-r--r--tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff2
-rw-r--r--tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff4
-rw-r--r--tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff4
-rw-r--r--tests/run-make/linker-warning/rmake.rs4
-rw-r--r--tests/run-make/uefi-qemu/rmake.rs84
-rw-r--r--tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.lock (renamed from src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock)0
-rw-r--r--tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.toml (renamed from src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml)0
-rw-r--r--tests/run-make/uefi-qemu/uefi_qemu_test/src/main.rs (renamed from src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs)9
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr45
-rw-r--r--tests/ui/attributes/unsafe/proc-unsafe-attributes.rs1
-rw-r--r--tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr36
-rw-r--r--tests/ui/c-variadic/same-program-multiple-abis.rs112
-rw-r--r--tests/ui/c-variadic/variadic-ffi-1.rs5
-rw-r--r--tests/ui/c-variadic/variadic-ffi-1.stderr32
-rw-r--r--tests/ui/c-variadic/variadic-ffi-2-arm.rs9
-rw-r--r--tests/ui/c-variadic/variadic-ffi-2.rs28
-rw-r--r--tests/ui/c-variadic/variadic-ffi-2.stderr9
-rw-r--r--tests/ui/const-generics/min_const_generics/macro-fail-const.rs23
-rw-r--r--tests/ui/const-generics/min_const_generics/macro-fail-const.stderr51
-rw-r--r--tests/ui/const-generics/min_const_generics/macro-fail.rs7
-rw-r--r--tests/ui/const-generics/min_const_generics/macro-fail.stderr43
-rw-r--r--tests/ui/consts/const-unsized.rs4
-rw-r--r--tests/ui/consts/const-unsized.stderr32
-rw-r--r--tests/ui/coroutine/layout-error.rs1
-rw-r--r--tests/ui/coroutine/layout-error.stderr2
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.rs1
-rw-r--r--tests/ui/dyn-compatibility/taint-const-eval.stderr26
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.rs2
-rw-r--r--tests/ui/editions/edition-keywords-2018-2015-parsing.stderr11
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.rs2
-rw-r--r--tests/ui/editions/edition-keywords-2018-2018-parsing.stderr11
-rw-r--r--tests/ui/extern/issue-36122-accessing-externed-dst.rs1
-rw-r--r--tests/ui/extern/issue-36122-accessing-externed-dst.stderr13
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs2
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr12
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs14
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr24
-rw-r--r--tests/ui/layout/issue-84108.rs2
-rw-r--r--tests/ui/layout/issue-84108.stderr21
-rw-r--r--tests/ui/macros/trace-macro.rs3
-rw-r--r--tests/ui/mir/static-by-value-dyn.rs14
-rw-r--r--tests/ui/mir/static-by-value-dyn.stderr19
-rw-r--r--tests/ui/mir/static-by-value-slice.rs10
-rw-r--r--tests/ui/mir/static-by-value-slice.stderr12
-rw-r--r--tests/ui/mir/static-by-value-str.rs15
-rw-r--r--tests/ui/mir/static-by-value-str.stderr13
-rw-r--r--tests/ui/mir/unsized-extern-static.rs13
-rw-r--r--tests/ui/mir/unsized-extern-static.stderr20
-rw-r--r--tests/ui/offset-of/offset-of-tuple-field.rs22
-rw-r--r--tests/ui/offset-of/offset-of-tuple-field.stderr81
-rw-r--r--tests/ui/offset-of/offset-of-tuple.rs15
-rw-r--r--tests/ui/offset-of/offset-of-tuple.stderr123
-rw-r--r--tests/ui/proc-macro/attribute.rs51
-rw-r--r--tests/ui/proc-macro/attribute.stderr152
-rw-r--r--tests/ui/proc-macro/invalid-attributes.rs24
-rw-r--r--tests/ui/proc-macro/invalid-attributes.stderr53
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.rs14
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.stderr17
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs2
-rw-r--r--tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr17
-rw-r--r--tests/ui/self/self_type_keyword.rs2
-rw-r--r--tests/ui/self/self_type_keyword.stderr20
-rw-r--r--tests/ui/self/self_type_macro_name.rs6
-rw-r--r--tests/ui/self/self_type_macro_name.stderr8
-rw-r--r--tests/ui/static/issue-24446.rs2
-rw-r--r--tests/ui/static/issue-24446.stderr26
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-static.rs4
-rw-r--r--tests/ui/traits/bound/on-structs-and-enums-static.stderr26
-rw-r--r--tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.rs2
-rw-r--r--tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs13
-rw-r--r--tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr56
-rw-r--r--tests/ui/wf/wf-static-type.rs2
-rw-r--r--tests/ui/wf/wf-static-type.stderr39
147 files changed, 1960 insertions, 1466 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 9e0561199ab..6be3bced5e1 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -443,20 +443,6 @@ dependencies = [
 
 [[package]]
 name = "cargo_metadata"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba"
-dependencies = [
- "camino",
- "cargo-platform 0.1.9",
- "semver",
- "serde",
- "serde_json",
- "thiserror 2.0.12",
-]
-
-[[package]]
-name = "cargo_metadata"
 version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5cfca2aaa699835ba88faf58a06342a314a950d2b9686165e038286c30316868"
@@ -1364,7 +1350,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "askama",
- "cargo_metadata 0.18.1",
+ "cargo_metadata 0.21.0",
  "serde",
  "serde_json",
  "thiserror 1.0.69",
@@ -5370,7 +5356,7 @@ name = "tidy"
 version = "0.1.0"
 dependencies = [
  "build_helper",
- "cargo_metadata 0.19.2",
+ "cargo_metadata 0.21.0",
  "fluent-syntax",
  "ignore",
  "miropt-test-tools",
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index 1e2576bef2c..610c93a253c 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -416,12 +416,24 @@ pub enum AttributeKind {
     /// Represents `#[pointee]`
     Pointee(Span),
 
+    /// Represents `#[proc_macro]`
+    ProcMacro(Span),
+
+    /// Represents `#[proc_macro_attribute]`
+    ProcMacroAttribute(Span),
+
+    /// Represents `#[proc_macro_derive]`
+    ProcMacroDerive { trait_name: Symbol, helper_attrs: ThinVec<Symbol>, span: Span },
+
     /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
     PubTransparent(Span),
 
     /// Represents [`#[repr]`](https://doc.rust-lang.org/stable/reference/type-layout.html#representations).
     Repr { reprs: ThinVec<(ReprAttr, Span)>, first_span: Span },
 
+    /// Represents `#[rustc_builtin_macro]`.
+    RustcBuiltinMacro { builtin_name: Option<Symbol>, helper_attrs: ThinVec<Symbol>, span: Span },
+
     /// Represents `#[rustc_layout_scalar_valid_range_end]`.
     RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
 
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index 159b807a3b2..af2d46d0bc7 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -61,8 +61,12 @@ impl AttributeKind {
             PassByValue(..) => Yes,
             Path(..) => No,
             Pointee(..) => No,
+            ProcMacro(..) => No,
+            ProcMacroAttribute(..) => No,
+            ProcMacroDerive { .. } => No,
             PubTransparent(..) => Yes,
             Repr { .. } => No,
+            RustcBuiltinMacro { .. } => Yes,
             RustcLayoutScalarValidRangeEnd(..) => Yes,
             RustcLayoutScalarValidRangeStart(..) => Yes,
             RustcObjectLifetimeDefault => No,
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 15b90bd2ed7..0c10517d044 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -41,6 +41,7 @@ pub(crate) mod must_use;
 pub(crate) mod no_implicit_prelude;
 pub(crate) mod non_exhaustive;
 pub(crate) mod path;
+pub(crate) mod proc_macro_attrs;
 pub(crate) mod repr;
 pub(crate) mod rustc_internal;
 pub(crate) mod semantics;
diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
new file mode 100644
index 00000000000..4de77dc268e
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
@@ -0,0 +1,139 @@
+use rustc_attr_data_structures::AttributeKind;
+use rustc_feature::{AttributeTemplate, template};
+use rustc_span::{Span, Symbol, sym};
+use thin_vec::ThinVec;
+
+use crate::attributes::{
+    AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
+};
+use crate::context::{AcceptContext, Stage};
+use crate::parser::ArgParser;
+
+pub(crate) struct ProcMacroParser;
+impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
+    const PATH: &[Symbol] = &[sym::proc_macro];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
+}
+
+pub(crate) struct ProcMacroAttributeParser;
+impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
+    const PATH: &[Symbol] = &[sym::proc_macro_attribute];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
+}
+
+pub(crate) struct ProcMacroDeriveParser;
+impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
+    const PATH: &[Symbol] = &[sym::proc_macro_derive];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate =
+        template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let (trait_name, helper_attrs) = parse_derive_like(cx, args, true)?;
+        Some(AttributeKind::ProcMacroDerive {
+            trait_name: trait_name.expect("Trait name is mandatory, so it is present"),
+            helper_attrs,
+            span: cx.attr_span,
+        })
+    }
+}
+
+pub(crate) struct RustcBuiltinMacroParser;
+impl<S: Stage> SingleAttributeParser<S> for RustcBuiltinMacroParser {
+    const PATH: &[Symbol] = &[sym::rustc_builtin_macro];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+    const TEMPLATE: AttributeTemplate =
+        template!(List: "TraitName, /*opt*/ attributes(name1, name2, ...)");
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let (builtin_name, helper_attrs) = parse_derive_like(cx, args, false)?;
+        Some(AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, span: cx.attr_span })
+    }
+}
+
+fn parse_derive_like<S: Stage>(
+    cx: &mut AcceptContext<'_, '_, S>,
+    args: &ArgParser<'_>,
+    trait_name_mandatory: bool,
+) -> Option<(Option<Symbol>, ThinVec<Symbol>)> {
+    let Some(list) = args.list() else {
+        // For #[rustc_builtin_macro], it is permitted to leave out the trait name
+        if args.no_args().is_ok() && !trait_name_mandatory {
+            return Some((None, ThinVec::new()));
+        }
+        cx.expected_list(cx.attr_span);
+        return None;
+    };
+    let mut items = list.mixed();
+
+    // Parse the name of the trait that is derived.
+    let Some(trait_attr) = items.next() else {
+        cx.expected_at_least_one_argument(list.span);
+        return None;
+    };
+    let Some(trait_attr) = trait_attr.meta_item() else {
+        cx.unexpected_literal(trait_attr.span());
+        return None;
+    };
+    let Some(trait_ident) = trait_attr.path().word() else {
+        cx.expected_identifier(trait_attr.path().span());
+        return None;
+    };
+    if !trait_ident.name.can_be_raw() {
+        cx.expected_identifier(trait_ident.span);
+        return None;
+    }
+    if let Err(e) = trait_attr.args().no_args() {
+        cx.expected_no_args(e);
+        return None;
+    };
+
+    // Parse optional attributes
+    let mut attributes = ThinVec::new();
+    if let Some(attrs) = items.next() {
+        let Some(attr_list) = attrs.meta_item() else {
+            cx.expected_list(attrs.span());
+            return None;
+        };
+        if !attr_list.path().word_is(sym::attributes) {
+            cx.expected_specific_argument(attrs.span(), vec!["attributes"]);
+            return None;
+        }
+        let Some(attr_list) = attr_list.args().list() else {
+            cx.expected_list(attrs.span());
+            return None;
+        };
+
+        // Parse item in `attributes(...)` argument
+        for attr in attr_list.mixed() {
+            let Some(attr) = attr.meta_item() else {
+                cx.expected_identifier(attr.span());
+                return None;
+            };
+            if let Err(e) = attr.args().no_args() {
+                cx.expected_no_args(e);
+                return None;
+            };
+            let Some(ident) = attr.path().word() else {
+                cx.expected_identifier(attr.path().span());
+                return None;
+            };
+            if !ident.name.can_be_raw() {
+                cx.expected_identifier(ident.span);
+                return None;
+            }
+            attributes.push(ident.name);
+        }
+    }
+
+    // If anything else is specified, we should reject it
+    if let Some(next) = items.next() {
+        cx.expected_no_args(next.span());
+    }
+
+    Some((Some(trait_ident.name), attributes))
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 45bfe345207..9b86d101840 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -38,6 +38,9 @@ use crate::attributes::must_use::MustUseParser;
 use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
 use crate::attributes::non_exhaustive::NonExhaustiveParser;
 use crate::attributes::path::PathParser as PathAttributeParser;
+use crate::attributes::proc_macro_attrs::{
+    ProcMacroAttributeParser, ProcMacroDeriveParser, ProcMacroParser, RustcBuiltinMacroParser,
+};
 use crate::attributes::repr::{AlignParser, ReprParser};
 use crate::attributes::rustc_internal::{
     RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@@ -154,6 +157,8 @@ attribute_parsers!(
         Single<MustUseParser>,
         Single<OptimizeParser>,
         Single<PathAttributeParser>,
+        Single<ProcMacroDeriveParser>,
+        Single<RustcBuiltinMacroParser>,
         Single<RustcForceInlineParser>,
         Single<RustcLayoutScalarValidRangeEnd>,
         Single<RustcLayoutScalarValidRangeStart>,
@@ -186,6 +191,8 @@ attribute_parsers!(
         Single<WithoutArgs<ParenSugarParser>>,
         Single<WithoutArgs<PassByValueParser>>,
         Single<WithoutArgs<PointeeParser>>,
+        Single<WithoutArgs<ProcMacroAttributeParser>>,
+        Single<WithoutArgs<ProcMacroParser>>,
         Single<WithoutArgs<PubTransparentParser>>,
         Single<WithoutArgs<SpecializationTraitParser>>,
         Single<WithoutArgs<StdInternalSymbolParser>>,
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 42b7e0e06d1..09f5e6f6efc 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -1,11 +1,13 @@
-use std::mem;
+use std::{mem, slice};
 
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{self as ast, NodeId, attr};
+use rustc_ast::{self as ast, HasNodeId, NodeId, attr};
 use rustc_ast_pretty::pprust;
+use rustc_attr_data_structures::AttributeKind;
+use rustc_attr_parsing::AttributeParser;
 use rustc_errors::DiagCtxtHandle;
-use rustc_expand::base::{ExtCtxt, ResolverExpand, parse_macro_name_and_helper_attrs};
+use rustc_expand::base::{ExtCtxt, ResolverExpand};
 use rustc_expand::expand::{AstFragment, ExpansionConfig};
 use rustc_feature::Features;
 use rustc_session::Session;
@@ -22,7 +24,7 @@ struct ProcMacroDerive {
     trait_name: Symbol,
     function_ident: Ident,
     span: Span,
-    attrs: Vec<Symbol>,
+    attrs: ThinVec<Symbol>,
 }
 
 struct ProcMacroDef {
@@ -41,6 +43,7 @@ struct CollectProcMacros<'a> {
     macros: Vec<ProcMacro>,
     in_root: bool,
     dcx: DiagCtxtHandle<'a>,
+    session: &'a Session,
     source_map: &'a SourceMap,
     is_proc_macro_crate: bool,
     is_test_crate: bool,
@@ -63,6 +66,7 @@ pub fn inject(
         macros: Vec::new(),
         in_root: true,
         dcx,
+        session: sess,
         source_map: sess.source_map(),
         is_proc_macro_crate,
         is_test_crate,
@@ -98,8 +102,18 @@ impl<'a> CollectProcMacros<'a> {
         function_ident: Ident,
         attr: &'a ast::Attribute,
     ) {
-        let Some((trait_name, proc_attrs)) =
-            parse_macro_name_and_helper_attrs(self.dcx, attr, "derive")
+        let Some(rustc_hir::Attribute::Parsed(AttributeKind::ProcMacroDerive {
+            trait_name,
+            helper_attrs,
+            ..
+        })) = AttributeParser::parse_limited(
+            self.session,
+            slice::from_ref(attr),
+            sym::proc_macro_derive,
+            item.span,
+            item.node_id(),
+            None,
+        )
         else {
             return;
         };
@@ -110,7 +124,7 @@ impl<'a> CollectProcMacros<'a> {
                 span: item.span,
                 trait_name,
                 function_ident,
-                attrs: proc_attrs,
+                attrs: helper_attrs,
             }));
         } else {
             let msg = if !self.in_root {
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
index 574463be7ff..39a59560c9d 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen/spans.rs
@@ -39,10 +39,7 @@ impl Coords {
 /// or other expansions), and if it does happen then skipping a span or function is
 /// better than an ICE or `llvm-cov` failure that the user might have no way to avoid.
 pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span) -> Option<Coords> {
-    if span.is_empty() {
-        debug_assert!(false, "can't make coords from empty span: {span:?}");
-        return None;
-    }
+    let span = ensure_non_empty_span(source_map, span)?;
 
     let lo = span.lo();
     let hi = span.hi();
@@ -73,6 +70,29 @@ pub(crate) fn make_coords(source_map: &SourceMap, file: &SourceFile, span: Span)
     })
 }
 
+fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
+    if !span.is_empty() {
+        return Some(span);
+    }
+
+    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
+    source_map
+        .span_to_source(span, |src, start, end| try {
+            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
+            // but in this case we have specifically checked that the character
+            // we're skipping over is one of two specific ASCII characters, so
+            // adjusting by exactly 1 byte is correct.
+            if src.as_bytes().get(end).copied() == Some(b'{') {
+                Some(span.with_hi(span.hi() + BytePos(1)))
+            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
+                Some(span.with_lo(span.lo() - BytePos(1)))
+            } else {
+                None
+            }
+        })
+        .ok()?
+}
+
 /// If `llvm-cov` sees a source region that is improperly ordered (end < start),
 /// it will immediately exit with a fatal error. To prevent that from happening,
 /// discard regions that are improperly ordered, or might be interpreted in a
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index fcc0d378f06..7b27e496986 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -382,26 +382,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                 let width = size.bits();
                 let llty = self.type_ix(width);
                 match name {
-                    sym::ctlz | sym::cttz => {
-                        let y = self.const_bool(false);
-                        let ret = self.call_intrinsic(
-                            format!("llvm.{name}"),
-                            &[llty],
-                            &[args[0].immediate(), y],
-                        );
-
-                        self.intcast(ret, result.layout.llvm_type(self), false)
-                    }
-                    sym::ctlz_nonzero => {
-                        let y = self.const_bool(true);
-                        let ret =
-                            self.call_intrinsic("llvm.ctlz", &[llty], &[args[0].immediate(), y]);
-                        self.intcast(ret, result.layout.llvm_type(self), false)
-                    }
-                    sym::cttz_nonzero => {
-                        let y = self.const_bool(true);
+                    sym::ctlz | sym::ctlz_nonzero | sym::cttz | sym::cttz_nonzero => {
+                        let y =
+                            self.const_bool(name == sym::ctlz_nonzero || name == sym::cttz_nonzero);
+                        let llvm_name = if name == sym::ctlz || name == sym::ctlz_nonzero {
+                            "llvm.ctlz"
+                        } else {
+                            "llvm.cttz"
+                        };
                         let ret =
-                            self.call_intrinsic("llvm.cttz", &[llty], &[args[0].immediate(), y]);
+                            self.call_intrinsic(llvm_name, &[llty], &[args[0].immediate(), y]);
                         self.intcast(ret, result.layout.llvm_type(self), false)
                     }
                     sym::ctpop => {
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 8edbae115bf..53899da183a 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -405,6 +405,8 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
         ("mips64" | "mips64r6", _) => false,
         // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
         ("nvptx64", _) => false,
+        // Unsupported https://github.com/llvm/llvm-project/issues/121122
+        ("amdgpu", _) => false,
         // ABI bugs <https://github.com/rust-lang/rust/issues/125109> et al. (full
         // list at <https://github.com/rust-lang/rust/issues/116909>)
         ("powerpc" | "powerpc64", _) => false,
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 6d6465dd798..c2c023af090 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -1,12 +1,13 @@
 //! An analysis to determine which locals require allocas and
 //! which do not.
 
+use rustc_abi as abi;
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_index::bit_set::DenseBitSet;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::{self, DefLocation, Location, TerminatorKind, traversal};
-use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::{bug, span_bug};
 use tracing::debug;
 
@@ -99,63 +100,75 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx>
         context: PlaceContext,
         location: Location,
     ) {
-        let cx = self.fx.cx;
-
-        if let Some((place_base, elem)) = place_ref.last_projection() {
-            let mut base_context = if context.is_mutating_use() {
-                PlaceContext::MutatingUse(MutatingUseContext::Projection)
-            } else {
-                PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection)
-            };
-
-            // Allow uses of projections that are ZSTs or from scalar fields.
-            let is_consume = matches!(
-                context,
-                PlaceContext::NonMutatingUse(
-                    NonMutatingUseContext::Copy | NonMutatingUseContext::Move,
-                )
-            );
-            if is_consume {
-                let base_ty = place_base.ty(self.fx.mir, cx.tcx());
-                let base_ty = self.fx.monomorphize(base_ty);
-
-                // ZSTs don't require any actual memory access.
-                let elem_ty = base_ty.projection_ty(cx.tcx(), self.fx.monomorphize(elem)).ty;
-                let span = self.fx.mir.local_decls[place_ref.local].source_info.span;
-                if cx.spanned_layout_of(elem_ty, span).is_zst() {
-                    return;
+        if !place_ref.projection.is_empty() {
+            const COPY_CONTEXT: PlaceContext =
+                PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+
+            // `PlaceElem::Index` is the only variant that can mention other `Local`s,
+            // so check for those up-front before any potential short-circuits.
+            for elem in place_ref.projection {
+                if let mir::PlaceElem::Index(index_local) = *elem {
+                    self.visit_local(index_local, COPY_CONTEXT, location);
                 }
+            }
 
-                if let mir::ProjectionElem::Field(..) = elem {
-                    let layout = cx.spanned_layout_of(base_ty.ty, span);
-                    if cx.is_backend_immediate(layout) || cx.is_backend_scalar_pair(layout) {
-                        // Recurse with the same context, instead of `Projection`,
-                        // potentially stopping at non-operand projections,
-                        // which would trigger `not_ssa` on locals.
-                        base_context = context;
-                    }
-                }
+            // If our local is already memory, nothing can make it *more* memory
+            // so we don't need to bother checking the projections further.
+            if self.locals[place_ref.local] == LocalKind::Memory {
+                return;
             }
 
-            if let mir::ProjectionElem::Deref = elem {
-                // Deref projections typically only read the pointer.
-                base_context = PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy);
+            if place_ref.is_indirect_first_projection() {
+                // If this starts with a `Deref`, we only need to record a read of the
+                // pointer being dereferenced, as all the subsequent projections are
+                // working on a place which is always supported. (And because we're
+                // looking at codegen MIR, it can only happen as the first projection.)
+                self.visit_local(place_ref.local, COPY_CONTEXT, location);
+                return;
             }
 
-            self.process_place(&place_base, base_context, location);
-            // HACK(eddyb) this emulates the old `visit_projection_elem`, this
-            // entire `visit_place`-like `process_place` method should be rewritten,
-            // now that we have moved to the "slice of projections" representation.
-            if let mir::ProjectionElem::Index(local) = elem {
-                self.visit_local(
-                    local,
-                    PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
-                    location,
-                );
+            if context.is_mutating_use() {
+                // If it's a mutating use it doesn't matter what the projections are,
+                // if there are *any* then we need a place to write. (For example,
+                // `_1 = Foo()` works in SSA but `_2.0 = Foo()` does not.)
+                let mut_projection = PlaceContext::MutatingUse(MutatingUseContext::Projection);
+                self.visit_local(place_ref.local, mut_projection, location);
+                return;
             }
-        } else {
-            self.visit_local(place_ref.local, context, location);
+
+            // Scan through to ensure the only projections are those which
+            // `FunctionCx::maybe_codegen_consume_direct` can handle.
+            let base_ty = self.fx.monomorphized_place_ty(mir::PlaceRef::from(place_ref.local));
+            let mut layout = self.fx.cx.layout_of(base_ty);
+            for elem in place_ref.projection {
+                layout = match *elem {
+                    mir::PlaceElem::Field(fidx, ..) => layout.field(self.fx.cx, fidx.as_usize()),
+                    mir::PlaceElem::Downcast(_, vidx)
+                        if let abi::Variants::Single { index: single_variant } =
+                            layout.variants
+                            && vidx == single_variant =>
+                    {
+                        layout.for_variant(self.fx.cx, vidx)
+                    }
+                    mir::PlaceElem::Subtype(subtype_ty) => {
+                        let subtype_ty = self.fx.monomorphize(subtype_ty);
+                        self.fx.cx.layout_of(subtype_ty)
+                    }
+                    _ => {
+                        self.locals[place_ref.local] = LocalKind::Memory;
+                        return;
+                    }
+                }
+            }
+            debug_assert!(
+                !self.fx.cx.is_backend_ref(layout),
+                "Post-projection {place_ref:?} layout should be non-Ref, but it's {layout:?}",
+            );
         }
+
+        // Even with supported projections, we still need to have `visit_local`
+        // check for things that can't be done in SSA (like `SharedBorrow`).
+        self.visit_local(place_ref.local, context, location);
     }
 }
 
@@ -170,11 +183,6 @@ impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> Visitor<'tcx> for LocalAnalyzer
 
         if let Some(local) = place.as_local() {
             self.define(local, DefLocation::Assignment(location));
-            if self.locals[local] != LocalKind::Memory {
-                if !self.fx.rvalue_creates_operand(rvalue) {
-                    self.locals[local] = LocalKind::Memory;
-                }
-            }
         } else {
             self.visit_place(place, PlaceContext::MutatingUse(MutatingUseContext::Store), location);
         }
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 8e308aac769..5459f95c186 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -335,13 +335,6 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
 
         let val = if field.is_zst() {
             OperandValue::ZeroSized
-        } else if let BackendRepr::SimdVector { .. } = self.layout.backend_repr {
-            // codegen_transmute_operand doesn't support SIMD, but since the previous
-            // check handled ZSTs, the only possible field access into something SIMD
-            // is to the `non_1zst_field` that's the same SIMD. (Other things, even
-            // just padding, would change the wrapper's representation type.)
-            assert_eq!(field.size, self.layout.size);
-            self.val
         } else if field.size == self.layout.size {
             assert_eq!(offset.bytes(), 0);
             fx.codegen_transmute_operand(bx, *self, field)
@@ -928,9 +921,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         match self.locals[place_ref.local] {
             LocalRef::Operand(mut o) => {
-                // Moves out of scalar and scalar pair fields are trivial.
-                for elem in place_ref.projection.iter() {
-                    match elem {
+                // We only need to handle the projections that
+                // `LocalAnalyzer::process_place` let make it here.
+                for elem in place_ref.projection {
+                    match *elem {
                         mir::ProjectionElem::Field(f, _) => {
                             assert!(
                                 !o.layout.ty.is_any_ptr(),
@@ -939,17 +933,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                             );
                             o = o.extract_field(self, bx, f.index());
                         }
-                        mir::ProjectionElem::Index(_)
-                        | mir::ProjectionElem::ConstantIndex { .. } => {
-                            // ZSTs don't require any actual memory access.
-                            // FIXME(eddyb) deduplicate this with the identical
-                            // checks in `codegen_consume` and `extract_field`.
-                            let elem = o.layout.field(bx.cx(), 0);
-                            if elem.is_zst() {
-                                o = OperandRef::zero_sized(elem);
-                            } else {
-                                return None;
-                            }
+                        mir::PlaceElem::Downcast(_, vidx) => {
+                            debug_assert_eq!(
+                                o.layout.variants,
+                                abi::Variants::Single { index: vidx },
+                            );
+                            let layout = o.layout.for_variant(bx.cx(), vidx);
+                            o = OperandRef { val: o.val, layout }
+                        }
+                        mir::PlaceElem::Subtype(subtype_ty) => {
+                            let subtype_ty = self.monomorphize(subtype_ty);
+                            let layout = self.cx.layout_of(subtype_ty);
+                            o = OperandRef { val: o.val, layout }
                         }
                         _ => return None,
                     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index a5759b79be4..8a67b8d6e5f 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -2,12 +2,12 @@ use rustc_abi::{self as abi, FIRST_VARIANT};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
-use rustc_middle::{bug, mir};
+use rustc_middle::{bug, mir, span_bug};
 use rustc_session::config::OptLevel;
 use tracing::{debug, instrument};
 
 use super::operand::{OperandRef, OperandRefBuilder, OperandValue};
-use super::place::{PlaceRef, codegen_tag_value};
+use super::place::{PlaceRef, PlaceValue, codegen_tag_value};
 use super::{FunctionCx, LocalRef};
 use crate::common::{IntPredicate, TypeKind};
 use crate::traits::*;
@@ -180,7 +180,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             }
 
             _ => {
-                assert!(self.rvalue_creates_operand(rvalue));
                 let temp = self.codegen_rvalue_operand(bx, rvalue);
                 temp.val.store(bx, dest);
             }
@@ -218,17 +217,26 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
     /// Transmutes an `OperandValue` to another `OperandValue`.
     ///
-    /// This is supported only for cases where [`Self::rvalue_creates_operand`]
-    /// returns `true`, and will ICE otherwise. (In particular, anything that
-    /// would need to `alloca` in order to return a `PlaceValue` will ICE,
-    /// expecting those to go via [`Self::codegen_transmute`] instead where
-    /// the destination place is already allocated.)
+    /// This is supported for all cases where the `cast` type is SSA,
+    /// but for non-ZSTs with [`abi::BackendRepr::Memory`] it ICEs.
     pub(crate) fn codegen_transmute_operand(
         &mut self,
         bx: &mut Bx,
         operand: OperandRef<'tcx, Bx::Value>,
         cast: TyAndLayout<'tcx>,
     ) -> OperandValue<Bx::Value> {
+        if let abi::BackendRepr::Memory { .. } = cast.backend_repr
+            && !cast.is_zst()
+        {
+            span_bug!(self.mir.span, "Use `codegen_transmute` to transmute to {cast:?}");
+        }
+
+        // `Layout` is interned, so we can do a cheap check for things that are
+        // exactly the same and thus don't need any handling.
+        if abi::Layout::eq(&operand.layout.layout, &cast.layout) {
+            return operand.val;
+        }
+
         // Check for transmutes that are always UB.
         if operand.layout.size != cast.size
             || operand.layout.is_uninhabited()
@@ -241,11 +249,22 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             return OperandValue::poison(bx, cast);
         }
 
+        // To or from pointers takes different methods, so we use this to restrict
+        // the SimdVector case to types which can be `bitcast` between each other.
+        #[inline]
+        fn vector_can_bitcast(x: abi::Scalar) -> bool {
+            matches!(
+                x,
+                abi::Scalar::Initialized {
+                    value: abi::Primitive::Int(..) | abi::Primitive::Float(..),
+                    ..
+                }
+            )
+        }
+
+        let cx = bx.cx();
         match (operand.val, operand.layout.backend_repr, cast.backend_repr) {
             _ if cast.is_zst() => OperandValue::ZeroSized,
-            (_, _, abi::BackendRepr::Memory { .. }) => {
-                bug!("Cannot `codegen_transmute_operand` to non-ZST memory-ABI output {cast:?}");
-            }
             (OperandValue::Ref(source_place_val), abi::BackendRepr::Memory { .. }, _) => {
                 assert_eq!(source_place_val.llextra, None);
                 // The existing alignment is part of `source_place_val`,
@@ -256,16 +275,46 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 OperandValue::Immediate(imm),
                 abi::BackendRepr::Scalar(from_scalar),
                 abi::BackendRepr::Scalar(to_scalar),
-            ) => OperandValue::Immediate(transmute_scalar(bx, imm, from_scalar, to_scalar)),
+            ) if from_scalar.size(cx) == to_scalar.size(cx) => {
+                OperandValue::Immediate(transmute_scalar(bx, imm, from_scalar, to_scalar))
+            }
+            (
+                OperandValue::Immediate(imm),
+                abi::BackendRepr::SimdVector { element: from_scalar, .. },
+                abi::BackendRepr::SimdVector { element: to_scalar, .. },
+            ) if vector_can_bitcast(from_scalar) && vector_can_bitcast(to_scalar) => {
+                let to_backend_ty = bx.cx().immediate_backend_type(cast);
+                OperandValue::Immediate(bx.bitcast(imm, to_backend_ty))
+            }
             (
                 OperandValue::Pair(imm_a, imm_b),
                 abi::BackendRepr::ScalarPair(in_a, in_b),
                 abi::BackendRepr::ScalarPair(out_a, out_b),
-            ) => OperandValue::Pair(
-                transmute_scalar(bx, imm_a, in_a, out_a),
-                transmute_scalar(bx, imm_b, in_b, out_b),
-            ),
-            _ => bug!("Cannot `codegen_transmute_operand` {operand:?} to {cast:?}"),
+            ) if in_a.size(cx) == out_a.size(cx) && in_b.size(cx) == out_b.size(cx) => {
+                OperandValue::Pair(
+                    transmute_scalar(bx, imm_a, in_a, out_a),
+                    transmute_scalar(bx, imm_b, in_b, out_b),
+                )
+            }
+            _ => {
+                // For any other potentially-tricky cases, make a temporary instead.
+                // If anything else wants the target local to be in memory this won't
+                // be hit, as `codegen_transmute` will get called directly. Thus this
+                // is only for places where everything else wants the operand form,
+                // and thus it's not worth making those places get it from memory.
+                //
+                // Notably, Scalar ⇌ ScalarPair cases go here to avoid padding
+                // and endianness issues, as do SimdVector ones to avoid worrying
+                // about things like f32x8 ⇌ ptrx4 that would need multiple steps.
+                let align = Ord::max(operand.layout.align.abi, cast.align.abi);
+                let size = Ord::max(operand.layout.size, cast.size);
+                let temp = PlaceValue::alloca(bx, size, align);
+                bx.lifetime_start(temp.llval, size);
+                operand.val.store(bx, temp.with_type(operand.layout));
+                let val = bx.load_operand(temp.with_type(cast)).val;
+                bx.lifetime_end(temp.llval, size);
+                val
+            }
         }
     }
 
@@ -326,8 +375,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         bx: &mut Bx,
         rvalue: &mir::Rvalue<'tcx>,
     ) -> OperandRef<'tcx, Bx::Value> {
-        assert!(self.rvalue_creates_operand(rvalue), "cannot codegen {rvalue:?} to operand",);
-
         match *rvalue {
             mir::Rvalue::Cast(ref kind, ref source, mir_cast_ty) => {
                 let operand = self.codegen_operand(bx, source);
@@ -653,8 +700,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 let ty = self.monomorphize(ty);
                 let layout = self.cx.layout_of(ty);
 
-                // `rvalue_creates_operand` has arranged that we only get here if
-                // we can build the aggregate immediate from the field immediates.
                 let mut builder = OperandRefBuilder::new(layout);
                 for (field_idx, field) in fields.iter_enumerated() {
                     let op = self.codegen_operand(bx, field);
@@ -955,69 +1000,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         OperandValue::Pair(val, of)
     }
-
-    /// Returns `true` if the `rvalue` can be computed into an [`OperandRef`],
-    /// rather than needing a full `PlaceRef` for the assignment destination.
-    ///
-    /// This is used by the [`super::analyze`] code to decide which MIR locals
-    /// can stay as SSA values (as opposed to generating `alloca` slots for them).
-    /// As such, some paths here return `true` even where the specific rvalue
-    /// will not actually take the operand path because the result type is such
-    /// that it always gets an `alloca`, but where it's not worth re-checking the
-    /// layout in this code when the right thing will happen anyway.
-    pub(crate) fn rvalue_creates_operand(&self, rvalue: &mir::Rvalue<'tcx>) -> bool {
-        match *rvalue {
-            mir::Rvalue::Cast(mir::CastKind::Transmute, ref operand, cast_ty) => {
-                let operand_ty = operand.ty(self.mir, self.cx.tcx());
-                let cast_layout = self.cx.layout_of(self.monomorphize(cast_ty));
-                let operand_layout = self.cx.layout_of(self.monomorphize(operand_ty));
-                match (operand_layout.backend_repr, cast_layout.backend_repr) {
-                    // When the output will be in memory anyway, just use its place
-                    // (instead of the operand path) unless it's the trivial ZST case.
-                    (_, abi::BackendRepr::Memory { .. }) => cast_layout.is_zst(),
-
-                    // Otherwise (for a non-memory output) if the input is memory
-                    // then we can just read the value from the place.
-                    (abi::BackendRepr::Memory { .. }, _) => true,
-
-                    // When we have scalar immediates, we can only convert things
-                    // where the sizes match, to avoid endianness questions.
-                    (abi::BackendRepr::Scalar(a), abi::BackendRepr::Scalar(b)) =>
-                        a.size(self.cx) == b.size(self.cx),
-                    (abi::BackendRepr::ScalarPair(a0, a1), abi::BackendRepr::ScalarPair(b0, b1)) =>
-                        a0.size(self.cx) == b0.size(self.cx) && a1.size(self.cx) == b1.size(self.cx),
-
-                    // Mixing Scalars and ScalarPairs can get quite complicated when
-                    // padding and undef get involved, so leave that to the memory path.
-                    (abi::BackendRepr::Scalar(_), abi::BackendRepr::ScalarPair(_, _)) |
-                    (abi::BackendRepr::ScalarPair(_, _), abi::BackendRepr::Scalar(_)) => false,
-
-                    // SIMD vectors aren't worth the trouble of dealing with complex
-                    // cases like from vectors of f32 to vectors of pointers or
-                    // from fat pointers to vectors of u16. (See #143194 #110021 ...)
-                    (abi::BackendRepr::SimdVector { .. }, _) | (_, abi::BackendRepr::SimdVector { .. }) => false,
-                }
-            }
-            mir::Rvalue::Ref(..) |
-            mir::Rvalue::CopyForDeref(..) |
-            mir::Rvalue::RawPtr(..) |
-            mir::Rvalue::Len(..) |
-            mir::Rvalue::Cast(..) | // (*)
-            mir::Rvalue::ShallowInitBox(..) | // (*)
-            mir::Rvalue::BinaryOp(..) |
-            mir::Rvalue::UnaryOp(..) |
-            mir::Rvalue::Discriminant(..) |
-            mir::Rvalue::NullaryOp(..) |
-            mir::Rvalue::ThreadLocalRef(_) |
-            mir::Rvalue::Use(..) |
-            mir::Rvalue::Repeat(..) | // (*)
-            mir::Rvalue::Aggregate(..) | // (*)
-            mir::Rvalue::WrapUnsafeBinder(..) => // (*)
-                true,
-        }
-
-        // (*) this is only true if the type is suitable
-    }
 }
 
 /// Transmutes a single scalar value `imm` from `from_scalar` to `to_scalar`.
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 89d6e62834d..5a53670c865 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -1,26 +1,8 @@
-expand_arg_not_attributes =
-    second argument must be `attributes`
-
-expand_attr_no_arguments =
-    attribute must have either one or two arguments
-
-expand_attribute_meta_item =
-    attribute must be a meta item, not a literal
-
-expand_attribute_single_word =
-    attribute must only be a single word
-
 expand_attributes_on_expressions_experimental =
     attributes on expressions are experimental
     .help_outer_doc = `///` is used for outer documentation comments; for a plain comment, use `//`
     .help_inner_doc = `//!` is used for inner documentation comments; for a plain comment, use `//` by removing the `!` or inserting a space in between them: `// !`
 
-expand_attributes_wrong_form =
-    attribute must be of form: `attributes(foo, bar)`
-
-expand_cannot_be_name_of_macro =
-    `{$trait_ident}` cannot be a name of {$macro_type} macro
-
 expand_collapse_debuginfo_illegal =
     illegal value for attribute #[collapse_debuginfo(no|external|yes)]
 
@@ -71,9 +53,6 @@ expand_glob_delegation_outside_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
-
 expand_incomplete_parse =
     macro expansion ignores {$descr} and any tokens following
     .label = caused by the macro expansion here
@@ -165,12 +144,6 @@ expand_mve_unrecognized_var =
 expand_non_inline_modules_in_proc_macro_input_are_unstable =
     non-inline modules in proc macro input are unstable
 
-expand_not_a_meta_item =
-    not a meta item
-
-expand_only_one_word =
-    must only be one word
-
 expand_proc_macro_back_compat = using an old version of `{$crate_name}`
     .note = older versions of the `{$crate_name}` crate no longer compile; please update to `{$crate_name}` v{$fixed_version}, or switch to one of the `{$crate_name}` alternatives
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 25ec5401111..c01320fc644 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -861,7 +861,7 @@ impl SyntaxExtension {
     /// | (unspecified) | no  | if-ext        | if-ext   | yes |
     /// | external      | no  | if-ext        | if-ext   | yes |
     /// | yes           | yes | yes           | yes      | yes |
-    fn get_collapse_debuginfo(sess: &Session, attrs: &[impl AttributeExt], ext: bool) -> bool {
+    fn get_collapse_debuginfo(sess: &Session, attrs: &[hir::Attribute], ext: bool) -> bool {
         let flag = sess.opts.cg.collapse_macro_debuginfo;
         let attr = ast::attr::find_by_name(attrs, sym::collapse_debuginfo)
             .and_then(|attr| {
@@ -872,7 +872,7 @@ impl SyntaxExtension {
                     .ok()
             })
             .unwrap_or_else(|| {
-                if ast::attr::contains_name(attrs, sym::rustc_builtin_macro) {
+                if find_attr!(attrs, AttributeKind::RustcBuiltinMacro { .. }) {
                     CollapseMacroDebuginfo::Yes
                 } else {
                     CollapseMacroDebuginfo::Unspecified
@@ -915,16 +915,18 @@ impl SyntaxExtension {
         let collapse_debuginfo = Self::get_collapse_debuginfo(sess, attrs, !is_local);
         tracing::debug!(?name, ?local_inner_macros, ?collapse_debuginfo, ?allow_internal_unsafe);
 
-        let (builtin_name, helper_attrs) = ast::attr::find_by_name(attrs, sym::rustc_builtin_macro)
-            .map(|attr| {
-                // Override `helper_attrs` passed above if it's a built-in macro,
-                // marking `proc_macro_derive` macros as built-in is not a realistic use case.
-                parse_macro_name_and_helper_attrs(sess.dcx(), attr, "built-in").map_or_else(
-                    || (Some(name), Vec::new()),
-                    |(name, helper_attrs)| (Some(name), helper_attrs),
-                )
-            })
-            .unwrap_or_else(|| (None, helper_attrs));
+        let (builtin_name, helper_attrs) = match find_attr!(attrs, AttributeKind::RustcBuiltinMacro { builtin_name, helper_attrs, .. } => (builtin_name, helper_attrs))
+        {
+            // Override `helper_attrs` passed above if it's a built-in macro,
+            // marking `proc_macro_derive` macros as built-in is not a realistic use case.
+            Some((Some(name), helper_attrs)) => {
+                (Some(*name), helper_attrs.iter().copied().collect())
+            }
+            Some((None, _)) => (Some(name), Vec::new()),
+
+            // Not a built-in macro
+            None => (None, helper_attrs),
+        };
 
         let stability = find_attr!(attrs, AttributeKind::Stability { stability, .. } => *stability);
 
@@ -1141,7 +1143,7 @@ pub trait ResolverExpand {
 
     /// Names of specific methods to which glob delegation expands.
     fn glob_delegation_suffixes(
-        &mut self,
+        &self,
         trait_def_id: DefId,
         impl_def_id: LocalDefId,
     ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate>;
@@ -1224,6 +1226,7 @@ pub struct ExtCtxt<'a> {
     pub(super) expanded_inert_attrs: MarkedAttrs,
     /// `-Zmacro-stats` data.
     pub macro_stats: FxHashMap<(Symbol, MacroKind), MacroStat>,
+    pub nb_macro_errors: usize,
 }
 
 impl<'a> ExtCtxt<'a> {
@@ -1254,6 +1257,7 @@ impl<'a> ExtCtxt<'a> {
             expanded_inert_attrs: MarkedAttrs::new(),
             buffered_early_lint: vec![],
             macro_stats: Default::default(),
+            nb_macro_errors: 0,
         }
     }
 
@@ -1315,6 +1319,12 @@ impl<'a> ExtCtxt<'a> {
         self.current_expansion.id.expansion_cause()
     }
 
+    /// This method increases the internal macro errors count and then call `trace_macros_diag`.
+    pub fn macro_error_and_trace_macros_diag(&mut self) {
+        self.nb_macro_errors += 1;
+        self.trace_macros_diag();
+    }
+
     pub fn trace_macros_diag(&mut self) {
         for (span, notes) in self.expansions.iter() {
             let mut db = self.dcx().create_note(errors::TraceMacro { span: *span });
@@ -1382,80 +1392,6 @@ pub fn resolve_path(sess: &Session, path: impl Into<PathBuf>, span: Span) -> PRe
     }
 }
 
-pub fn parse_macro_name_and_helper_attrs(
-    dcx: DiagCtxtHandle<'_>,
-    attr: &impl AttributeExt,
-    macro_type: &str,
-) -> Option<(Symbol, Vec<Symbol>)> {
-    // Once we've located the `#[proc_macro_derive]` attribute, verify
-    // that it's of the form `#[proc_macro_derive(Foo)]` or
-    // `#[proc_macro_derive(Foo, attributes(A, ..))]`
-    let list = attr.meta_item_list()?;
-    let ([trait_attr] | [trait_attr, _]) = list.as_slice() else {
-        dcx.emit_err(errors::AttrNoArguments { span: attr.span() });
-        return None;
-    };
-    let Some(trait_attr) = trait_attr.meta_item() else {
-        dcx.emit_err(errors::NotAMetaItem { span: trait_attr.span() });
-        return None;
-    };
-    let trait_ident = match trait_attr.ident() {
-        Some(trait_ident) if trait_attr.is_word() => trait_ident,
-        _ => {
-            dcx.emit_err(errors::OnlyOneWord { span: trait_attr.span });
-            return None;
-        }
-    };
-
-    if !trait_ident.name.can_be_raw() {
-        dcx.emit_err(errors::CannotBeNameOfMacro {
-            span: trait_attr.span,
-            trait_ident,
-            macro_type,
-        });
-    }
-
-    let attributes_attr = list.get(1);
-    let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
-        if !attr.has_name(sym::attributes) {
-            dcx.emit_err(errors::ArgumentNotAttributes { span: attr.span() });
-        }
-        attr.meta_item_list()
-            .unwrap_or_else(|| {
-                dcx.emit_err(errors::AttributesWrongForm { span: attr.span() });
-                &[]
-            })
-            .iter()
-            .filter_map(|attr| {
-                let Some(attr) = attr.meta_item() else {
-                    dcx.emit_err(errors::AttributeMetaItem { span: attr.span() });
-                    return None;
-                };
-
-                let ident = match attr.ident() {
-                    Some(ident) if attr.is_word() => ident,
-                    _ => {
-                        dcx.emit_err(errors::AttributeSingleWord { span: attr.span });
-                        return None;
-                    }
-                };
-                if !ident.name.can_be_raw() {
-                    dcx.emit_err(errors::HelperAttributeNameInvalid {
-                        span: attr.span,
-                        name: ident,
-                    });
-                }
-
-                Some(ident.name)
-            })
-            .collect()
-    } else {
-        Vec::new()
-    };
-
-    Some((trait_ident.name, proc_attrs))
-}
-
 /// If this item looks like a specific enums from `rental`, emit a fatal error.
 /// See #73345 and #83125 for more details.
 /// FIXME(#73933): Remove this eventually.
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 3ac5d213053..fd1391a554a 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -79,72 +79,6 @@ pub(crate) struct MacroBodyStability {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_attr_no_arguments)]
-pub(crate) struct AttrNoArguments {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_not_a_meta_item)]
-pub(crate) struct NotAMetaItem {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_only_one_word)]
-pub(crate) struct OnlyOneWord {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_cannot_be_name_of_macro)]
-pub(crate) struct CannotBeNameOfMacro<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub trait_ident: Ident,
-    pub macro_type: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_arg_not_attributes)]
-pub(crate) struct ArgumentNotAttributes {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_attributes_wrong_form)]
-pub(crate) struct AttributesWrongForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_attribute_meta_item)]
-pub(crate) struct AttributeMetaItem {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_attribute_single_word)]
-pub(crate) struct AttributeSingleWord {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(expand_helper_attribute_name_invalid)]
-pub(crate) struct HelperAttributeNameInvalid {
-    #[primary_span]
-    pub span: Span,
-    pub name: Ident,
-}
-
-#[derive(Diagnostic)]
 #[diag(expand_feature_removed, code = E0557)]
 #[note]
 pub(crate) struct FeatureRemoved<'a> {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 79ec79a2fdf..0517fd0419d 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -693,7 +693,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
             crate_name: self.cx.ecfg.crate_name,
         });
 
-        self.cx.trace_macros_diag();
+        self.cx.macro_error_and_trace_macros_diag();
         guar
     }
 
@@ -707,7 +707,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     ) -> ErrorGuaranteed {
         let guar =
             self.cx.dcx().emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
-        self.cx.trace_macros_diag();
+        self.cx.macro_error_and_trace_macros_diag();
         guar
     }
 
@@ -1048,7 +1048,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 }
                 annotate_err_with_kind(&mut err, kind, span);
                 let guar = err.emit();
-                self.cx.trace_macros_diag();
+                self.cx.macro_error_and_trace_macros_diag();
                 kind.dummy(span, guar)
             }
         }
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 3f1fc841ea3..0324057e331 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -299,6 +299,7 @@ enum EofMatcherPositions {
 }
 
 /// Represents the possible results of an attempted parse.
+#[derive(Debug)]
 pub(crate) enum ParseResult<T, F> {
     /// Parsed successfully.
     Success(T),
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 2f713a09b95..febe6f8b88c 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -280,7 +280,7 @@ fn expand_macro<'cx>(
             // Retry and emit a better error.
             let (span, guar) =
                 diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, rules);
-            cx.trace_macros_diag();
+            cx.macro_error_and_trace_macros_diag();
             DummyResult::any(span, guar)
         }
     }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index e83f6a1df72..96501844264 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1363,6 +1363,17 @@ impl AttributeExt for Attribute {
             _ => None,
         }
     }
+
+    fn is_proc_macro_attr(&self) -> bool {
+        matches!(
+            self,
+            Attribute::Parsed(
+                AttributeKind::ProcMacro(..)
+                    | AttributeKind::ProcMacroAttribute(..)
+                    | AttributeKind::ProcMacroDerive { .. }
+            )
+        )
+    }
 }
 
 // FIXME(fn_delegation): use function delegation instead of manually forwarding
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index bb1de5bcfc3..acc831d30ca 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -767,7 +767,8 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(),
                 DefKind::Static { .. } => {
                     check_static_inhabited(tcx, def_id);
                     check_static_linkage(tcx, def_id);
-                    res = res.and(wfcheck::check_static_item(tcx, def_id));
+                    let ty = tcx.type_of(def_id).instantiate_identity();
+                    res = res.and(wfcheck::check_static_item(tcx, def_id, ty, true));
                 }
                 DefKind::Const => res = res.and(wfcheck::check_const_item(tcx, def_id)),
                 _ => unreachable!(),
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 14ec82ede1c..a62efed13bc 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1180,12 +1180,13 @@ fn check_item_fn(
 }
 
 #[instrument(level = "debug", skip(tcx))]
-pub(super) fn check_static_item(
-    tcx: TyCtxt<'_>,
+pub(crate) fn check_static_item<'tcx>(
+    tcx: TyCtxt<'tcx>,
     item_id: LocalDefId,
+    ty: Ty<'tcx>,
+    should_check_for_sync: bool,
 ) -> Result<(), ErrorGuaranteed> {
     enter_wf_checking_ctxt(tcx, item_id, |wfcx| {
-        let ty = tcx.type_of(item_id).instantiate_identity();
         let span = tcx.ty_span(item_id);
         let item_ty = wfcx.deeply_normalize(span, Some(WellFormedLoc::Ty(item_id)), ty);
 
@@ -1212,9 +1213,9 @@ pub(super) fn check_static_item(
         }
 
         // Ensure that the end result is `Sync` in a non-thread local `static`.
-        let should_check_for_sync = tcx.static_mutability(item_id.to_def_id())
-            == Some(hir::Mutability::Not)
+        let should_check_for_sync = should_check_for_sync
             && !is_foreign_item
+            && tcx.static_mutability(item_id.to_def_id()) == Some(hir::Mutability::Not)
             && !tcx.is_thread_local_static(item_id.to_def_id());
 
         if should_check_for_sync {
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 902a2e15dff..68a91212e50 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -14,6 +14,7 @@ use rustc_middle::{bug, span_bug};
 use rustc_span::{DUMMY_SP, Ident, Span};
 
 use super::{HirPlaceholderCollector, ItemCtxt, bad_placeholder};
+use crate::check::wfcheck::check_static_item;
 use crate::errors::TypeofReservedKeywordUsed;
 use crate::hir_ty_lowering::HirTyLowerer;
 
@@ -217,7 +218,13 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                         "static variable",
                     )
                 } else {
-                    icx.lower_ty(ty)
+                    let ty = icx.lower_ty(ty);
+                    // MIR relies on references to statics being scalars.
+                    // Verify that here to avoid ill-formed MIR.
+                    match check_static_item(tcx, def_id, ty, false) {
+                        Ok(()) => ty,
+                        Err(guar) => Ty::new_error(tcx, guar),
+                    }
                 }
             }
             ItemKind::Const(ident, _, ty, body_id) => {
@@ -275,7 +282,15 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
                 let args = ty::GenericArgs::identity_for_item(tcx, def_id);
                 Ty::new_fn_def(tcx, def_id.to_def_id(), args)
             }
-            ForeignItemKind::Static(t, _, _) => icx.lower_ty(t),
+            ForeignItemKind::Static(ty, _, _) => {
+                let ty = icx.lower_ty(ty);
+                // MIR relies on references to statics being scalars.
+                // Verify that here to avoid ill-formed MIR.
+                match check_static_item(tcx, def_id, ty, false) {
+                    Ok(()) => ty,
+                    Err(guar) => Ty::new_error(tcx, guar),
+                }
+            }
             ForeignItemKind::Type => Ty::new_foreign(tcx, def_id.to_def_id()),
         },
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index fb6897c7d89..057fbe2fc4e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -208,6 +208,10 @@ fn configure_and_expand(
         // Expand macros now!
         let krate = sess.time("expand_crate", || ecx.monotonic_expander().expand_crate(krate));
 
+        if ecx.nb_macro_errors > 0 {
+            sess.dcx().abort_if_errors();
+        }
+
         // The rest is error reporting and stats
 
         sess.psess.buffered_lints.with_lock(|buffered_lints: &mut Vec<BufferedEarlyLint>| {
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 24a3a6e0c4f..ffb33c67f8a 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -5,7 +5,7 @@ use std::io::{Read, Seek, Write};
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-use rustc_attr_data_structures::EncodeCrossCrate;
+use rustc_attr_data_structures::{AttributeKind, EncodeCrossCrate, find_attr};
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::sync::{join, par_for_each_in};
@@ -1965,18 +1965,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                 // Proc-macros may have attributes like `#[allow_internal_unstable]`,
                 // so downstream crates need access to them.
                 let attrs = tcx.hir_attrs(proc_macro);
-                let macro_kind = if ast::attr::contains_name(attrs, sym::proc_macro) {
+                let macro_kind = if find_attr!(attrs, AttributeKind::ProcMacro(..)) {
                     MacroKind::Bang
-                } else if ast::attr::contains_name(attrs, sym::proc_macro_attribute) {
+                } else if find_attr!(attrs, AttributeKind::ProcMacroAttribute(..)) {
                     MacroKind::Attr
-                } else if let Some(attr) = ast::attr::find_by_name(attrs, sym::proc_macro_derive) {
-                    // This unwrap chain should have been checked by the proc-macro harness.
-                    name = attr.meta_item_list().unwrap()[0]
-                        .meta_item()
-                        .unwrap()
-                        .ident()
-                        .unwrap()
-                        .name;
+                } else if let Some(trait_name) = find_attr!(attrs, AttributeKind::ProcMacroDerive { trait_name, ..} => trait_name)
+                {
+                    name = *trait_name;
                     MacroKind::Derive
                 } else {
                     bug!("Unknown proc-macro type for item {:?}", id);
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 66d1335e763..6f21160d1f6 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1041,11 +1041,13 @@ const NUM_PREINTERNED_TY_VARS: u32 = 100;
 const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
 const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
 const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
+const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3;
+const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20;
 
 // This number may seem high, but it is reached in all but the smallest crates.
 const NUM_PREINTERNED_RE_VARS: u32 = 500;
-const NUM_PREINTERNED_RE_LATE_BOUNDS_I: u32 = 2;
-const NUM_PREINTERNED_RE_LATE_BOUNDS_V: u32 = 20;
+const NUM_PREINTERNED_ANON_RE_BOUNDS_I: u32 = 3;
+const NUM_PREINTERNED_ANON_RE_BOUNDS_V: u32 = 20;
 
 pub struct CommonTypes<'tcx> {
     pub unit: Ty<'tcx>,
@@ -1088,6 +1090,11 @@ pub struct CommonTypes<'tcx> {
 
     /// Pre-interned `Infer(ty::FreshFloatTy(n))` for small values of `n`.
     pub fresh_float_tys: Vec<Ty<'tcx>>,
+
+    /// Pre-interned values of the form:
+    /// `Bound(DebruijnIndex(i), BoundTy { var: v, kind: BoundTyKind::Anon})`
+    /// for small values of `i` and `v`.
+    pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>,
 }
 
 pub struct CommonLifetimes<'tcx> {
@@ -1101,9 +1108,9 @@ pub struct CommonLifetimes<'tcx> {
     pub re_vars: Vec<Region<'tcx>>,
 
     /// Pre-interned values of the form:
-    /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BrAnon })`
+    /// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BoundRegionKind::Anon })`
     /// for small values of `i` and `v`.
-    pub re_late_bounds: Vec<Vec<Region<'tcx>>>,
+    pub anon_re_bounds: Vec<Vec<Region<'tcx>>>,
 }
 
 pub struct CommonConsts<'tcx> {
@@ -1131,6 +1138,19 @@ impl<'tcx> CommonTypes<'tcx> {
         let fresh_float_tys: Vec<_> =
             (0..NUM_PREINTERNED_FRESH_FLOAT_TYS).map(|n| mk(Infer(ty::FreshFloatTy(n)))).collect();
 
+        let anon_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_I)
+            .map(|i| {
+                (0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
+                    .map(|v| {
+                        mk(ty::Bound(
+                            ty::DebruijnIndex::from(i),
+                            ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon },
+                        ))
+                    })
+                    .collect()
+            })
+            .collect();
+
         CommonTypes {
             unit: mk(Tuple(List::empty())),
             bool: mk(Bool),
@@ -1161,6 +1181,7 @@ impl<'tcx> CommonTypes<'tcx> {
             fresh_tys,
             fresh_int_tys,
             fresh_float_tys,
+            anon_bound_tys,
         }
     }
 }
@@ -1176,9 +1197,9 @@ impl<'tcx> CommonLifetimes<'tcx> {
         let re_vars =
             (0..NUM_PREINTERNED_RE_VARS).map(|n| mk(ty::ReVar(ty::RegionVid::from(n)))).collect();
 
-        let re_late_bounds = (0..NUM_PREINTERNED_RE_LATE_BOUNDS_I)
+        let anon_re_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_I)
             .map(|i| {
-                (0..NUM_PREINTERNED_RE_LATE_BOUNDS_V)
+                (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
                     .map(|v| {
                         mk(ty::ReBound(
                             ty::DebruijnIndex::from(i),
@@ -1196,7 +1217,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
             re_static: mk(ty::ReStatic),
             re_erased: mk(ty::ReErased),
             re_vars,
-            re_late_bounds,
+            anon_re_bounds,
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a7cde2ad485..4c95f0748d3 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -2024,7 +2024,10 @@ impl<'tcx> TyCtxt<'tcx> {
             && let Some(def_id) = def_id.as_local()
             && let outer = self.def_span(def_id).ctxt().outer_expn_data()
             && matches!(outer.kind, ExpnKind::Macro(MacroKind::Derive, _))
-            && self.has_attr(outer.macro_def_id.unwrap(), sym::rustc_builtin_macro)
+            && find_attr!(
+                self.get_all_attrs(outer.macro_def_id.unwrap()),
+                AttributeKind::RustcBuiltinMacro { .. }
+            )
         {
             true
         } else {
diff --git a/compiler/rustc_middle/src/ty/region.rs b/compiler/rustc_middle/src/ty/region.rs
index 51be93d9a72..5cf96072177 100644
--- a/compiler/rustc_middle/src/ty/region.rs
+++ b/compiler/rustc_middle/src/ty/region.rs
@@ -54,7 +54,7 @@ impl<'tcx> Region<'tcx> {
     ) -> Region<'tcx> {
         // Use a pre-interned one when possible.
         if let ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon } = bound_region
-            && let Some(inner) = tcx.lifetimes.re_late_bounds.get(debruijn.as_usize())
+            && let Some(inner) = tcx.lifetimes.anon_re_bounds.get(debruijn.as_usize())
             && let Some(re) = inner.get(var.as_usize()).copied()
         {
             re
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8bb3b3f1263..4569596cfbe 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -485,7 +485,15 @@ impl<'tcx> Ty<'tcx> {
         index: ty::DebruijnIndex,
         bound_ty: ty::BoundTy,
     ) -> Ty<'tcx> {
-        Ty::new(tcx, Bound(index, bound_ty))
+        // Use a pre-interned one when possible.
+        if let ty::BoundTy { var, kind: ty::BoundTyKind::Anon } = bound_ty
+            && let Some(inner) = tcx.types.anon_bound_tys.get(index.as_usize())
+            && let Some(ty) = inner.get(var.as_usize()).copied()
+        {
+            ty
+        } else {
+            Ty::new(tcx, Bound(index, bound_ty))
+        }
     }
 
     #[inline]
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index ddeae093df5..ec76076020e 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -1,8 +1,7 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir;
 use rustc_middle::ty::TyCtxt;
-use rustc_span::source_map::SourceMap;
-use rustc_span::{BytePos, DesugaringKind, ExpnKind, MacroKind, Span};
+use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
 use tracing::instrument;
 
 use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
@@ -84,18 +83,8 @@ pub(super) fn extract_refined_covspans<'tcx>(
     // Discard any span that overlaps with a hole.
     discard_spans_overlapping_holes(&mut covspans, &holes);
 
-    // Discard spans that overlap in unwanted ways.
+    // Perform more refinement steps after holes have been dealt with.
     let mut covspans = remove_unwanted_overlapping_spans(covspans);
-
-    // For all empty spans, either enlarge them to be non-empty, or discard them.
-    let source_map = tcx.sess.source_map();
-    covspans.retain_mut(|covspan| {
-        let Some(span) = ensure_non_empty_span(source_map, covspan.span) else { return false };
-        covspan.span = span;
-        true
-    });
-
-    // Merge covspans that can be merged.
     covspans.dedup_by(|b, a| a.merge_if_eligible(b));
 
     code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
@@ -241,26 +230,3 @@ fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
         // - Both have the same start and span A extends further right
         .then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
 }
-
-fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
-    if !span.is_empty() {
-        return Some(span);
-    }
-
-    // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
-    source_map
-        .span_to_source(span, |src, start, end| try {
-            // Adjusting span endpoints by `BytePos(1)` is normally a bug,
-            // but in this case we have specifically checked that the character
-            // we're skipping over is one of two specific ASCII characters, so
-            // adjusting by exactly 1 byte is correct.
-            if src.as_bytes().get(end).copied() == Some(b'{') {
-                Some(span.with_hi(span.hi() + BytePos(1)))
-            } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
-                Some(span.with_lo(span.lo() - BytePos(1)))
-            } else {
-                None
-            }
-        })
-        .ok()?
-}
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 4b524bb2bd2..0b329cc38b0 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -130,6 +130,22 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         for attr in attrs {
             let mut style = None;
             match attr {
+                Attribute::Parsed(AttributeKind::ProcMacro(_)) => {
+                    self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
+                }
+                Attribute::Parsed(AttributeKind::ProcMacroAttribute(_)) => {
+                    self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
+                }
+                Attribute::Parsed(AttributeKind::ProcMacroDerive { span: attr_span, .. }) => {
+                    self.check_generic_attr(
+                        hir_id,
+                        sym::proc_macro_derive,
+                        *attr_span,
+                        target,
+                        Target::Fn,
+                    );
+                    self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
+                }
                 Attribute::Parsed(
                     AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. }
                     | AttributeKind::Coinductive(attr_span)
@@ -275,6 +291,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::MacroTransparency(_)
                     | AttributeKind::Pointee(..)
                     | AttributeKind::Dummy
+                    | AttributeKind::RustcBuiltinMacro { .. }
                     | AttributeKind::OmitGdbPrettyPrinterSection,
                 ) => { /* do nothing  */ }
                 Attribute::Parsed(AttributeKind::AsPtr(attr_span)) => {
@@ -373,16 +390,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::should_panic, ..] => {
                             self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn)
                         }
-                        [sym::proc_macro, ..] => {
-                            self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
-                        }
-                        [sym::proc_macro_attribute, ..] => {
-                            self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
-                        }
-                        [sym::proc_macro_derive, ..] => {
-                            self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn);
-                            self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
-                        }
                         [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
                             self.check_autodiff(hir_id, attr, span, target)
                         }
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ac64385d664..b15b478a6be 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -23,9 +23,9 @@ use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
 use rustc_index::bit_set::DenseBitSet;
 use rustc_metadata::creader::LoadedMacro;
-use rustc_middle::bug;
 use rustc_middle::metadata::ModChild;
 use rustc_middle::ty::{Feed, Visibility};
+use rustc_middle::{bug, span_bug};
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
 use rustc_span::{Ident, Span, Symbol, kw, sym};
 use thin_vec::ThinVec;
@@ -46,30 +46,59 @@ type Res = def::Res<NodeId>;
 impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
     /// otherwise, reports an error.
-    pub(crate) fn define_binding(
+    pub(crate) fn define_binding_local(
         &mut self,
         parent: Module<'ra>,
         ident: Ident,
         ns: Namespace,
         binding: NameBinding<'ra>,
     ) {
-        if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
+        if let Err(old_binding) = self.try_define_local(parent, ident, ns, binding, false) {
             self.report_conflict(parent, ident, ns, old_binding, binding);
         }
     }
 
-    fn define(
+    fn define_local(
         &mut self,
         parent: Module<'ra>,
         ident: Ident,
         ns: Namespace,
         res: Res,
-        vis: Visibility<impl Into<DefId>>,
+        vis: Visibility,
         span: Span,
         expn_id: LocalExpnId,
     ) {
         let binding = self.arenas.new_res_binding(res, vis.to_def_id(), span, expn_id);
-        self.define_binding(parent, ident, ns, binding)
+        self.define_binding_local(parent, ident, ns, binding);
+    }
+
+    fn define_extern(
+        &self,
+        parent: Module<'ra>,
+        ident: Ident,
+        ns: Namespace,
+        res: Res,
+        vis: Visibility<DefId>,
+        span: Span,
+        expn_id: LocalExpnId,
+    ) {
+        let binding = self.arenas.new_res_binding(res, vis, span, expn_id);
+        // Even if underscore names cannot be looked up, we still need to add them to modules,
+        // because they can be fetched by glob imports from those modules, and bring traits
+        // into scope both directly and through glob imports.
+        let key = BindingKey::new_disambiguated(ident, ns, || {
+            parent.underscore_disambiguator.update(|d| d + 1);
+            parent.underscore_disambiguator.get()
+        });
+        if self
+            .resolution_or_default(parent, key)
+            .borrow_mut()
+            .non_glob_binding
+            .replace(binding)
+            .is_some()
+        {
+            span_bug!(span, "an external binding was already defined");
+        }
     }
 
     /// Walks up the tree of definitions starting at `def_id`,
@@ -192,7 +221,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         visitor.parent_scope.macro_rules
     }
 
-    pub(crate) fn build_reduced_graph_external(&mut self, module: Module<'ra>) {
+    pub(crate) fn build_reduced_graph_external(&self, module: Module<'ra>) {
         for child in self.tcx.module_children(module.def_id()) {
             let parent_scope = ParentScope::module(module, self);
             self.build_reduced_graph_for_external_crate_res(child, parent_scope)
@@ -201,7 +230,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     /// Builds the reduced graph for a single item in an external crate.
     fn build_reduced_graph_for_external_crate_res(
-        &mut self,
+        &self,
         child: &ModChild,
         parent_scope: ParentScope<'ra>,
     ) {
@@ -232,7 +261,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 _,
             )
             | Res::PrimTy(..)
-            | Res::ToolMod => self.define(parent, ident, TypeNS, res, vis, span, expansion),
+            | Res::ToolMod => self.define_extern(parent, ident, TypeNS, res, vis, span, expansion),
             Res::Def(
                 DefKind::Fn
                 | DefKind::AssocFn
@@ -241,9 +270,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 | DefKind::AssocConst
                 | DefKind::Ctor(..),
                 _,
-            ) => self.define(parent, ident, ValueNS, res, vis, span, expansion),
+            ) => self.define_extern(parent, ident, ValueNS, res, vis, span, expansion),
             Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
-                self.define(parent, ident, MacroNS, res, vis, span, expansion)
+                self.define_extern(parent, ident, MacroNS, res, vis, span, expansion)
             }
             Res::Def(
                 DefKind::TyParam
@@ -711,7 +740,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let expansion = parent_scope.expansion;
 
         // Define a name in the type namespace if it is not anonymous.
-        self.r.define(parent, ident, TypeNS, adt_res, adt_vis, adt_span, expansion);
+        self.r.define_local(parent, ident, TypeNS, adt_res, adt_vis, adt_span, expansion);
         self.r.feed_visibility(feed, adt_vis);
         let def_id = feed.key();
 
@@ -763,7 +792,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             ItemKind::Mod(_, ident, ref mod_kind) => {
-                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
+                self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
 
                 if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
                     self.r.mods_with_parse_errors.insert(def_id);
@@ -782,10 +811,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             ItemKind::Const(box ConstItem { ident, .. })
             | ItemKind::Delegation(box Delegation { ident, .. })
             | ItemKind::Static(box StaticItem { ident, .. }) => {
-                self.r.define(parent, ident, ValueNS, res, vis, sp, expansion);
+                self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion);
             }
             ItemKind::Fn(box Fn { ident, .. }) => {
-                self.r.define(parent, ident, ValueNS, res, vis, sp, expansion);
+                self.r.define_local(parent, ident, ValueNS, res, vis, sp, expansion);
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
@@ -794,11 +823,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
 
             // These items live in the type namespace.
             ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
-                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
+                self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
             }
 
             ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
-                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
+                self.r.define_local(parent, ident, TypeNS, res, vis, sp, expansion);
 
                 self.parent_scope.module = self.r.new_local_module(
                     Some(parent),
@@ -850,7 +879,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                     let feed = self.r.feed(ctor_node_id);
                     let ctor_def_id = feed.key();
                     let ctor_res = self.res(ctor_def_id);
-                    self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, sp, expansion);
+                    self.r.define_local(parent, ident, ValueNS, ctor_res, ctor_vis, sp, expansion);
                     self.r.feed_visibility(feed, ctor_vis);
                     // We need the field visibility spans also for the constructor for E0603.
                     self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields());
@@ -974,7 +1003,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
         }
-        self.r.define_binding(parent, ident, TypeNS, imported_binding);
+        self.r.define_binding_local(parent, ident, TypeNS, imported_binding);
     }
 
     /// Constructs the reduced graph for one foreign item.
@@ -991,7 +1020,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
-        self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
+        self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
         self.r.feed_visibility(feed, vis);
     }
 
@@ -1074,7 +1103,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         if let Some(span) = import_all {
             let import = macro_use_import(self, span, false);
             self.r.potentially_unused_imports.push(import);
-            module.for_each_child(self, |this, ident, ns, binding| {
+            module.for_each_child_mut(self, |this, ident, ns, binding| {
                 if ns == MacroNS {
                     let import = if this.r.is_accessible_from(binding.vis, this.parent_scope.module)
                     {
@@ -1239,7 +1268,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 });
                 self.r.import_use_map.insert(import, Used::Other);
                 let import_binding = self.r.import(binding, import);
-                self.r.define_binding(self.r.graph_root, ident, MacroNS, import_binding);
+                self.r.define_binding_local(self.r.graph_root, ident, MacroNS, import_binding);
             } else {
                 self.r.check_reserved_macro_name(ident, res);
                 self.insert_unused_macro(ident, def_id, item.id);
@@ -1267,7 +1296,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             if !vis.is_public() {
                 self.insert_unused_macro(ident, def_id, item.id);
             }
-            self.r.define(module, ident, MacroNS, res, vis, span, expansion);
+            self.r.define_local(module, ident, MacroNS, res, vis, span, expansion);
             self.r.feed_visibility(feed, vis);
             self.parent_scope.macro_rules
         }
@@ -1403,7 +1432,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         if ctxt == AssocCtxt::Trait {
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
-            self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
+            self.r.define_local(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
         } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
             && ident.name != kw::Underscore
         {
@@ -1491,7 +1520,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let feed = self.r.feed(variant.id);
         let def_id = feed.key();
         let vis = self.resolve_visibility(&variant.vis);
-        self.r.define(parent, ident, TypeNS, self.res(def_id), vis, variant.span, expn_id);
+        self.r.define_local(parent, ident, TypeNS, self.res(def_id), vis, variant.span, expn_id);
         self.r.feed_visibility(feed, vis);
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the crate.
@@ -1507,7 +1536,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             let feed = self.r.feed(ctor_node_id);
             let ctor_def_id = feed.key();
             let ctor_res = self.res(ctor_def_id);
-            self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, variant.span, expn_id);
+            self.r.define_local(parent, ident, ValueNS, ctor_res, ctor_vis, variant.span, expn_id);
             self.r.feed_visibility(feed, ctor_vis);
         }
 
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 13cf700fbb2..3af69b28780 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -523,7 +523,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     }
 
     pub(crate) fn add_module_candidates(
-        &mut self,
+        &self,
         module: Module<'ra>,
         names: &mut Vec<TypoSuggestion>,
         filter_fn: &impl Fn(Res) -> bool,
@@ -1150,7 +1150,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     }
 
     fn lookup_import_candidates_from_module<FilterFn>(
-        &mut self,
+        &self,
         lookup_ident: Ident,
         namespace: Namespace,
         parent_scope: &ParentScope<'ra>,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f2de57b4d50..156df45147f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -334,8 +334,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     }
 
     /// Define the name or return the existing binding if there is a collision.
-    /// `update` indicates if the definition is a redefinition of an existing binding.
-    pub(crate) fn try_define(
+    pub(crate) fn try_define_local(
         &mut self,
         module: Module<'ra>,
         ident: Ident,
@@ -353,7 +352,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             module.underscore_disambiguator.update(|d| d + 1);
             module.underscore_disambiguator.get()
         });
-        self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
+        self.update_local_resolution(module, key, warn_ambiguity, |this, resolution| {
             if let Some(old_binding) = resolution.best_binding() {
                 if res == Res::Err && old_binding.res() != Res::Err {
                     // Do not override real bindings with `Res::Err`s from error recovery.
@@ -456,7 +455,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     // Use `f` to mutate the resolution of the name in the module.
     // If the resolution becomes a success, define it in the module's glob importers.
-    fn update_resolution<T, F>(
+    fn update_local_resolution<T, F>(
         &mut self,
         module: Module<'ra>,
         key: BindingKey,
@@ -497,7 +496,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             };
             if self.is_accessible_from(binding.vis, scope) {
                 let imported_binding = self.import(binding, *import);
-                let _ = self.try_define(
+                let _ = self.try_define_local(
                     import.parent_scope.module,
                     ident,
                     key.ns,
@@ -523,11 +522,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
                 let module = import.parent_scope.module;
-                let _ = this.try_define(module, target, ns, dummy_binding, false);
+                let _ = this.try_define_local(module, target, ns, dummy_binding, false);
                 // Don't remove underscores from `single_imports`, they were never added.
                 if target.name != kw::Underscore {
                     let key = BindingKey::new(target, ns);
-                    this.update_resolution(module, key, false, |_, resolution| {
+                    this.update_local_resolution(module, key, false, |_, resolution| {
                         resolution.single_imports.swap_remove(&import);
                     })
                 }
@@ -902,14 +901,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         }
                         // We need the `target`, `source` can be extracted.
                         let imported_binding = this.import(binding, import);
-                        this.define_binding(parent, target, ns, imported_binding);
+                        this.define_binding_local(parent, target, ns, imported_binding);
                         PendingBinding::Ready(Some(imported_binding))
                     }
                     Err(Determinacy::Determined) => {
                         // Don't remove underscores from `single_imports`, they were never added.
                         if target.name != kw::Underscore {
                             let key = BindingKey::new(target, ns);
-                            this.update_resolution(parent, key, false, |_, resolution| {
+                            this.update_local_resolution(parent, key, false, |_, resolution| {
                                 resolution.single_imports.swap_remove(&import);
                             });
                         }
@@ -1516,7 +1515,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     .resolution(import.parent_scope.module, key)
                     .and_then(|r| r.binding())
                     .is_some_and(|binding| binding.warn_ambiguity_recursive());
-                let _ = self.try_define(
+                let _ = self.try_define_local(
                     import.parent_scope.module,
                     key.ident,
                     key.ns,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 203827a9e1a..0f0babd4904 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -2633,7 +2633,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         false
     }
 
-    fn find_module(&mut self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> {
+    fn find_module(&self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> {
         let mut result = None;
         let mut seen_modules = FxHashSet::default();
         let root_did = self.r.graph_root.def_id();
@@ -2690,7 +2690,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         result
     }
 
-    fn collect_enum_ctors(&mut self, def_id: DefId) -> Option<Vec<(Path, DefId, CtorKind)>> {
+    fn collect_enum_ctors(&self, def_id: DefId) -> Option<Vec<(Path, DefId, CtorKind)>> {
         self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
             let mut variants = Vec::new();
             enum_module.for_each_child(self.r, |_, ident, _, name_binding| {
@@ -2707,7 +2707,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
 
     /// Adds a suggestion for using an enum's variant when an enum is used instead.
     fn suggest_using_enum_variant(
-        &mut self,
+        &self,
         err: &mut Diag<'_>,
         source: PathSource<'_, '_, '_>,
         def_id: DefId,
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index fe7ed07c46e..8115b87dcae 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -656,11 +656,23 @@ impl<'ra> ModuleData<'ra> {
 }
 
 impl<'ra> Module<'ra> {
-    fn for_each_child<'tcx, R, F>(self, resolver: &mut R, mut f: F)
-    where
-        R: AsMut<Resolver<'ra, 'tcx>>,
-        F: FnMut(&mut R, Ident, Namespace, NameBinding<'ra>),
-    {
+    fn for_each_child<'tcx, R: AsRef<Resolver<'ra, 'tcx>>>(
+        self,
+        resolver: &R,
+        mut f: impl FnMut(&R, Ident, Namespace, NameBinding<'ra>),
+    ) {
+        for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
+            if let Some(binding) = name_resolution.borrow().best_binding() {
+                f(resolver, key.ident, key.ns, binding);
+            }
+        }
+    }
+
+    fn for_each_child_mut<'tcx, R: AsMut<Resolver<'ra, 'tcx>>>(
+        self,
+        resolver: &mut R,
+        mut f: impl FnMut(&mut R, Ident, Namespace, NameBinding<'ra>),
+    ) {
         for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
             if let Some(binding) = name_resolution.borrow().best_binding() {
                 f(resolver, key.ident, key.ns, binding);
@@ -669,10 +681,7 @@ impl<'ra> Module<'ra> {
     }
 
     /// This modifies `self` in place. The traits will be stored in `self.traits`.
-    fn ensure_traits<'tcx, R>(self, resolver: &mut R)
-    where
-        R: AsMut<Resolver<'ra, 'tcx>>,
-    {
+    fn ensure_traits<'tcx>(self, resolver: &impl AsRef<Resolver<'ra, 'tcx>>) {
         let mut traits = self.traits.borrow_mut();
         if traits.is_none() {
             let mut collected_traits = Vec::new();
@@ -681,7 +690,7 @@ impl<'ra> Module<'ra> {
                     return;
                 }
                 if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() {
-                    collected_traits.push((name, binding, r.as_mut().get_module(def_id)))
+                    collected_traits.push((name, binding, r.as_ref().get_module(def_id)))
                 }
             });
             *traits = Some(collected_traits.into_boxed_slice());
@@ -1340,6 +1349,12 @@ impl<'ra, 'tcx> AsMut<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> {
     }
 }
 
+impl<'ra, 'tcx> AsRef<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> {
+    fn as_ref(&self) -> &Resolver<'ra, 'tcx> {
+        self
+    }
+}
+
 impl<'tcx> Resolver<'_, 'tcx> {
     fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
         self.opt_feed(node).map(|f| f.key())
@@ -1861,7 +1876,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
     // associated items.
     fn trait_may_have_item(
-        &mut self,
+        &self,
         trait_module: Option<Module<'ra>>,
         assoc_item: Option<(Symbol, Namespace)>,
     ) -> bool {
@@ -1893,7 +1908,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         import_ids
     }
 
-    fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
+    fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
         if module.populate_on_access.get() {
             module.populate_on_access.set(false);
             self.build_reduced_graph_external(module);
@@ -1902,7 +1917,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     }
 
     fn resolution(
-        &mut self,
+        &self,
         module: Module<'ra>,
         key: BindingKey,
     ) -> Option<Ref<'ra, NameResolution<'ra>>> {
@@ -1910,7 +1925,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     }
 
     fn resolution_or_default(
-        &mut self,
+        &self,
         module: Module<'ra>,
         key: BindingKey,
     ) -> &'ra RefCell<NameResolution<'ra>> {
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index f0225daa09d..b96d9e7dc8e 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -511,7 +511,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
     }
 
     fn glob_delegation_suffixes(
-        &mut self,
+        &self,
         trait_def_id: DefId,
         impl_def_id: LocalDefId,
     ) -> Result<Vec<(Ident, Option<Ident>)>, Indeterminate> {
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index c3080875da8..97d1d9c2d2a 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -322,6 +322,7 @@ impl ExpnId {
 
     /// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
     /// `expn_id.is_descendant_of(ctxt.outer_expn())`.
+    #[inline]
     pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
         HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt)))
     }
@@ -394,6 +395,7 @@ impl HygieneData {
         }
     }
 
+    #[inline]
     fn with<R>(f: impl FnOnce(&mut HygieneData) -> R) -> R {
         with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
     }
@@ -406,6 +408,7 @@ impl HygieneData {
         }
     }
 
+    #[inline]
     fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
         self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
     }
@@ -437,23 +440,28 @@ impl HygieneData {
         }
     }
 
+    #[inline]
     fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque
     }
 
+    #[inline]
     fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
     }
 
+    #[inline]
     fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
         self.syntax_context_data[ctxt.0 as usize].outer_expn
     }
 
+    #[inline]
     fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
         let data = &self.syntax_context_data[ctxt.0 as usize];
         (data.outer_expn, data.outer_transparency)
     }
 
+    #[inline]
     fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
         self.syntax_context_data[ctxt.0 as usize].parent
     }
@@ -718,11 +726,13 @@ impl SyntaxContext {
         SyntaxContext(raw as u32)
     }
 
+    #[inline]
     fn from_usize(raw: usize) -> SyntaxContext {
         SyntaxContext(u32::try_from(raw).unwrap())
     }
 
     /// Extend a syntax context with a given expansion and transparency.
+    #[inline]
     pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
         HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
     }
@@ -743,10 +753,12 @@ impl SyntaxContext {
     /// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
     /// invocation of f that created g1.
     /// Returns the mark that was removed.
+    #[inline]
     pub fn remove_mark(&mut self) -> ExpnId {
         HygieneData::with(|data| data.remove_mark(self).0)
     }
 
+    #[inline]
     pub fn marks(self) -> Vec<(ExpnId, Transparency)> {
         HygieneData::with(|data| data.marks(self))
     }
@@ -776,11 +788,13 @@ impl SyntaxContext {
     /// ```
     /// This returns the expansion whose definition scope we use to privacy check the resolution,
     /// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
+    #[inline]
     pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         HygieneData::with(|data| data.adjust(self, expn_id))
     }
 
     /// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
+    #[inline]
     pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
         HygieneData::with(|data| {
             *self = data.normalize_to_macros_2_0(*self);
@@ -901,10 +915,12 @@ impl SyntaxContext {
         HygieneData::with(|data| data.outer_mark(self))
     }
 
+    #[inline]
     pub(crate) fn dollar_crate_name(self) -> Symbol {
         HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
     }
 
+    #[inline]
     pub fn edition(self) -> Edition {
         HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
     }
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index 9b0e009b2cd..dbc67da37b5 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -167,6 +167,7 @@ where
     }
 }
 
+#[inline]
 pub fn with_session_globals<R, F>(f: F) -> R
 where
     F: FnOnce(&SessionGlobals) -> R,
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 58daaa03675..478726fbef6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
     base.max_atomic_width = Some(128);
     base.supports_xray = true;
-    base.features = "+v8a".into();
+    base.features = "+v8a,+outline-atomics".into();
     base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers = SanitizerSet::ADDRESS
         | SanitizerSet::CFI
diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs
index e3c4a793b37..3a00fe89360 100644
--- a/compiler/rustc_type_ir/src/relate.rs
+++ b/compiler/rustc_type_ir/src/relate.rs
@@ -400,8 +400,12 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
         (ty::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => Ok(a),
 
         (ty::Adt(a_def, a_args), ty::Adt(b_def, b_args)) if a_def == b_def => {
-            let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?;
-            Ok(Ty::new_adt(cx, a_def, args))
+            Ok(if a_args.is_empty() {
+                a
+            } else {
+                let args = relation.relate_item_args(a_def.def_id(), a_args, b_args)?;
+                if args == a_args { a } else { Ty::new_adt(cx, a_def, args) }
+            })
         }
 
         (ty::Foreign(a_id), ty::Foreign(b_id)) if a_id == b_id => Ok(Ty::new_foreign(cx, a_id)),
@@ -515,8 +519,12 @@ pub fn structurally_relate_tys<I: Interner, R: TypeRelation<I>>(
         }
 
         (ty::FnDef(a_def_id, a_args), ty::FnDef(b_def_id, b_args)) if a_def_id == b_def_id => {
-            let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
-            Ok(Ty::new_fn_def(cx, a_def_id, args))
+            Ok(if a_args.is_empty() {
+                a
+            } else {
+                let args = relation.relate_item_args(a_def_id, a_args, b_args)?;
+                if args == a_args { a } else { Ty::new_fn_def(cx, a_def_id, args) }
+            })
         }
 
         (ty::FnPtr(a_sig_tys, a_hdr), ty::FnPtr(b_sig_tys, b_hdr)) => {
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 017c790ecac..9ba7c5bd28a 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -21,9 +21,7 @@ compiler_builtins = { path = "../compiler-builtins/compiler-builtins", features
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
-compiler-builtins-no-asm = ["compiler_builtins/no-asm"]
 compiler-builtins-no-f16-f128 = ["compiler_builtins/no-f16-f128"]
-compiler-builtins-mangled-names = ["compiler_builtins/mangled-names"]
 # Make panics and failed asserts immediately abort without formatting any message
 panic_immediate_abort = ["core/panic_immediate_abort"]
 # Choose algorithms that are optimized for binary size instead of runtime performance
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index f1b38813d44..29ab9be0e69 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -97,9 +97,7 @@ backtrace-trace-only = []
 panic-unwind = ["dep:panic_unwind"]
 compiler-builtins-c = ["alloc/compiler-builtins-c"]
 compiler-builtins-mem = ["alloc/compiler-builtins-mem"]
-compiler-builtins-no-asm = ["alloc/compiler-builtins-no-asm"]
 compiler-builtins-no-f16-f128 = ["alloc/compiler-builtins-no-f16-f128"]
-compiler-builtins-mangled-names = ["alloc/compiler-builtins-mangled-names"]
 llvm-libunwind = ["unwind/llvm-libunwind"]
 system-llvm-libunwind = ["unwind/system-llvm-libunwind"]
 
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 6d7d576b32a..9f17ff76445 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -617,7 +617,7 @@ impl Error for JoinPathsError {
 /// # Unix
 ///
 /// - Returns the value of the 'HOME' environment variable if it is set
-///   (including to an empty string).
+///   (and not an empty string).
 /// - Otherwise, it tries to determine the home directory by invoking the `getpwuid_r` function
 ///   using the UID of the current user. An empty home directory field returned from the
 ///   `getpwuid_r` function is considered to be a valid value.
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 850bdfdf5b5..0e68313cc3e 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -633,7 +633,10 @@ pub fn temp_dir() -> PathBuf {
 }
 
 pub fn home_dir() -> Option<PathBuf> {
-    return crate::env::var_os("HOME").or_else(|| unsafe { fallback() }).map(PathBuf::from);
+    return crate::env::var_os("HOME")
+        .filter(|s| !s.is_empty())
+        .or_else(|| unsafe { fallback() })
+        .map(PathBuf::from);
 
     #[cfg(any(
         target_os = "android",
diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml
index 032f5272a9c..82b93682c61 100644
--- a/library/sysroot/Cargo.toml
+++ b/library/sysroot/Cargo.toml
@@ -23,9 +23,7 @@ backtrace = ["std/backtrace"]
 backtrace-trace-only = ["std/backtrace-trace-only"]
 compiler-builtins-c = ["std/compiler-builtins-c"]
 compiler-builtins-mem = ["std/compiler-builtins-mem"]
-compiler-builtins-no-asm = ["std/compiler-builtins-no-asm"]
 compiler-builtins-no-f16-f128 = ["std/compiler-builtins-no-f16-f128"]
-compiler-builtins-mangled-names = ["std/compiler-builtins-mangled-names"]
 debug_refcell = ["std/debug_refcell"]
 llvm-libunwind = ["std/llvm-libunwind"]
 system-llvm-libunwind = ["std/system-llvm-libunwind"]
diff --git a/library/windows_targets/src/lib.rs b/library/windows_targets/src/lib.rs
index 9e82e6a7200..3446e2113dd 100644
--- a/library/windows_targets/src/lib.rs
+++ b/library/windows_targets/src/lib.rs
@@ -34,22 +34,12 @@ pub macro link_dylib {
 
 #[cfg(feature = "windows_raw_dylib")]
 pub macro link($($tt:tt)*) {
-    $crate::link_raw_dylib!($($tt)*)
+    $crate::link_raw_dylib!($($tt)*);
 }
 
 #[cfg(not(feature = "windows_raw_dylib"))]
-pub macro link {
-    ($library:literal $abi:literal $($link_name:literal)? $(#[$doc:meta])? fn $($function:tt)*) => (
-        // Note: the windows-targets crate uses a pre-built Windows.lib import library which we don't
-        // have in this repo. So instead we always link kernel32.lib and add the rest of the import
-        // libraries below by using an empty extern block. This works because extern blocks are not
-        // connected to the library given in the #[link] attribute.
-        #[link(name = "kernel32")]
-        unsafe extern $abi {
-            $(#[link_name=$link_name])?
-            pub fn $($function)*;
-        }
-    )
+pub macro link($($tt:tt)*) {
+    $crate::link_dylib!($($tt)*);
 }
 
 #[cfg(not(feature = "windows_raw_dylib"))]
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index c7e7b0160b1..4abfe1843eb 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -597,11 +597,6 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
 
     let mut features = String::new();
 
-    if stage != 0 && builder.config.default_codegen_backend(target).as_deref() == Some("cranelift")
-    {
-        features += "compiler-builtins-no-f16-f128 ";
-    }
-
     if builder.no_std(target) == Some(true) {
         features += " compiler-builtins-mem";
         if !target.starts_with("bpf") {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index ebbb569e9db..0f9268097d7 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -3132,7 +3132,11 @@ impl Step for Bootstrap {
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/bootstrap")
+        // Bootstrap tests might not be perfectly self-contained and can depend on the external
+        // environment, submodules that are checked out, etc.
+        // Therefore we only run them by default on CI.
+        let runs_on_ci = run.builder.config.is_running_on_ci;
+        run.path("src/bootstrap").default_condition(runs_on_ci)
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/utils/shared_helpers.rs b/src/bootstrap/src/utils/shared_helpers.rs
index 9c6b4a7615d..9428e221f41 100644
--- a/src/bootstrap/src/utils/shared_helpers.rs
+++ b/src/bootstrap/src/utils/shared_helpers.rs
@@ -1,14 +1,18 @@
 //! This module serves two purposes:
-//!     1. It is part of the `utils` module and used in other parts of bootstrap.
-//!     2. It is embedded inside bootstrap shims to avoid a dependency on the bootstrap library.
-//!        Therefore, this module should never use any other bootstrap module. This reduces binary
-//!        size and improves compilation time by minimizing linking time.
+//!
+//! 1. It is part of the `utils` module and used in other parts of bootstrap.
+//! 2. It is embedded inside bootstrap shims to avoid a dependency on the bootstrap library.
+//!    Therefore, this module should never use any other bootstrap module. This reduces binary size
+//!    and improves compilation time by minimizing linking time.
+
+// # Note on tests
+//
+// If we were to declare a tests submodule here, the shim binaries that include this module via
+// `#[path]` would fail to find it, which breaks `./x check bootstrap`. So instead the unit tests
+// for this module are in `super::tests::shared_helpers_tests`.
 
 #![allow(dead_code)]
 
-#[cfg(test)]
-mod tests;
-
 use std::env;
 use std::ffi::OsString;
 use std::fs::OpenOptions;
@@ -16,10 +20,6 @@ use std::io::Write;
 use std::process::Command;
 use std::str::FromStr;
 
-// If we were to declare a tests submodule here, the shim binaries that include this
-// module via `#[path]` would fail to find it, which breaks `./x check bootstrap`.
-// So instead the unit tests for this module are in `super::tests::shared_helpers_tests`.
-
 /// Returns the environment variable which the dynamic library lookup path
 /// resides in for this platform.
 pub fn dylib_path_var() -> &'static str {
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index ec87e71e0b6..983680b0385 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -12,6 +12,10 @@ use crate::{Build, Config, Flags, t};
 
 pub mod git;
 
+// Note: tests for `shared_helpers` is separate here, as otherwise shim binaries that include the
+// `shared_helpers` via `#[path]` would fail to find it, breaking `./x check bootstrap`.
+mod shared_helpers_tests;
+
 /// Holds temporary state of a bootstrap test.
 /// Right now it is only used to redirect the build directory of the bootstrap
 /// invocation, in the future it would be great if we could actually execute
diff --git a/src/bootstrap/src/utils/shared_helpers/tests.rs b/src/bootstrap/src/utils/tests/shared_helpers_tests.rs
index 559e9f70abd..c486e65007e 100644
--- a/src/bootstrap/src/utils/shared_helpers/tests.rs
+++ b/src/bootstrap/src/utils/tests/shared_helpers_tests.rs
@@ -1,3 +1,10 @@
+//! The `shared_helpers` module can't have its own tests submodule, because that would cause
+//! problems for the shim binaries that include it via `#[path]`, so instead those unit tests live
+//! here.
+//!
+//! To prevent tidy from complaining about this file not being named `tests.rs`, it lives inside a
+//! submodule directory named `tests`.
+
 use crate::utils::shared_helpers::parse_value_from_args;
 
 #[test]
diff --git a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
index d3c3cd1b63e..f7d51fba861 100644
--- a/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
+++ b/src/ci/docker/host-x86_64/pr-check-1/Dockerfile
@@ -40,6 +40,7 @@ COPY host-x86_64/pr-check-1/validate-toolstate.sh /scripts/
 # We disable optimized compiler built-ins because that requires a C toolchain for the target.
 # We also skip the x86_64-unknown-linux-gnu target as it is well-tested by other jobs.
 ENV SCRIPT \
+  python3 ../x.py check bootstrap && \
   /scripts/check-default-config-profiles.sh && \
   python3 ../x.py build src/tools/build-manifest && \
   python3 ../x.py test --stage 0 src/tools/compiletest && \
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 4d09bea69c0..662a26400ce 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -79,7 +79,6 @@ ENV MUSL_TARGETS=x86_64-unknown-linux-musl \
     CXX_x86_64_unknown_linux_musl=x86_64-linux-musl-g++
 ENV MUSL_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $MUSL_TARGETS
 
-COPY host-x86_64/test-various/uefi_qemu_test /uefi_qemu_test
 ENV UEFI_TARGETS=aarch64-unknown-uefi,i686-unknown-uefi,x86_64-unknown-uefi \
     CC_aarch64_unknown_uefi=clang-11 \
     CXX_aarch64_unknown_uefi=clang++-11 \
@@ -88,6 +87,8 @@ ENV UEFI_TARGETS=aarch64-unknown-uefi,i686-unknown-uefi,x86_64-unknown-uefi \
     CC_x86_64_unknown_uefi=clang-11 \
     CXX_x86_64_unknown_uefi=clang++-11
 ENV UEFI_SCRIPT python3 /checkout/x.py --stage 2 build --host='' --target $UEFI_TARGETS && \
-  python3 -u /uefi_qemu_test/run.py
+  python3 /checkout/x.py --stage 2 test tests/run-make/uefi-qemu/rmake.rs --target aarch64-unknown-uefi && \
+  python3 /checkout/x.py --stage 2 test tests/run-make/uefi-qemu/rmake.rs --target i686-unknown-uefi && \
+  python3 /checkout/x.py --stage 2 test tests/run-make/uefi-qemu/rmake.rs --target x86_64-unknown-uefi
 
 ENV SCRIPT $WASM_SCRIPT && $NVPTX_SCRIPT && $MUSL_SCRIPT && $UEFI_SCRIPT
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py b/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py
deleted file mode 100755
index 4f877389fbc..00000000000
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/run.py
+++ /dev/null
@@ -1,140 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import shutil
-import subprocess
-import sys
-import tempfile
-
-from pathlib import Path
-
-TARGET_AARCH64 = "aarch64-unknown-uefi"
-TARGET_I686 = "i686-unknown-uefi"
-TARGET_X86_64 = "x86_64-unknown-uefi"
-
-
-def run(*cmd, capture=False, check=True, env=None, timeout=None):
-    """Print and run a command, optionally capturing the output."""
-    cmd = [str(p) for p in cmd]
-    print(" ".join(cmd))
-    return subprocess.run(
-        cmd, capture_output=capture, check=check, env=env, text=True, timeout=timeout
-    )
-
-
-def build_and_run(tmp_dir, target):
-    if target == TARGET_AARCH64:
-        boot_file_name = "bootaa64.efi"
-        ovmf_dir = Path("/usr/share/AAVMF")
-        ovmf_code = "AAVMF_CODE.fd"
-        ovmf_vars = "AAVMF_VARS.fd"
-        qemu = "qemu-system-aarch64"
-        machine = "virt"
-        cpu = "cortex-a72"
-    elif target == TARGET_I686:
-        boot_file_name = "bootia32.efi"
-        ovmf_dir = Path("/usr/share/OVMF")
-        ovmf_code = "OVMF32_CODE_4M.secboot.fd"
-        ovmf_vars = "OVMF32_VARS_4M.fd"
-        # The i686 target intentionally uses 64-bit qemu; the important
-        # difference is that the OVMF code provides a 32-bit environment.
-        qemu = "qemu-system-x86_64"
-        machine = "q35"
-        cpu = "qemu64"
-    elif target == TARGET_X86_64:
-        boot_file_name = "bootx64.efi"
-        ovmf_dir = Path("/usr/share/OVMF")
-        ovmf_code = "OVMF_CODE.fd"
-        ovmf_vars = "OVMF_VARS.fd"
-        qemu = "qemu-system-x86_64"
-        machine = "q35"
-        cpu = "qemu64"
-    else:
-        raise KeyError("invalid target")
-
-    host_artifacts = Path("/checkout/obj/build/x86_64-unknown-linux-gnu")
-    stage0 = host_artifacts / "stage0/bin"
-    stage2 = host_artifacts / "stage2/bin"
-
-    env = dict(os.environ)
-    env["PATH"] = "{}:{}:{}".format(stage2, stage0, env["PATH"])
-
-    # Copy the test create into `tmp_dir`.
-    test_crate = Path(tmp_dir) / "uefi_qemu_test"
-    shutil.copytree("/uefi_qemu_test", test_crate)
-
-    # Build the UEFI executable.
-    run(
-        "cargo",
-        "build",
-        "--manifest-path",
-        test_crate / "Cargo.toml",
-        "--target",
-        target,
-        env=env,
-    )
-
-    # Create a mock EFI System Partition in a subdirectory.
-    esp = test_crate / "esp"
-    boot = esp / "efi/boot"
-    os.makedirs(boot, exist_ok=True)
-
-    # Copy the executable into the ESP.
-    src_exe_path = test_crate / "target" / target / "debug/uefi_qemu_test.efi"
-    shutil.copy(src_exe_path, boot / boot_file_name)
-    print(src_exe_path, boot / boot_file_name)
-
-    # Select the appropriate EDK2 build.
-    ovmf_code = ovmf_dir / ovmf_code
-    ovmf_vars = ovmf_dir / ovmf_vars
-
-    # Make a writable copy of the vars file. aarch64 doesn't boot
-    # correctly with read-only vars.
-    ovmf_rw_vars = Path(tmp_dir) / "vars.fd"
-    shutil.copy(ovmf_vars, ovmf_rw_vars)
-
-    # Run the executable in QEMU and capture the output.
-    output = run(
-        qemu,
-        "-machine",
-        machine,
-        "-cpu",
-        cpu,
-        "-display",
-        "none",
-        "-serial",
-        "stdio",
-        "-drive",
-        f"if=pflash,format=raw,readonly=on,file={ovmf_code}",
-        "-drive",
-        f"if=pflash,format=raw,readonly=off,file={ovmf_rw_vars}",
-        "-drive",
-        f"format=raw,file=fat:rw:{esp}",
-        capture=True,
-        check=True,
-        # Set a timeout to kill the VM in case something goes wrong.
-        timeout=60,
-    ).stdout
-
-    if "Hello World!" in output:
-        print("VM produced expected output")
-    else:
-        print("unexpected VM output:")
-        print("---start---")
-        print(output)
-        print("---end---")
-        sys.exit(1)
-
-
-def main():
-    targets = [TARGET_AARCH64, TARGET_I686, TARGET_X86_64]
-
-    for target in targets:
-        # Create a temporary directory so that we have a writeable
-        # workspace.
-        with tempfile.TemporaryDirectory() as tmp_dir:
-            build_and_run(tmp_dir, target)
-
-
-if __name__ == "__main__":
-    main()
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1265a39d27b..14295ce0a31 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -36,6 +36,7 @@ use std::mem;
 
 use rustc_ast::token::{Token, TokenKind};
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_attr_data_structures::{AttributeKind, find_attr};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry};
 use rustc_errors::codes::*;
 use rustc_errors::{FatalError, struct_span_code_err};
@@ -987,28 +988,17 @@ fn clean_proc_macro<'tcx>(
     kind: MacroKind,
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
-    let attrs = cx.tcx.hir_attrs(item.hir_id());
-    if kind == MacroKind::Derive
-        && let Some(derive_name) =
-            hir_attr_lists(attrs, sym::proc_macro_derive).find_map(|mi| mi.ident())
-    {
-        *name = derive_name.name;
+    if kind != MacroKind::Derive {
+        return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
     }
+    let attrs = cx.tcx.hir_attrs(item.hir_id());
+    let Some((trait_name, helper_attrs)) = find_attr!(attrs, AttributeKind::ProcMacroDerive { trait_name, helper_attrs, ..} => (*trait_name, helper_attrs))
+    else {
+        return ProcMacroItem(ProcMacro { kind, helpers: vec![] });
+    };
+    *name = trait_name;
+    let helpers = helper_attrs.iter().copied().collect();
 
-    let mut helpers = Vec::new();
-    for mi in hir_attr_lists(attrs, sym::proc_macro_derive) {
-        if !mi.has_name(sym::attributes) {
-            continue;
-        }
-
-        if let Some(list) = mi.meta_item_list() {
-            for inner_mi in list {
-                if let Some(ident) = inner_mi.ident() {
-                    helpers.push(ident.name);
-                }
-            }
-        }
-    }
     ProcMacroItem(ProcMacro { kind, helpers })
 }
 
@@ -1021,17 +1011,16 @@ fn clean_fn_or_proc_macro<'tcx>(
     cx: &mut DocContext<'tcx>,
 ) -> ItemKind {
     let attrs = cx.tcx.hir_attrs(item.hir_id());
-    let macro_kind = attrs.iter().find_map(|a| {
-        if a.has_name(sym::proc_macro) {
-            Some(MacroKind::Bang)
-        } else if a.has_name(sym::proc_macro_derive) {
-            Some(MacroKind::Derive)
-        } else if a.has_name(sym::proc_macro_attribute) {
-            Some(MacroKind::Attr)
-        } else {
-            None
-        }
-    });
+    let macro_kind = if find_attr!(attrs, AttributeKind::ProcMacro(..)) {
+        Some(MacroKind::Bang)
+    } else if find_attr!(attrs, AttributeKind::ProcMacroDerive { .. }) {
+        Some(MacroKind::Derive)
+    } else if find_attr!(attrs, AttributeKind::ProcMacroAttribute(..)) {
+        Some(MacroKind::Attr)
+    } else {
+        None
+    };
+
     match macro_kind {
         Some(kind) => clean_proc_macro(item, name, kind, cx),
         None => {
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 2006a824402..7b057998063 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -312,9 +312,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
 /// Functions marked with these attributes must have the exact signature.
 pub(crate) fn requires_exact_signature(attrs: &[Attribute]) -> bool {
     attrs.iter().any(|attr| {
-        [sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
-            .iter()
-            .any(|&allow| attr.has_name(allow))
+        attr.is_proc_macro_attr()
     })
 }
 
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 8dc3a46d6dd..a1f76a07556 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -992,6 +992,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "only-stable",
     "only-thumb",
     "only-tvos",
+    "only-uefi",
     "only-unix",
     "only-visionos",
     "only-wasm32",
diff --git a/src/tools/generate-copyright/Cargo.toml b/src/tools/generate-copyright/Cargo.toml
index e420a450d42..bcb3165de45 100644
--- a/src/tools/generate-copyright/Cargo.toml
+++ b/src/tools/generate-copyright/Cargo.toml
@@ -9,7 +9,7 @@ description = "Produces a manifest of all the copyrighted materials in the Rust
 [dependencies]
 anyhow = "1.0.65"
 askama = "0.14.0"
-cargo_metadata = "0.18.1"
+cargo_metadata = "0.21"
 serde = { version = "1.0.147", features = ["derive"] }
 serde_json = "1.0.85"
 thiserror = "1"
diff --git a/src/tools/generate-copyright/src/cargo_metadata.rs b/src/tools/generate-copyright/src/cargo_metadata.rs
index 3fae26bda47..87cd85c8def 100644
--- a/src/tools/generate-copyright/src/cargo_metadata.rs
+++ b/src/tools/generate-copyright/src/cargo_metadata.rs
@@ -92,7 +92,8 @@ pub fn get_metadata(
                 continue;
             }
             // otherwise it's an out-of-tree dependency
-            let package_id = Package { name: package.name, version: package.version.to_string() };
+            let package_id =
+                Package { name: package.name.to_string(), version: package.version.to_string() };
             output.insert(
                 package_id,
                 PackageMetadata {
diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml
index d995106ae02..c1f27de7ed4 100644
--- a/src/tools/tidy/Cargo.toml
+++ b/src/tools/tidy/Cargo.toml
@@ -6,7 +6,7 @@ autobins = false
 
 [dependencies]
 build_helper = { path = "../../build_helper" }
-cargo_metadata = "0.19"
+cargo_metadata = "0.21"
 regex = "1"
 miropt-test-tools = { path = "../miropt-test-tools" }
 walkdir = "2"
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 21cbb143c51..8e2a796106f 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -73,7 +73,6 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>,
     // tidy-alphabetical-start
     ("compiler/rustc_codegen_gcc", EXCEPTIONS_GCC, None, &[]),
     ("src/bootstrap", EXCEPTIONS_BOOTSTRAP, None, &[]),
-    ("src/ci/docker/host-x86_64/test-various/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]),
     ("src/tools/cargo", EXCEPTIONS_CARGO, None, &["src/tools/cargo"]),
     //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored
     //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored
@@ -81,6 +80,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>,
     ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]),
     ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]),
     ("src/tools/test-float-parse", EXCEPTIONS, None, &[]),
+    ("tests/run-make/uefi-qemu/uefi_qemu_test", EXCEPTIONS_UEFI_QEMU_TEST, None, &[]),
     // tidy-alphabetical-end
 ];
 
@@ -633,8 +633,8 @@ fn check_proc_macro_dep_list(root: &Path, cargo: &Path, bless: bool, bad: &mut b
     proc_macro_deps.retain(|pkg| !is_proc_macro_pkg(&metadata[pkg]));
 
     let proc_macro_deps: HashSet<_> =
-        proc_macro_deps.into_iter().map(|dep| metadata[dep].name.clone()).collect();
-    let expected = proc_macro_deps::CRATES.iter().map(|s| s.to_string()).collect::<HashSet<_>>();
+        proc_macro_deps.into_iter().map(|dep| metadata[dep].name.as_ref()).collect();
+    let expected = proc_macro_deps::CRATES.iter().copied().collect::<HashSet<_>>();
 
     let needs_blessing = proc_macro_deps.difference(&expected).next().is_some()
         || expected.difference(&proc_macro_deps).next().is_some();
@@ -718,7 +718,7 @@ fn check_runtime_license_exceptions(metadata: &Metadata, bad: &mut bool) {
             // See https://github.com/rust-lang/rust/issues/62620 for more.
             // In general, these should never be added and this exception
             // should not be taken as precedent for any new target.
-            if pkg.name == "fortanix-sgx-abi" && pkg.license.as_deref() == Some("MPL-2.0") {
+            if *pkg.name == "fortanix-sgx-abi" && pkg.license.as_deref() == Some("MPL-2.0") {
                 continue;
             }
 
@@ -734,7 +734,7 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
     // Validate the EXCEPTIONS list hasn't changed.
     for (name, license) in exceptions {
         // Check that the package actually exists.
-        if !metadata.packages.iter().any(|p| p.name == *name) {
+        if !metadata.packages.iter().any(|p| *p.name == *name) {
             tidy_error!(
                 bad,
                 "could not find exception package `{}`\n\
@@ -743,7 +743,7 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba
             );
         }
         // Check that the license hasn't changed.
-        for pkg in metadata.packages.iter().filter(|p| p.name == *name) {
+        for pkg in metadata.packages.iter().filter(|p| *p.name == *name) {
             match &pkg.license {
                 None => {
                     if *license == NON_STANDARD_LICENSE
@@ -818,9 +818,9 @@ fn check_permitted_dependencies(
                 let Ok(version) = Version::parse(version) else {
                     return false;
                 };
-                pkg.name == name && pkg.version == version
+                *pkg.name == name && pkg.version == version
             } else {
-                pkg.name == permitted
+                *pkg.name == permitted
             }
         }
         if !deps.iter().any(|dep_id| compare(pkg_from_id(metadata, dep_id), permitted)) {
@@ -868,7 +868,7 @@ fn check_permitted_dependencies(
 
 /// Finds a package with the given name.
 fn pkg_from_name<'a>(metadata: &'a Metadata, name: &'static str) -> &'a Package {
-    let mut i = metadata.packages.iter().filter(|p| p.name == name);
+    let mut i = metadata.packages.iter().filter(|p| *p.name == name);
     let result =
         i.next().unwrap_or_else(|| panic!("could not find package `{name}` in package list"));
     assert!(i.next().is_none(), "more than one package found for `{name}`");
diff --git a/tests/assembly-llvm/asm/aarch64-outline-atomics.rs b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs
index 5990fb84942..22599c18dcf 100644
--- a/tests/assembly-llvm/asm/aarch64-outline-atomics.rs
+++ b/tests/assembly-llvm/asm/aarch64-outline-atomics.rs
@@ -1,7 +1,5 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: -Copt-level=3
-//@ compile-flags: --target aarch64-unknown-linux-gnu
-//@ needs-llvm-components: aarch64
 //@ only-aarch64
 //@ only-linux
 
diff --git a/tests/codegen-llvm/cffi/c-variadic-ffi.rs b/tests/codegen-llvm/cffi/c-variadic-ffi.rs
new file mode 100644
index 00000000000..3e99c9fb84e
--- /dev/null
+++ b/tests/codegen-llvm/cffi/c-variadic-ffi.rs
@@ -0,0 +1,86 @@
+//! Test calling variadic functions with various ABIs.
+//@ add-core-stubs
+//@ compile-flags: -Z merge-functions=disabled
+//@ revisions: x86_32 x86_32_win x86_64 aarch64 arm32
+//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86_64] needs-llvm-components: x86
+//@[x86_32_win] compile-flags: --target i686-pc-windows-msvc
+//@[x86_32_win] needs-llvm-components: x86
+//@[x86_32] compile-flags: --target i686-unknown-linux-gnu
+//@[x86_32] needs-llvm-components: x86
+//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@[aarch64] needs-llvm-components: aarch64
+//@[arm32] compile-flags: --target armv7-unknown-linux-gnueabihf
+//@[arm32] needs-llvm-components: arm
+#![crate_type = "lib"]
+#![feature(no_core)]
+#![feature(extended_varargs_abi_support, extern_system_varargs)]
+#![no_core]
+
+extern crate minicore;
+
+// CHECK-LABEL: @c
+#[unsafe(no_mangle)]
+fn c(f: extern "C" fn(i32, ...)) {
+    // CHECK: call void (i32, ...)
+    f(22, 44);
+}
+
+// CHECK-LABEL: @system
+#[unsafe(no_mangle)]
+fn system(f: extern "system" fn(i32, ...)) {
+    // Crucially, this is *always* the C calling convention, even on Windows.
+    // CHECK: call void (i32, ...)
+    f(22, 44);
+}
+
+// x86_32-LABEL: @cdecl
+#[unsafe(no_mangle)]
+#[cfg(target_arch = "x86")]
+fn cdecl(f: extern "cdecl" fn(i32, ...)) {
+    // x86_32: call void (i32, ...)
+    f(22, 44);
+}
+
+// x86_64-LABEL: @sysv
+#[unsafe(no_mangle)]
+#[cfg(target_arch = "x86_64")]
+fn sysv(f: extern "sysv64" fn(i32, ...)) {
+    // x86_64: call x86_64_sysvcc void (i32, ...)
+    f(22, 44);
+}
+
+// x86_64-LABEL: @win
+#[unsafe(no_mangle)]
+#[cfg(target_arch = "x86_64")]
+fn win(f: extern "win64" fn(i32, ...)) {
+    // x86_64: call win64cc void (i32, ...)
+    f(22, 44);
+}
+
+// CHECK-LABEL: @efiapi
+#[unsafe(no_mangle)]
+#[cfg(any(
+    target_arch = "arm",
+    target_arch = "aarch64",
+    target_arch = "riscv32",
+    target_arch = "riscv64",
+    target_arch = "x86",
+    target_arch = "x86_64"
+))]
+fn efiapi(f: extern "efiapi" fn(i32, ...)) {
+    // x86_32: call void (i32, ...)
+    // x86_32_win: call void (i32, ...)
+    // x86_64: call win64cc void (i32, ...)
+    // aarch64: call void (i32, ...)
+    // arm32: call arm_aapcscc void (i32, ...)
+    f(22, 44);
+}
+
+// arm32-LABEL: @aapcs
+#[unsafe(no_mangle)]
+#[cfg(target_arch = "arm")]
+fn aapcs(f: extern "aapcs" fn(i32, ...)) {
+    // arm32: call arm_aapcscc void (i32, ...)
+    f(22, 44);
+}
diff --git a/tests/codegen-llvm/enum/enum-transparent-extract.rs b/tests/codegen-llvm/enum/enum-transparent-extract.rs
new file mode 100644
index 00000000000..c5efb8d472b
--- /dev/null
+++ b/tests/codegen-llvm/enum/enum-transparent-extract.rs
@@ -0,0 +1,31 @@
+//@ compile-flags: -Copt-level=0
+//@ only-64bit
+
+#![crate_type = "lib"]
+
+use std::ops::ControlFlow;
+
+pub enum Never {}
+
+#[no_mangle]
+pub fn make_unmake_result_never(x: i32) -> i32 {
+    // CHECK-LABEL: define i32 @make_unmake_result_never(i32 %x)
+    // CHECK: start:
+    // CHECK-NEXT: ret i32 %x
+
+    let y: Result<i32, Never> = Ok(x);
+    let Ok(z) = y;
+    z
+}
+
+#[no_mangle]
+pub fn extract_control_flow_never(x: ControlFlow<&str, Never>) -> &str {
+    // CHECK-LABEL: define { ptr, i64 } @extract_control_flow_never(ptr align 1 %x.0, i64 %x.1)
+    // CHECK: start:
+    // CHECK-NEXT: %[[P0:.+]] = insertvalue { ptr, i64 } poison, ptr %x.0, 0
+    // CHECK-NEXT: %[[P1:.+]] = insertvalue { ptr, i64 } %[[P0]], i64 %x.1, 1
+    // CHECK-NEXT: ret { ptr, i64 } %[[P1]]
+
+    let ControlFlow::Break(s) = x;
+    s
+}
diff --git a/tests/codegen-llvm/intrinsics/transmute-simd.rs b/tests/codegen-llvm/intrinsics/transmute-simd.rs
new file mode 100644
index 00000000000..e34b27e1333
--- /dev/null
+++ b/tests/codegen-llvm/intrinsics/transmute-simd.rs
@@ -0,0 +1,176 @@
+//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes
+//@ only-64bit (so I don't need to worry about usize)
+//@ revisions: aarch64 x86_64
+//@ [aarch64] only-aarch64
+//@ [aarch64] compile-flags: -C target-feature=+neon
+//@ [x86_64] only-x86_64
+//@ [x86_64] compile-flags: -C target-feature=+sse2
+
+#![crate_type = "lib"]
+#![feature(core_intrinsics)]
+#![feature(portable_simd)]
+
+use std::intrinsics::transmute;
+use std::simd::{Simd, f32x4, f64x2, i32x4, i64x2};
+type PtrX2 = Simd<*const (), 2>;
+
+// These tests use the "C" ABI so that the vectors in question aren't passed and
+// returned though memory (as they are in the "Rust" ABI), which greatly
+// simplifies seeing the difference between the in-operand cases vs the ones
+// that fallback to just using the `LocalKind::Memory` path.
+
+// CHECK-LABEL: <2 x i64> @mixed_int(<4 x i32> %v)
+#[no_mangle]
+pub extern "C" fn mixed_int(v: i32x4) -> i64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <4 x i32> %v to <2 x i64>
+    // CHECK: ret <2 x i64> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x double> @mixed_float(<4 x float> %v)
+#[no_mangle]
+pub extern "C" fn mixed_float(v: f32x4) -> f64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <4 x float> %v to <2 x double>
+    // CHECK: ret <2 x double> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <4 x i32> @float_int_same_lanes(<4 x float> %v)
+#[no_mangle]
+pub extern "C" fn float_int_same_lanes(v: f32x4) -> i32x4 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <4 x float> %v to <4 x i32>
+    // CHECK: ret <4 x i32> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x double> @int_float_same_lanes(<2 x i64> %v)
+#[no_mangle]
+pub extern "C" fn int_float_same_lanes(v: i64x2) -> f64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <2 x i64> %v to <2 x double>
+    // CHECK: ret <2 x double> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x i64> @float_int_widen(<4 x float> %v)
+#[no_mangle]
+pub extern "C" fn float_int_widen(v: f32x4) -> i64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <4 x float> %v to <2 x i64>
+    // CHECK: ret <2 x i64> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x double> @int_float_widen(<4 x i32> %v)
+#[no_mangle]
+pub extern "C" fn int_float_widen(v: i32x4) -> f64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <4 x i32> %v to <2 x double>
+    // CHECK: ret <2 x double> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <4 x i32> @float_int_narrow(<2 x double> %v)
+#[no_mangle]
+pub extern "C" fn float_int_narrow(v: f64x2) -> i32x4 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <2 x double> %v to <4 x i32>
+    // CHECK: ret <4 x i32> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <4 x float> @int_float_narrow(<2 x i64> %v)
+#[no_mangle]
+pub extern "C" fn int_float_narrow(v: i64x2) -> f32x4 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[RET:.+]] = bitcast <2 x i64> %v to <4 x float>
+    // CHECK: ret <4 x float> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x ptr> @float_ptr_same_lanes(<2 x double> %v)
+#[no_mangle]
+pub extern "C" fn float_ptr_same_lanes(v: f64x2) -> PtrX2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <2 x double> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x ptr>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x ptr> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x double> @ptr_float_same_lanes(<2 x ptr> %v)
+#[no_mangle]
+pub extern "C" fn ptr_float_same_lanes(v: PtrX2) -> f64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <2 x ptr> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x double>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x double> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x ptr> @int_ptr_same_lanes(<2 x i64> %v)
+#[no_mangle]
+pub extern "C" fn int_ptr_same_lanes(v: i64x2) -> PtrX2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <2 x i64> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x ptr>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x ptr> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x i64> @ptr_int_same_lanes(<2 x ptr> %v)
+#[no_mangle]
+pub extern "C" fn ptr_int_same_lanes(v: PtrX2) -> i64x2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <2 x ptr> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x i64>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x i64> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x ptr> @float_ptr_widen(<4 x float> %v)
+#[no_mangle]
+pub extern "C" fn float_ptr_widen(v: f32x4) -> PtrX2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <4 x float> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x ptr>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x ptr> %[[RET]]
+    unsafe { transmute(v) }
+}
+
+// CHECK-LABEL: <2 x ptr> @int_ptr_widen(<4 x i32> %v)
+#[no_mangle]
+pub extern "C" fn int_ptr_widen(v: i32x4) -> PtrX2 {
+    // CHECK-NOT: alloca
+    // CHECK: %[[TEMP:.+]] = alloca [16 x i8]
+    // CHECK-NOT: alloca
+    // CHECK: call void @llvm.lifetime.start.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: store <4 x i32> %v, ptr %[[TEMP]]
+    // CHECK: %[[RET:.+]] = load <2 x ptr>, ptr %[[TEMP]]
+    // CHECK: call void @llvm.lifetime.end.p0(i64 16, ptr %[[TEMP]])
+    // CHECK: ret <2 x ptr> %[[RET]]
+    unsafe { transmute(v) }
+}
diff --git a/tests/codegen-llvm/intrinsics/transmute.rs b/tests/codegen-llvm/intrinsics/transmute.rs
index c9a1cd58af3..91cff38773d 100644
--- a/tests/codegen-llvm/intrinsics/transmute.rs
+++ b/tests/codegen-llvm/intrinsics/transmute.rs
@@ -191,22 +191,28 @@ pub unsafe fn check_byte_from_bool(x: bool) -> u8 {
 // CHECK-LABEL: @check_to_pair(
 #[no_mangle]
 pub unsafe fn check_to_pair(x: u64) -> Option<i32> {
-    // CHECK: %_0 = alloca [8 x i8], align 4
-    // CHECK: store i64 %x, ptr %_0, align 4
+    // CHECK: %[[TEMP:.+]] = alloca [8 x i8], align 8
+    // CHECK: call void @llvm.lifetime.start.p0(i64 8, ptr %[[TEMP]])
+    // CHECK: store i64 %x, ptr %[[TEMP]], align 8
+    // CHECK: %[[PAIR0:.+]] = load i32, ptr %[[TEMP]], align 8
+    // CHECK: %[[PAIR1P:.+]] = getelementptr inbounds i8, ptr %[[TEMP]], i64 4
+    // CHECK: %[[PAIR1:.+]] = load i32, ptr %[[PAIR1P]], align 4
+    // CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[TEMP]])
+    // CHECK: insertvalue {{.+}}, i32 %[[PAIR0]], 0
+    // CHECK: insertvalue {{.+}}, i32 %[[PAIR1]], 1
     transmute(x)
 }
 
 // CHECK-LABEL: @check_from_pair(
 #[no_mangle]
 pub unsafe fn check_from_pair(x: Option<i32>) -> u64 {
-    // The two arguments are of types that are only 4-aligned, but they're
-    // immediates so we can write using the destination alloca's alignment.
-    const { assert!(std::mem::align_of::<Option<i32>>() == 4) };
-
-    // CHECK: %_0 = alloca [8 x i8], align 8
-    // CHECK: store i32 %x.0, ptr %_0, align 8
-    // CHECK: store i32 %x.1, ptr %0, align 4
-    // CHECK: %[[R:.+]] = load i64, ptr %_0, align 8
+    // CHECK: %[[TEMP:.+]] = alloca [8 x i8], align 8
+    // CHECK: call void @llvm.lifetime.start.p0(i64 8, ptr %[[TEMP]])
+    // CHECK: store i32 %x.0, ptr %[[TEMP]], align 8
+    // CHECK: %[[PAIR1P:.+]] = getelementptr inbounds i8, ptr %[[TEMP]], i64 4
+    // CHECK: store i32 %x.1, ptr %[[PAIR1P]], align 4
+    // CHECK: %[[R:.+]] = load i64, ptr %[[TEMP]], align 8
+    // CHECK: call void @llvm.lifetime.end.p0(i64 8, ptr %[[TEMP]])
     // CHECK: ret i64 %[[R]]
     transmute(x)
 }
diff --git a/tests/coverage/async_closure.cov-map b/tests/coverage/async_closure.cov-map
index 53128dd7a48..9f8dc8d6cbb 100644
--- a/tests/coverage/async_closure.cov-map
+++ b/tests/coverage/async_closure.cov-map
@@ -37,29 +37,32 @@ Number of file 0 mappings: 8
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
 Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
+Raw bytes (14): 0x[01, 01, 00, 02, 01, 0b, 22, 00, 23, 01, 00, 23, 00, 24]
 Number of files: 1
 - file 0 => $DIR/async_closure.rs
 Number of expressions: 0
-Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
+Number of file 0 mappings: 2
+- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 35)
+- Code(Counter(0)) at (prev + 0, 35) to (start + 0, 36)
 Highest counter ID seen: c0
 
diff --git a/tests/crashes/121176.rs b/tests/crashes/121176.rs
deleted file mode 100644
index 4d82e51de8f..00000000000
--- a/tests/crashes/121176.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #121176
-//@ needs-rustc-debug-assertions
-use std::fmt::Debug;
-
-static STATIC_1: dyn Debug + Sync = *();
-
-fn main() {
-    println!("{:?}", &STATIC_1);
-}
diff --git a/tests/crashes/129109.rs b/tests/crashes/129109.rs
deleted file mode 100644
index 0db53b98a71..00000000000
--- a/tests/crashes/129109.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ known-bug: rust-lang/rust#129109
-//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir
-
-extern "C" {
-    pub static mut symbol: [i8];
-}
-
-fn main() {
-    println!("C", unsafe { &symbol });
-}
diff --git a/tests/crashes/130970.rs b/tests/crashes/130970.rs
deleted file mode 100644
index 698c2b478e1..00000000000
--- a/tests/crashes/130970.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #130970
-//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir
-
-fn main() {
-    extern "C" {
-        static symbol: [usize];
-    }
-    println!("{}", symbol[0]);
-}
diff --git a/tests/crashes/131347.rs b/tests/crashes/131347.rs
deleted file mode 100644
index 08f7d068e25..00000000000
--- a/tests/crashes/131347.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ known-bug: #131347
-//@ compile-flags: -Zmir-enable-passes=+GVN -Zmir-enable-passes=+Inline -Zvalidate-mir
-
-struct S;
-static STUFF: [i8] = [0; S::N];
-
-fn main() {
-    assert_eq!(STUFF, [0; 63]);
-}
diff --git a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
index fa88211383a..d465b8bded2 100644
--- a/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/branch_match_arms.main.InstrumentCoverage.diff
@@ -40,7 +40,7 @@
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:17: 19:18 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:23: 19:30 (#0);
 +     coverage Code { bcb: bcb5 } => $DIR/branch_match_arms.rs:19:31: 19:32 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:1: 21:2 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/branch_match_arms.rs:21:2: 21:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
index 9b6d2b22087..cf6d85abd80 100644
--- a/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.bar.InstrumentCoverage.diff
@@ -6,7 +6,7 @@
   
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:27:1: 27:17 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:28:5: 28:9 (#0);
-+     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:1: 29:2 (#0);
++     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:29:2: 29:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
index b2bb2375aee..980c5e202ff 100644
--- a/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage.rs:15:12: 15:15 (#0);
 +     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:16:13: 16:18 (#0);
-+     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:9: 17:10 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:1: 19:2 (#0);
++     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage.rs:17:10: 17:10 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage.rs:19:2: 19:2 (#0);
 + 
       bb0: {
 +         Coverage::VirtualCounter(bcb0);
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
index 2eb78c08ee8..b707cd41788 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.CleanupPostBorrowck.diff
@@ -10,8 +10,8 @@
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
       coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
       coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
-      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
+      coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
+      coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
       coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
   
       bb0: {
diff --git a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
index 0c1bc24b6dc..239b845c231 100644
--- a/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
+++ b/tests/mir-opt/coverage/instrument_coverage_cleanup.main.InstrumentCoverage.diff
@@ -10,8 +10,8 @@
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:13:1: 13:10 (#0);
 +     coverage Code { bcb: bcb0 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 +     coverage Code { bcb: bcb3 } => $DIR/instrument_coverage_cleanup.rs:14:37: 14:39 (#0);
-+     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:38: 14:39 (#0);
-+     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:1: 15:2 (#0);
++     coverage Code { bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:39: 14:39 (#0);
++     coverage Code { bcb: bcb2 } => $DIR/instrument_coverage_cleanup.rs:15:2: 15:2 (#0);
 +     coverage Branch { true_bcb: bcb3, false_bcb: bcb1 } => $DIR/instrument_coverage_cleanup.rs:14:8: 14:36 (#0);
 + 
       bb0: {
diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs
index 57b68c65930..9ea706af503 100644
--- a/tests/run-make/linker-warning/rmake.rs
+++ b/tests/run-make/linker-warning/rmake.rs
@@ -64,7 +64,9 @@ fn main() {
             .normalize(r#"/rustc[^/_-]*/"#, "/rustc/")
             .normalize("libpanic_abort", "libpanic_unwind")
             .normalize(
-                regex::escape(run_make_support::build_root().to_str().unwrap()),
+                regex::escape(
+                    run_make_support::build_root().canonicalize().unwrap().to_str().unwrap(),
+                ),
                 "/build-root",
             )
             .normalize(r#""[^"]*\/symbols.o""#, "\"/symbols.o\"")
diff --git a/tests/run-make/uefi-qemu/rmake.rs b/tests/run-make/uefi-qemu/rmake.rs
new file mode 100644
index 00000000000..55d42fba5e7
--- /dev/null
+++ b/tests/run-make/uefi-qemu/rmake.rs
@@ -0,0 +1,84 @@
+//! This test builds and runs a basic UEFI application on QEMU for various targets.
+//!
+//! You must have the relevant OVMF or AAVMF firmware installed for this to work.
+//!
+//! Requires: qemu-system-x86_64, qemu-system-aarch64
+//!           OVMF/AAVMF firmware
+//!
+//! Note: test assumes `/uefi_qemu_test` exists and is a self-contained crate.
+
+//@ only-uefi
+
+use std::path::Path;
+
+use run_make_support::{cargo, cmd, path, rfs};
+
+fn main() {
+    let target = run_make_support::target();
+
+    let (boot_filename, ovmf_dir, ovmf_code_name, ovmf_vars_name, qemu, machine, cpu) =
+        match target.as_str() {
+            "aarch64-unknown-uefi" => (
+                "bootaa64.efi",
+                Path::new("/usr/share/AAVMF"),
+                "AAVMF_CODE.fd",
+                "AAVMF_VARS.fd",
+                "qemu-system-aarch64",
+                "virt",
+                "cortex-a72",
+            ),
+            "i686-unknown-uefi" => (
+                "bootia32.efi",
+                Path::new("/usr/share/OVMF"),
+                "OVMF32_CODE_4M.secboot.fd",
+                "OVMF32_VARS_4M.fd",
+                "qemu-system-x86_64",
+                "q35",
+                "qemu64",
+            ),
+            "x86_64-unknown-uefi" => (
+                "bootx64.efi",
+                Path::new("/usr/share/OVMF"),
+                "OVMF_CODE_4M.fd",
+                "OVMF_VARS_4M.fd",
+                "qemu-system-x86_64",
+                "q35",
+                "qemu64",
+            ),
+            _ => panic!("unsupported target {target}"),
+        };
+
+    let tmp = std::env::temp_dir();
+    let test_crate = tmp.join("uefi_qemu_test");
+    rfs::copy_dir_all(path("uefi_qemu_test"), &test_crate);
+
+    cargo().args(&["build", "--target", &target]).current_dir(&test_crate).run();
+
+    // Prepare ESP
+    let esp = test_crate.join("esp");
+    let boot = esp.join("efi/boot");
+    rfs::create_dir_all(&boot);
+
+    let src_efi = test_crate.join("target").join(&target).join("debug/uefi_qemu_test.efi");
+    let dst_efi = boot.join(boot_filename);
+    rfs::copy(&src_efi, &dst_efi);
+
+    // Copy OVMF files
+    let code = ovmf_dir.join(ovmf_code_name);
+    let vars_src = ovmf_dir.join(ovmf_vars_name);
+    let vars_dst = tmp.join("vars.fd");
+    rfs::copy(&vars_src, &vars_dst);
+
+    let output = cmd(qemu)
+        .args(["-machine", machine])
+        .args(["-cpu", cpu])
+        .args(["-display", "none"])
+        .args(["-serial", "stdio"])
+        .args(["-drive", &format!("if=pflash,format=raw,readonly=on,file={}", code.display())])
+        .args(["-drive", &format!("if=pflash,format=raw,readonly=off,file={}", vars_dst.display())])
+        .args(["-drive", &format!("format=raw,file=fat:rw:{}", esp.display())])
+        .run()
+        .stdout_utf8();
+
+    assert!(output.contains("Hello World!"), "invalid output for {target}:\n{output}");
+}
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock b/tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.lock
index 8b6a664ad93..8b6a664ad93 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.lock
+++ b/tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.lock
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml b/tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.toml
index 1a8d0d94368..1a8d0d94368 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/Cargo.toml
+++ b/tests/run-make/uefi-qemu/uefi_qemu_test/Cargo.toml
diff --git a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs b/tests/run-make/uefi-qemu/uefi_qemu_test/src/main.rs
index 89e4393cb5c..f8e1212a9f6 100644
--- a/src/ci/docker/host-x86_64/test-various/uefi_qemu_test/src/main.rs
+++ b/tests/run-make/uefi-qemu/uefi_qemu_test/src/main.rs
@@ -15,14 +15,7 @@ fn panic_handler(_info: &panic::PanicInfo) -> ! {
 
 #[export_name = "efi_main"]
 pub extern "C" fn main(_h: Handle, st: *mut SystemTable) -> Status {
-    let s = [
-        0x0048u16, 0x0065u16, 0x006cu16, 0x006cu16, 0x006fu16, // "Hello"
-        0x0020u16, //                                             " "
-        0x0057u16, 0x006fu16, 0x0072u16, 0x006cu16, 0x0064u16, // "World"
-        0x0021u16, //                                             "!"
-        0x000au16, //                                             "\n"
-        0x0000u16, //                                             NUL
-    ];
+    let s = b"Hello World!\n\0".map(|c| u16::from(c));
 
     // Print "Hello World!".
     let r = unsafe { ((*(*st).con_out).output_string)((*st).con_out, s.as_ptr() as *mut Char16) };
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 7ae24db8b5f..814a1e5f691 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -43,12 +43,6 @@ error: malformed `no_sanitize` attribute input
 LL | #[no_sanitize]
    | ^^^^^^^^^^^^^^ help: must be of the form: `#[no_sanitize(address, kcfi, memory, thread)]`
 
-error: malformed `proc_macro` attribute input
-  --> $DIR/malformed-attrs.rs:100:1
-   |
-LL | #[proc_macro = 18]
-   | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
-
 error: malformed `instruction_set` attribute input
   --> $DIR/malformed-attrs.rs:107:1
    |
@@ -67,18 +61,6 @@ error: malformed `coroutine` attribute input
 LL |     #[coroutine = 63] || {}
    |     ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[coroutine]`
 
-error: malformed `proc_macro_attribute` attribute input
-  --> $DIR/malformed-attrs.rs:117:1
-   |
-LL | #[proc_macro_attribute = 19]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
-
-error: malformed `proc_macro_derive` attribute input
-  --> $DIR/malformed-attrs.rs:124:1
-   |
-LL | #[proc_macro_derive]
-   | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
-
 error: malformed `must_not_suspend` attribute input
   --> $DIR/malformed-attrs.rs:133:1
    |
@@ -454,6 +436,24 @@ LL | #[no_implicit_prelude = 23]
    | |                     didn't expect any arguments here
    | help: must be of the form: `#[no_implicit_prelude]`
 
+error[E0565]: malformed `proc_macro` attribute input
+  --> $DIR/malformed-attrs.rs:100:1
+   |
+LL | #[proc_macro = 18]
+   | ^^^^^^^^^^^^^----^
+   | |            |
+   | |            didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro]`
+
+error[E0565]: malformed `proc_macro_attribute` attribute input
+  --> $DIR/malformed-attrs.rs:117:1
+   |
+LL | #[proc_macro_attribute = 19]
+   | ^^^^^^^^^^^^^^^^^^^^^^^----^
+   | |                      |
+   | |                      didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_attribute]`
+
 error[E0539]: malformed `must_use` attribute input
   --> $DIR/malformed-attrs.rs:120:1
    |
@@ -471,6 +471,15 @@ LL - #[must_use = 1]
 LL + #[must_use]
    |
 
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/malformed-attrs.rs:124:1
+   |
+LL | #[proc_macro_derive]
+   | ^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+
 error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
   --> $DIR/malformed-attrs.rs:129:1
    |
diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
index 2f17d9620b4..bd136e64d3f 100644
--- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
+++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.rs
@@ -12,6 +12,7 @@ pub fn b() {}
 #[proc_macro_derive(unsafe(Foo))]
 //~^ ERROR attribute is only usable with crates of the `proc-macro` crate type
 //~| ERROR: expected identifier, found keyword `unsafe`
+//~| ERROR malformed `proc_macro_derive` attribute input
 pub fn c() {}
 
 #[unsafe(proc_macro_attribute)]
diff --git a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
index 25b83a26e17..884e7663c85 100644
--- a/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
+++ b/tests/ui/attributes/unsafe/proc-unsafe-attributes.stderr
@@ -1,11 +1,11 @@
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
@@ -40,7 +40,7 @@ LL | #[proc_macro_derive(r#unsafe(Foo))]
    |                     ++
 
 error: `proc_macro_attribute` is not an unsafe attribute
-  --> $DIR/proc-unsafe-attributes.rs:17:3
+  --> $DIR/proc-unsafe-attributes.rs:18:3
    |
 LL | #[unsafe(proc_macro_attribute)]
    |   ^^^^^^ this is not an unsafe attribute
@@ -48,7 +48,7 @@ LL | #[unsafe(proc_macro_attribute)]
    = note: extraneous unsafe is not allowed in attributes
 
 error: `allow` is not an unsafe attribute
-  --> $DIR/proc-unsafe-attributes.rs:22:3
+  --> $DIR/proc-unsafe-attributes.rs:23:3
    |
 LL | #[unsafe(allow(dead_code))]
    |   ^^^^^^ this is not an unsafe attribute
@@ -56,7 +56,7 @@ LL | #[unsafe(allow(dead_code))]
    = note: extraneous unsafe is not allowed in attributes
 
 error: `allow` is not an unsafe attribute
-  --> $DIR/proc-unsafe-attributes.rs:26:3
+  --> $DIR/proc-unsafe-attributes.rs:27:3
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |   ^^^^^^ this is not an unsafe attribute
@@ -64,7 +64,7 @@ LL | #[unsafe(allow(unsafe(dead_code)))]
    = note: extraneous unsafe is not allowed in attributes
 
 error: expected identifier, found keyword `unsafe`
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^ expected identifier, found keyword
@@ -93,13 +93,13 @@ LL | #[proc_macro_derive(unsafe(Foo))]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/proc-unsafe-attributes.rs:17:1
+  --> $DIR/proc-unsafe-attributes.rs:18:1
    |
 LL | #[unsafe(proc_macro_attribute)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
@@ -107,15 +107,24 @@ LL | #[unsafe(allow(unsafe(dead_code)))]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/proc-unsafe-attributes.rs:12:1
+   |
+LL | #[proc_macro_derive(unsafe(Foo))]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----^^
+   | |                         |
+   | |                         didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
@@ -123,13 +132,14 @@ LL | #[unsafe(allow(unsafe(dead_code)))]
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0452]: malformed lint attribute input
-  --> $DIR/proc-unsafe-attributes.rs:26:16
+  --> $DIR/proc-unsafe-attributes.rs:27:16
    |
 LL | #[unsafe(allow(unsafe(dead_code)))]
    |                ^^^^^^^^^^^^^^^^^ bad attribute argument
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 17 previous errors
+error: aborting due to 18 previous errors
 
-For more information about this error, try `rustc --explain E0452`.
+Some errors have detailed explanations: E0452, E0565.
+For more information about an error, try `rustc --explain E0452`.
diff --git a/tests/ui/c-variadic/same-program-multiple-abis.rs b/tests/ui/c-variadic/same-program-multiple-abis.rs
new file mode 100644
index 00000000000..b21accb999e
--- /dev/null
+++ b/tests/ui/c-variadic/same-program-multiple-abis.rs
@@ -0,0 +1,112 @@
+#![feature(extended_varargs_abi_support)]
+//@ run-pass
+//@ only-x86_64
+
+// Check that multiple c-variadic calling conventions can be used in the same program.
+//
+// Clang and gcc reject defining functions with a non-default calling convention and a variable
+// argument list, so C programs that use multiple c-variadic calling conventions are unlikely
+// to come up. Here we validate that our codegen backends do in fact generate correct code.
+
+extern "sysv64" {
+    fn variadic_sysv64(_: u32, _: ...) -> u32;
+}
+
+extern "win64" {
+    fn variadic_win64(_: u32, _: ...) -> u32;
+}
+
+fn main() {
+    unsafe {
+        assert_eq!(variadic_win64(1, 2, 3), 1 + 2 + 3);
+        assert_eq!(variadic_sysv64(1, 2, 3), 1 + 2 + 3);
+    }
+}
+
+// This assembly was generated using https://godbolt.org/z/dbTGanoh6, and corresponds to the
+// following code compiled for the `x86_64-unknown-linux-gnu` and `x86_64-pc-windows-gnu`
+// targets, respectively:
+//
+// ```rust
+// #![feature(c_variadic)]
+//
+// #[unsafe(no_mangle)]
+// unsafe extern "C" fn variadic(a: u32, mut args: ...) -> u32 {
+//     let b = args.arg::<u32>();
+//     let c = args.arg::<u32>();
+//
+//     a + b + c
+// }
+// ```
+core::arch::global_asm!(
+    r#"
+{variadic_sysv64}:
+        sub     rsp, 88
+        test    al, al
+        je      .LBB0_7
+        movaps  xmmword ptr [rsp - 48], xmm0
+        movaps  xmmword ptr [rsp - 32], xmm1
+        movaps  xmmword ptr [rsp - 16], xmm2
+        movaps  xmmword ptr [rsp], xmm3
+        movaps  xmmword ptr [rsp + 16], xmm4
+        movaps  xmmword ptr [rsp + 32], xmm5
+        movaps  xmmword ptr [rsp + 48], xmm6
+        movaps  xmmword ptr [rsp + 64], xmm7
+.LBB0_7:
+        mov     qword ptr [rsp - 88], rsi
+        mov     qword ptr [rsp - 80], rdx
+        mov     qword ptr [rsp - 72], rcx
+        mov     qword ptr [rsp - 64], r8
+        mov     qword ptr [rsp - 56], r9
+        movabs  rax, 206158430216
+        mov     qword ptr [rsp - 120], rax
+        lea     rax, [rsp + 96]
+        mov     qword ptr [rsp - 112], rax
+        lea     rax, [rsp - 96]
+        mov     qword ptr [rsp - 104], rax
+        mov     edx, 8
+        cmp     rdx, 41
+        jae     .LBB0_1
+        mov     rax, qword ptr [rsp - 104]
+        mov     ecx, 8
+        add     rcx, 8
+        mov     dword ptr [rsp - 120], ecx
+        mov     eax, dword ptr [rax + rdx]
+        cmp     edx, 32
+        ja      .LBB0_2
+        add     rcx, qword ptr [rsp - 104]
+        add     edx, 16
+        mov     dword ptr [rsp - 120], edx
+        add     eax, edi
+        add     eax, dword ptr [rcx]
+        add     rsp, 88
+        ret
+.LBB0_1:
+        mov     rax, qword ptr [rsp - 112]
+        lea     rcx, [rax + 8]
+        mov     qword ptr [rsp - 112], rcx
+        mov     eax, dword ptr [rax]
+.LBB0_2:
+        mov     rcx, qword ptr [rsp - 112]
+        lea     rdx, [rcx + 8]
+        mov     qword ptr [rsp - 112], rdx
+        add     eax, edi
+        add     eax, dword ptr [rcx]
+        add     rsp, 88
+        ret
+
+{variadic_win64}:
+        push    rax
+        mov     qword ptr [rsp + 40], r9
+        mov     qword ptr [rsp + 24], rdx
+        mov     qword ptr [rsp + 32], r8
+        lea     rax, [rsp + 40]
+        mov     qword ptr [rsp], rax
+        lea     eax, [rdx + rcx]
+        add     eax, r8d
+        pop     rcx
+        ret
+    "#,
+    variadic_win64 = sym variadic_win64,
+    variadic_sysv64 = sym variadic_sysv64,
+);
diff --git a/tests/ui/c-variadic/variadic-ffi-1.rs b/tests/ui/c-variadic/variadic-ffi-1.rs
index cd8f2a951ef..2baa00a079a 100644
--- a/tests/ui/c-variadic/variadic-ffi-1.rs
+++ b/tests/ui/c-variadic/variadic-ffi-1.rs
@@ -12,6 +12,11 @@ extern "stdcall" {
     //~^ ERROR: C-variadic functions with the "stdcall" calling convention are not supported
 }
 
+fn baz(f: extern "Rust" fn(usize, ...)) {
+    //~^ ERROR: C-variadic functions with the "Rust" calling convention are not supported
+    f(22, 44);
+}
+
 extern "C" {
     fn foo(f: isize, x: u8, ...);
 }
diff --git a/tests/ui/c-variadic/variadic-ffi-1.stderr b/tests/ui/c-variadic/variadic-ffi-1.stderr
index a49fc0ce126..981b021276d 100644
--- a/tests/ui/c-variadic/variadic-ffi-1.stderr
+++ b/tests/ui/c-variadic/variadic-ffi-1.stderr
@@ -4,14 +4,20 @@ error[E0045]: C-variadic functions with the "stdcall" calling convention are not
 LL |     fn printf(_: *const u8, ...);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
 
+error[E0045]: C-variadic functions with the "Rust" calling convention are not supported
+  --> $DIR/variadic-ffi-1.rs:15:11
+   |
+LL | fn baz(f: extern "Rust" fn(usize, ...)) {
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
+
 error[E0060]: this function takes at least 2 arguments but 0 arguments were supplied
-  --> $DIR/variadic-ffi-1.rs:23:9
+  --> $DIR/variadic-ffi-1.rs:28:9
    |
 LL |         foo();
    |         ^^^-- two arguments of type `isize` and `u8` are missing
    |
 note: function defined here
-  --> $DIR/variadic-ffi-1.rs:16:8
+  --> $DIR/variadic-ffi-1.rs:21:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^ -         -
@@ -21,13 +27,13 @@ LL |         foo(/* isize */, /* u8 */);
    |             +++++++++++++++++++++
 
 error[E0060]: this function takes at least 2 arguments but 1 argument was supplied
-  --> $DIR/variadic-ffi-1.rs:24:9
+  --> $DIR/variadic-ffi-1.rs:29:9
    |
 LL |         foo(1);
    |         ^^^--- argument #2 of type `u8` is missing
    |
 note: function defined here
-  --> $DIR/variadic-ffi-1.rs:16:8
+  --> $DIR/variadic-ffi-1.rs:21:8
    |
 LL |     fn foo(f: isize, x: u8, ...);
    |        ^^^           -
@@ -37,7 +43,7 @@ LL |         foo(1, /* u8 */);
    |              ++++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-1.rs:26:56
+  --> $DIR/variadic-ffi-1.rs:31:56
    |
 LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
    |                -------------------------------------   ^^^ expected non-variadic fn, found variadic function
@@ -48,7 +54,7 @@ LL |         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
                  found fn item `unsafe extern "C" fn(_, _, ...) {foo}`
 
 error[E0308]: mismatched types
-  --> $DIR/variadic-ffi-1.rs:27:54
+  --> $DIR/variadic-ffi-1.rs:32:54
    |
 LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
    |                -----------------------------------   ^^^ expected variadic fn, found non-variadic function
@@ -59,7 +65,7 @@ LL |         let y: extern "C" fn(f: isize, x: u8, ...) = bar;
                  found fn item `extern "C" fn(_, _) {bar}`
 
 error[E0617]: can't pass `f32` to variadic function
-  --> $DIR/variadic-ffi-1.rs:29:19
+  --> $DIR/variadic-ffi-1.rs:34:19
    |
 LL |         foo(1, 2, 3f32);
    |                   ^^^^
@@ -70,7 +76,7 @@ LL |         foo(1, 2, 3f32 as c_double);
    |                        +++++++++++
 
 error[E0617]: can't pass `bool` to variadic function
-  --> $DIR/variadic-ffi-1.rs:30:19
+  --> $DIR/variadic-ffi-1.rs:35:19
    |
 LL |         foo(1, 2, true);
    |                   ^^^^
@@ -81,7 +87,7 @@ LL |         foo(1, 2, true as c_int);
    |                        ++++++++
 
 error[E0617]: can't pass `i8` to variadic function
-  --> $DIR/variadic-ffi-1.rs:31:19
+  --> $DIR/variadic-ffi-1.rs:36:19
    |
 LL |         foo(1, 2, 1i8);
    |                   ^^^
@@ -92,7 +98,7 @@ LL |         foo(1, 2, 1i8 as c_int);
    |                       ++++++++
 
 error[E0617]: can't pass `u8` to variadic function
-  --> $DIR/variadic-ffi-1.rs:32:19
+  --> $DIR/variadic-ffi-1.rs:37:19
    |
 LL |         foo(1, 2, 1u8);
    |                   ^^^
@@ -103,7 +109,7 @@ LL |         foo(1, 2, 1u8 as c_uint);
    |                       +++++++++
 
 error[E0617]: can't pass `i16` to variadic function
-  --> $DIR/variadic-ffi-1.rs:33:19
+  --> $DIR/variadic-ffi-1.rs:38:19
    |
 LL |         foo(1, 2, 1i16);
    |                   ^^^^
@@ -114,7 +120,7 @@ LL |         foo(1, 2, 1i16 as c_int);
    |                        ++++++++
 
 error[E0617]: can't pass `u16` to variadic function
-  --> $DIR/variadic-ffi-1.rs:34:19
+  --> $DIR/variadic-ffi-1.rs:39:19
    |
 LL |         foo(1, 2, 1u16);
    |                   ^^^^
@@ -124,7 +130,7 @@ help: cast the value to `c_uint`
 LL |         foo(1, 2, 1u16 as c_uint);
    |                        +++++++++
 
-error: aborting due to 11 previous errors
+error: aborting due to 12 previous errors
 
 Some errors have detailed explanations: E0045, E0060, E0308, E0617.
 For more information about an error, try `rustc --explain E0045`.
diff --git a/tests/ui/c-variadic/variadic-ffi-2-arm.rs b/tests/ui/c-variadic/variadic-ffi-2-arm.rs
deleted file mode 100644
index 3b0a71007a0..00000000000
--- a/tests/ui/c-variadic/variadic-ffi-2-arm.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-//@ only-arm
-//@ build-pass
-#![feature(extended_varargs_abi_support)]
-
-fn aapcs(f: extern "aapcs" fn(usize, ...)) {
-    f(22, 44);
-}
-
-fn main() {}
diff --git a/tests/ui/c-variadic/variadic-ffi-2.rs b/tests/ui/c-variadic/variadic-ffi-2.rs
deleted file mode 100644
index adfd9bfa279..00000000000
--- a/tests/ui/c-variadic/variadic-ffi-2.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-#![feature(extended_varargs_abi_support)]
-
-fn baz(f: extern "Rust" fn(usize, ...)) {
-    //~^ ERROR: C-variadic functions with the "Rust" calling convention are not supported
-    f(22, 44);
-}
-
-#[cfg(target_arch = "x86_64")]
-fn sysv(f: extern "sysv64" fn(usize, ...)) {
-    f(22, 44);
-}
-#[cfg(target_arch = "x86_64")]
-fn win(f: extern "win64" fn(usize, ...)) {
-    f(22, 44);
-}
-#[cfg(any(
-    target_arch = "arm",
-    target_arch = "aarch64",
-    target_arch = "riscv32",
-    target_arch = "riscv64",
-    target_arch = "x86",
-    target_arch = "x86_64"
-))]
-fn efiapi(f: extern "efiapi" fn(usize, ...)) {
-    f(22, 44);
-}
-
-fn main() {}
diff --git a/tests/ui/c-variadic/variadic-ffi-2.stderr b/tests/ui/c-variadic/variadic-ffi-2.stderr
deleted file mode 100644
index 2ac0a9f5ea2..00000000000
--- a/tests/ui/c-variadic/variadic-ffi-2.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0045]: C-variadic functions with the "Rust" calling convention are not supported
-  --> $DIR/variadic-ffi-2.rs:3:11
-   |
-LL | fn baz(f: extern "Rust" fn(usize, ...)) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0045`.
diff --git a/tests/ui/const-generics/min_const_generics/macro-fail-const.rs b/tests/ui/const-generics/min_const_generics/macro-fail-const.rs
new file mode 100644
index 00000000000..619d6de7ad2
--- /dev/null
+++ b/tests/ui/const-generics/min_const_generics/macro-fail-const.rs
@@ -0,0 +1,23 @@
+trait Marker<const N: usize> {}
+struct Example<const N: usize>;
+impl<const N: usize> Marker<N> for Example<N> {}
+
+fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
+  //~^ ERROR: type provided when a constant was expected
+  //~| ERROR: type provided when a constant was expected
+  Example::<gimme_a_const!(marker)>
+  //~^ ERROR: type provided when a constant was expected
+}
+
+fn main() {
+  let _ok = Example::<{
+    #[macro_export]
+    macro_rules! gimme_a_const {
+      ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
+      //~^ ERROR expected type
+      //~| ERROR expected type
+    }
+    gimme_a_const!(run)
+  }>;
+  let _ok = Example::<{gimme_a_const!(marker)}>;
+}
diff --git a/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr b/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr
new file mode 100644
index 00000000000..2d8cb50834b
--- /dev/null
+++ b/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr
@@ -0,0 +1,51 @@
+error: expected type, found `{`
+  --> $DIR/macro-fail-const.rs:16:27
+   |
+LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
+   |                                 ----------------------
+   |                                 |
+   |                                 this macro call doesn't expand to a type
+   |                                 in this macro invocation
+...
+LL |       ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
+   |                           ^ expected type
+   |
+   = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: expected type, found `{`
+  --> $DIR/macro-fail-const.rs:16:27
+   |
+LL |   Example::<gimme_a_const!(marker)>
+   |             ----------------------
+   |             |
+   |             this macro call doesn't expand to a type
+   |             in this macro invocation
+...
+LL |       ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
+   |                           ^ expected type
+   |
+   = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/macro-fail-const.rs:5:33
+   |
+LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/macro-fail-const.rs:5:33
+   |
+LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0747]: type provided when a constant was expected
+  --> $DIR/macro-fail-const.rs:8:13
+   |
+LL |   Example::<gimme_a_const!(marker)>
+   |             ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.rs b/tests/ui/const-generics/min_const_generics/macro-fail.rs
index 8cfa5293cc2..ada9400b2a3 100644
--- a/tests/ui/const-generics/min_const_generics/macro-fail.rs
+++ b/tests/ui/const-generics/min_const_generics/macro-fail.rs
@@ -12,10 +12,7 @@ trait Marker<const N: usize> {}
 impl<const N: usize> Marker<N> for Example<N> {}
 
 fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
-  //~^ ERROR: type provided when a constant was expected
-  //~| ERROR: type provided when a constant was expected
   Example::<gimme_a_const!(marker)>
-  //~^ ERROR: type provided when a constant was expected
 }
 
 fn from_marker(_: impl Marker<{
@@ -35,9 +32,7 @@ fn main() {
   }>;
 
   let _fail = Example::<external_macro!()>;
-  //~^ ERROR: type provided when a constant
 
   let _fail = Example::<gimme_a_const!()>;
-  //~^ ERROR unexpected end of macro invocation
-  //~| ERROR: type provided when a constant was expected
+  //~^ ERROR: unexpected end of macro invocation
 }
diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr
index 34764982bb0..b1d766cbfb6 100644
--- a/tests/ui/const-generics/min_const_generics/macro-fail.stderr
+++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr
@@ -1,5 +1,5 @@
 error: expected type, found `{`
-  --> $DIR/macro-fail.rs:30:27
+  --> $DIR/macro-fail.rs:27:27
    |
 LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
    |                                 ----------------------
@@ -13,7 +13,7 @@ LL |       ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
    = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: expected type, found `{`
-  --> $DIR/macro-fail.rs:30:27
+  --> $DIR/macro-fail.rs:27:27
    |
 LL |   Example::<gimme_a_const!(marker)>
    |             ----------------------
@@ -41,7 +41,7 @@ LL |   let _fail = Example::<external_macro!()>;
    = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: unexpected end of macro invocation
-  --> $DIR/macro-fail.rs:40:25
+  --> $DIR/macro-fail.rs:36:25
    |
 LL |     macro_rules! gimme_a_const {
    |     -------------------------- when calling this macro
@@ -50,43 +50,10 @@ LL |   let _fail = Example::<gimme_a_const!()>;
    |                         ^^^^^^^^^^^^^^^^ missing tokens in macro arguments
    |
 note: while trying to match meta-variable `$rusty:ident`
-  --> $DIR/macro-fail.rs:30:8
+  --> $DIR/macro-fail.rs:27:8
    |
 LL |       ($rusty: ident) => {{ let $rusty = 3; *&$rusty }}
    |        ^^^^^^^^^^^^^
 
-error[E0747]: type provided when a constant was expected
-  --> $DIR/macro-fail.rs:14:33
-   |
-LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0747]: type provided when a constant was expected
-  --> $DIR/macro-fail.rs:14:33
-   |
-LL | fn make_marker() -> impl Marker<gimme_a_const!(marker)> {
-   |                                 ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0747]: type provided when a constant was expected
-  --> $DIR/macro-fail.rs:17:13
-   |
-LL |   Example::<gimme_a_const!(marker)>
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0747]: type provided when a constant was expected
-  --> $DIR/macro-fail.rs:37:25
-   |
-LL |   let _fail = Example::<external_macro!()>;
-   |                         ^^^^^^^^^^^^^^^^^
-
-error[E0747]: type provided when a constant was expected
-  --> $DIR/macro-fail.rs:40:25
-   |
-LL |   let _fail = Example::<gimme_a_const!()>;
-   |                         ^^^^^^^^^^^^^^^^
-
-error: aborting due to 9 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0747`.
diff --git a/tests/ui/consts/const-unsized.rs b/tests/ui/consts/const-unsized.rs
index e8af3323ceb..4140563fa40 100644
--- a/tests/ui/consts/const-unsized.rs
+++ b/tests/ui/consts/const-unsized.rs
@@ -10,14 +10,10 @@ const CONST_FOO: str = *"foo";
 
 static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
 //~^ ERROR the size for values of type
-//~| ERROR cannot move out of a shared reference
 
 static STATIC_BAR: str = *"bar";
 //~^ ERROR the size for values of type
-//~| ERROR cannot move out of a shared reference
 
 fn main() {
     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-    //~^ ERROR: cannot move a value of type `str`
-    //~| ERROR: cannot move a value of type `dyn Debug + Sync`
 }
diff --git a/tests/ui/consts/const-unsized.stderr b/tests/ui/consts/const-unsized.stderr
index c92fbc17f9c..a37a6df71f8 100644
--- a/tests/ui/consts/const-unsized.stderr
+++ b/tests/ui/consts/const-unsized.stderr
@@ -26,7 +26,7 @@ LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
    = note: statics and constants must have a statically known size
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/const-unsized.rs:15:1
+  --> $DIR/const-unsized.rs:14:1
    |
 LL | static STATIC_BAR: str = *"bar";
    | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -46,31 +46,7 @@ error[E0507]: cannot move out of a shared reference
 LL | const CONST_FOO: str = *"foo";
    |                        ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
 
-error[E0507]: cannot move out of a shared reference
-  --> $DIR/const-unsized.rs:11:37
-   |
-LL | static STATIC_1: dyn Debug + Sync = *(&1 as &(dyn Debug + Sync));
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `dyn Debug + Sync`, which does not implement the `Copy` trait
-
-error[E0507]: cannot move out of a shared reference
-  --> $DIR/const-unsized.rs:15:26
-   |
-LL | static STATIC_BAR: str = *"bar";
-   |                          ^^^^^^ move occurs because value has type `str`, which does not implement the `Copy` trait
-
-error[E0161]: cannot move a value of type `dyn Debug + Sync`
-  --> $DIR/const-unsized.rs:20:38
-   |
-LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-   |                                      ^^^^^^^ the size of `dyn Debug + Sync` cannot be statically determined
-
-error[E0161]: cannot move a value of type `str`
-  --> $DIR/const-unsized.rs:20:48
-   |
-LL |     println!("{:?} {:?} {:?} {:?}", &CONST_0, &CONST_FOO, &STATIC_1, &STATIC_BAR);
-   |                                                ^^^^^^^^^ the size of `str` cannot be statically determined
-
-error: aborting due to 10 previous errors
+error: aborting due to 6 previous errors
 
-Some errors have detailed explanations: E0161, E0277, E0507.
-For more information about an error, try `rustc --explain E0161`.
+Some errors have detailed explanations: E0277, E0507.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/coroutine/layout-error.rs b/tests/ui/coroutine/layout-error.rs
index 6cf32134025..7f6714542c1 100644
--- a/tests/ui/coroutine/layout-error.rs
+++ b/tests/ui/coroutine/layout-error.rs
@@ -17,6 +17,7 @@ impl<F: Future> Task<F> {
 }
 
 pub type F = impl Future;
+
 #[define_opaque(F)]
 fn foo()
 where
diff --git a/tests/ui/coroutine/layout-error.stderr b/tests/ui/coroutine/layout-error.stderr
index 91e35216435..f3b3843de89 100644
--- a/tests/ui/coroutine/layout-error.stderr
+++ b/tests/ui/coroutine/layout-error.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `Foo` in this scope
-  --> $DIR/layout-error.rs:26:17
+  --> $DIR/layout-error.rs:27:17
    |
 LL |         let a = Foo;
    |                 ^^^ not found in this scope
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.rs b/tests/ui/dyn-compatibility/taint-const-eval.rs
index a5c01e1791e..3d1b3b8fe61 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.rs
+++ b/tests/ui/dyn-compatibility/taint-const-eval.rs
@@ -6,6 +6,5 @@ trait Qux {
 
 static FOO: &(dyn Qux + Sync) = "desc";
 //~^ ERROR the trait `Qux` is not dyn compatible
-//~| ERROR the trait `Qux` is not dyn compatible
 
 fn main() {}
diff --git a/tests/ui/dyn-compatibility/taint-const-eval.stderr b/tests/ui/dyn-compatibility/taint-const-eval.stderr
index 585c1f012c7..e4be9870fdc 100644
--- a/tests/ui/dyn-compatibility/taint-const-eval.stderr
+++ b/tests/ui/dyn-compatibility/taint-const-eval.stderr
@@ -21,30 +21,6 @@ help: alternatively, consider constraining `bar` so it does not apply to trait o
 LL |     fn bar() where Self: Sized;
    |              +++++++++++++++++
 
-error[E0038]: the trait `Qux` is not dyn compatible
-  --> $DIR/taint-const-eval.rs:7:15
-   |
-LL | static FOO: &(dyn Qux + Sync) = "desc";
-   |               ^^^^^^^^^^^^^^ `Qux` is not dyn compatible
-   |
-note: for a trait to be dyn compatible it needs to allow building a vtable
-      for more information, visit <https://doc.rust-lang.org/reference/items/traits.html#dyn-compatibility>
-  --> $DIR/taint-const-eval.rs:4:8
-   |
-LL | trait Qux {
-   |       --- this trait is not dyn compatible...
-LL |     fn bar();
-   |        ^^^ ...because associated function `bar` has no `self` parameter
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider turning `bar` into a method by giving it a `&self` argument
-   |
-LL |     fn bar(&self);
-   |            +++++
-help: alternatively, consider constraining `bar` so it does not apply to trait objects
-   |
-LL |     fn bar() where Self: Sized;
-   |              +++++++++++++++++
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
index f8d2755b9d7..df473946317 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.rs
@@ -26,7 +26,7 @@ pub fn check_async() {
     module::async(); //~ ERROR expected identifier, found keyword `async`
     module::r#async(); // OK
 
-    let _recovery_witness: () = 0; //~ ERROR mismatched types
+    let _recovery_witness: () = 0; // not emitted because of the macro parsing error
 }
 
 //~? ERROR macro expansion ends with an incomplete expression
diff --git a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
index 34f5c7d3084..4d69df9fff8 100644
--- a/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2015-parsing.stderr
@@ -61,14 +61,5 @@ error: macro expansion ends with an incomplete expression: expected one of `move
 LL |     if passes_tt!(async) == 1 {}
    |                        ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
-error[E0308]: mismatched types
-  --> $DIR/edition-keywords-2018-2015-parsing.rs:29:33
-   |
-LL |     let _recovery_witness: () = 0;
-   |                            --   ^ expected `()`, found integer
-   |                            |
-   |                            expected due to this
-
-error: aborting due to 7 previous errors
+error: aborting due to 6 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
index f4438472a0e..34aaf16b4ae 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.rs
@@ -36,8 +36,6 @@ pub fn check_async() {
     if local_passes_tt!(r#async) == 1 {} // OK
     module::async(); //~ ERROR expected identifier, found keyword `async`
     module::r#async(); // OK
-
-    let _recovery_witness: () = 0; //~ ERROR mismatched types
 }
 
 //~? ERROR macro expansion ends with an incomplete expression
diff --git a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
index dd3f4938c74..753dac605a3 100644
--- a/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
+++ b/tests/ui/editions/edition-keywords-2018-2018-parsing.stderr
@@ -73,14 +73,5 @@ error: macro expansion ends with an incomplete expression: expected one of `move
 LL |     if local_passes_tt!(async) == 1 {}
    |                              ^ expected one of `move`, `use`, `{`, `|`, or `||`
 
-error[E0308]: mismatched types
-  --> $DIR/edition-keywords-2018-2018-parsing.rs:40:33
-   |
-LL |     let _recovery_witness: () = 0;
-   |                            --   ^ expected `()`, found integer
-   |                            |
-   |                            expected due to this
-
-error: aborting due to 9 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.rs b/tests/ui/extern/issue-36122-accessing-externed-dst.rs
index 9fb7780e3d7..5f886ff5737 100644
--- a/tests/ui/extern/issue-36122-accessing-externed-dst.rs
+++ b/tests/ui/extern/issue-36122-accessing-externed-dst.rs
@@ -3,5 +3,4 @@ fn main() {
         static symbol: [usize]; //~ ERROR: the size for values of type
     }
     println!("{}", symbol[0]);
-    //~^ ERROR: extern static is unsafe
 }
diff --git a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
index 8007c3f13e5..c617cf4e61b 100644
--- a/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
+++ b/tests/ui/extern/issue-36122-accessing-externed-dst.stderr
@@ -7,15 +7,6 @@ LL |         static symbol: [usize];
    = help: the trait `Sized` is not implemented for `[usize]`
    = note: statics and constants must have a statically known size
 
-error[E0133]: use of extern static is unsafe and requires unsafe function or block
-  --> $DIR/issue-36122-accessing-externed-dst.rs:5:20
-   |
-LL |     println!("{}", symbol[0]);
-   |                    ^^^^^^ use of extern static
-   |
-   = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0133, E0277.
-For more information about an error, try `rustc --explain E0133`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index 9740eaaf1e9..b93cb2ea006 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -57,7 +57,7 @@
 // see gated-link-args.rs
 // see issue-43106-gating-of-macro_escape.rs for crate-level; but non crate-level is below at "2700"
 // (cannot easily test gating of crate-level #[no_std]; but non crate-level is below at "2600")
-#![proc_macro_derive()] //~ WARN `#[proc_macro_derive]` only has an effect
+#![proc_macro_derive(Test)] //~ WARN `#[proc_macro_derive]` only has an effect
 #![doc = "2400"]
 #![cold] //~ WARN attribute should be applied to a function
 //~^ WARN this was previously accepted
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 9016ca1efa7..8bac1f6155e 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -367,12 +367,6 @@ warning: `#[should_panic]` only has an effect on functions
 LL | #![should_panic]
    | ^^^^^^^^^^^^^^^^
 
-warning: `#[proc_macro_derive]` only has an effect on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
-   |
-LL | #![proc_macro_derive()]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
 warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:64:1
    |
@@ -409,6 +403,12 @@ warning: `#[must_use]` has no effect when applied to a module
 LL | #![must_use]
    | ^^^^^^^^^^^^
 
+warning: `#[proc_macro_derive]` only has an effect on functions
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:60:1
+   |
+LL | #![proc_macro_derive(Test)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 warning: attribute should be applied to a function definition
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:62:1
    |
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
index a94ffd602ef..392880e1b3b 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.rs
@@ -7,27 +7,27 @@
 // signal errors, making it incompatible with the "warnings only"
 // nature of issue-43106-gating-of-builtin-attrs.rs
 
-#[proc_macro_derive()]
+#[proc_macro_derive(Test)]
 //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
 mod proc_macro_derive1 {
-    mod inner { #![proc_macro_derive()] }
+    mod inner { #![proc_macro_derive(Test)] }
     // (no error issued here if there was one on outer module)
 }
 
 mod proc_macro_derive2 {
-    mod inner { #![proc_macro_derive()] }
+    mod inner { #![proc_macro_derive(Test)] }
     //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
 
-    #[proc_macro_derive()] fn f() { }
+    #[proc_macro_derive(Test)] fn f() { }
     //~^ ERROR the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro`
 
-    #[proc_macro_derive()] struct S;
+    #[proc_macro_derive(Test)] struct S;
     //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
 
-    #[proc_macro_derive()] type T = S;
+    #[proc_macro_derive(Test)] type T = S;
     //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
 
-    #[proc_macro_derive()] impl S { }
+    #[proc_macro_derive(Test)] impl S { }
     //~^ ERROR the `#[proc_macro_derive]` attribute may only be used on bare functions
 }
 
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
index e202b472d9c..537032d777f 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-proc_macro_derive.stderr
@@ -1,38 +1,38 @@
 error: the `#[proc_macro_derive]` attribute may only be used on bare functions
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:10:1
    |
-LL | #[proc_macro_derive()]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+LL | #[proc_macro_derive(Test)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute may only be used on bare functions
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:18:17
    |
-LL |     mod inner { #![proc_macro_derive()] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^
+LL |     mod inner { #![proc_macro_derive(Test)] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:21:5
    |
-LL |     #[proc_macro_derive()] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[proc_macro_derive(Test)] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute may only be used on bare functions
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:24:5
    |
-LL |     #[proc_macro_derive()] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[proc_macro_derive(Test)] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute may only be used on bare functions
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:27:5
    |
-LL |     #[proc_macro_derive()] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[proc_macro_derive(Test)] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute may only be used on bare functions
   --> $DIR/issue-43106-gating-of-proc_macro_derive.rs:30:5
    |
-LL |     #[proc_macro_derive()] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #[proc_macro_derive(Test)] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/layout/issue-84108.rs b/tests/ui/layout/issue-84108.rs
index 974d5310f6b..33884617acb 100644
--- a/tests/ui/layout/issue-84108.rs
+++ b/tests/ui/layout/issue-84108.rs
@@ -14,5 +14,3 @@ const BAR: (&Path, [u8], usize) = ("hello", [], 42);
 
 static BAZ: ([u8], usize) = ([], 0);
 //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time
-//~| ERROR the size for values of type `[u8]` cannot be known at compilation time
-//~| ERROR mismatched types
diff --git a/tests/ui/layout/issue-84108.stderr b/tests/ui/layout/issue-84108.stderr
index e296abfc3b5..62a6ae341fa 100644
--- a/tests/ui/layout/issue-84108.stderr
+++ b/tests/ui/layout/issue-84108.stderr
@@ -57,26 +57,7 @@ LL | const BAR: (&Path, [u8], usize) = ("hello", [], 42);
    = note: expected slice `[u8]`
               found array `[_; 0]`
 
-error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
-  --> $DIR/issue-84108.rs:15:13
-   |
-LL | static BAZ: ([u8], usize) = ([], 0);
-   |             ^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `[u8]`
-   = note: only the last element of a tuple may have a dynamically sized type
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0308]: mismatched types
-  --> $DIR/issue-84108.rs:15:30
-   |
-LL | static BAZ: ([u8], usize) = ([], 0);
-   |                              ^^ expected `[u8]`, found `[_; 0]`
-   |
-   = note: expected slice `[u8]`
-              found array `[_; 0]`
-
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0412.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/macros/trace-macro.rs b/tests/ui/macros/trace-macro.rs
index ecc6aabe8ca..a85f8f42e7a 100644
--- a/tests/ui/macros/trace-macro.rs
+++ b/tests/ui/macros/trace-macro.rs
@@ -3,4 +3,7 @@
 
 fn main() {
     println!("Hello, World!");
+    //~^ NOTE trace_macro
+    //~| NOTE expanding `println!
+    //~| NOTE to `{
 }
diff --git a/tests/ui/mir/static-by-value-dyn.rs b/tests/ui/mir/static-by-value-dyn.rs
new file mode 100644
index 00000000000..f1154ef0860
--- /dev/null
+++ b/tests/ui/mir/static-by-value-dyn.rs
@@ -0,0 +1,14 @@
+//! Regression test for #121176
+//! KnownPanicsLint used to assert ABI compatibility in the interpreter,
+//! which ICEs with unsized statics.
+//@ needs-rustc-debug-assertions
+
+use std::fmt::Debug;
+
+static STATIC_1: dyn Debug + Sync = *();
+//~^ ERROR the size for values of type `(dyn Debug + Sync + 'static)` cannot be known
+//~| ERROR type `()` cannot be dereferenced
+
+fn main() {
+    println!("{:?}", &STATIC_1);
+}
diff --git a/tests/ui/mir/static-by-value-dyn.stderr b/tests/ui/mir/static-by-value-dyn.stderr
new file mode 100644
index 00000000000..25ed81326f4
--- /dev/null
+++ b/tests/ui/mir/static-by-value-dyn.stderr
@@ -0,0 +1,19 @@
+error[E0277]: the size for values of type `(dyn Debug + Sync + 'static)` cannot be known at compilation time
+  --> $DIR/static-by-value-dyn.rs:8:1
+   |
+LL | static STATIC_1: dyn Debug + Sync = *();
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `(dyn Debug + Sync + 'static)`
+   = note: statics and constants must have a statically known size
+
+error[E0614]: type `()` cannot be dereferenced
+  --> $DIR/static-by-value-dyn.rs:8:37
+   |
+LL | static STATIC_1: dyn Debug + Sync = *();
+   |                                     ^^^ can't be dereferenced
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0277, E0614.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/mir/static-by-value-slice.rs b/tests/ui/mir/static-by-value-slice.rs
new file mode 100644
index 00000000000..af98be6a74d
--- /dev/null
+++ b/tests/ui/mir/static-by-value-slice.rs
@@ -0,0 +1,10 @@
+//! Regression test for #140332
+//! KnownPanicsLint used to assert ABI compatibility in the interpreter,
+//! which ICEs with unsized statics.
+
+static mut S: [i8] = ["Some thing"; 1];
+//~^ ERROR the size for values of type `[i8]` cannot be known
+
+fn main() {
+    assert_eq!(S, [0; 1]);
+}
diff --git a/tests/ui/mir/static-by-value-slice.stderr b/tests/ui/mir/static-by-value-slice.stderr
new file mode 100644
index 00000000000..2d0592943d0
--- /dev/null
+++ b/tests/ui/mir/static-by-value-slice.stderr
@@ -0,0 +1,12 @@
+error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
+  --> $DIR/static-by-value-slice.rs:5:1
+   |
+LL | static mut S: [i8] = ["Some thing"; 1];
+   | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i8]`
+   = note: statics and constants must have a statically known size
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/mir/static-by-value-str.rs b/tests/ui/mir/static-by-value-str.rs
new file mode 100644
index 00000000000..88b72f90819
--- /dev/null
+++ b/tests/ui/mir/static-by-value-str.rs
@@ -0,0 +1,15 @@
+//! Regression test for #139872
+//! KnownPanicsLint used to assert ABI compatibility in the interpreter,
+//! which ICEs with unsized statics.
+
+enum E {
+    V16(u16),
+    V32(u32),
+}
+
+static C: (E, u16, str) = (E::V16(0xDEAD), 0x600D, 0xBAD);
+//~^ ERROR the size for values of type `str` cannot be known
+
+pub fn main() {
+    let (_, n, _) = C;
+}
diff --git a/tests/ui/mir/static-by-value-str.stderr b/tests/ui/mir/static-by-value-str.stderr
new file mode 100644
index 00000000000..6e046e00551
--- /dev/null
+++ b/tests/ui/mir/static-by-value-str.stderr
@@ -0,0 +1,13 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/static-by-value-str.rs:10:1
+   |
+LL | static C: (E, u16, str) = (E::V16(0xDEAD), 0x600D, 0xBAD);
+   | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `(E, u16, str)`, the trait `Sized` is not implemented for `str`
+   = note: required because it appears within the type `(E, u16, str)`
+   = note: statics and constants must have a statically known size
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/mir/unsized-extern-static.rs b/tests/ui/mir/unsized-extern-static.rs
new file mode 100644
index 00000000000..386842556ba
--- /dev/null
+++ b/tests/ui/mir/unsized-extern-static.rs
@@ -0,0 +1,13 @@
+//! Regression test for #129109
+//! MIR building used to produce erroneous constants when referring to statics of unsized type.
+//@ compile-flags: -Zmir-enable-passes=+GVN -Zvalidate-mir
+
+extern "C" {
+    pub static mut symbol: [i8];
+    //~^ ERROR the size for values of type `[i8]`
+}
+
+fn main() {
+    println!("C", unsafe { &symbol });
+    //~^ ERROR argument never used
+}
diff --git a/tests/ui/mir/unsized-extern-static.stderr b/tests/ui/mir/unsized-extern-static.stderr
new file mode 100644
index 00000000000..93aed3549d7
--- /dev/null
+++ b/tests/ui/mir/unsized-extern-static.stderr
@@ -0,0 +1,20 @@
+error: argument never used
+  --> $DIR/unsized-extern-static.rs:11:19
+   |
+LL |     println!("C", unsafe { &symbol });
+   |              ---  ^^^^^^^^^^^^^^^^^^ argument never used
+   |              |
+   |              formatting specifier missing
+
+error[E0277]: the size for values of type `[i8]` cannot be known at compilation time
+  --> $DIR/unsized-extern-static.rs:6:5
+   |
+LL |     pub static mut symbol: [i8];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i8]`
+   = note: statics and constants must have a statically known size
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/offset-of/offset-of-tuple-field.rs b/tests/ui/offset-of/offset-of-tuple-field.rs
new file mode 100644
index 00000000000..02d41f91a25
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-tuple-field.rs
@@ -0,0 +1,22 @@
+#![feature(builtin_syntax)]
+
+use std::mem::offset_of;
+
+fn main() {
+    offset_of!((u8, u8), _0); //~ ERROR no field `_0`
+    offset_of!((u8, u8), 01); //~ ERROR no field `01`
+    offset_of!((u8, u8), 1e2); //~ ERROR no field `1e2`
+    offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_`
+    //~| ERROR suffixes on a tuple index
+
+    builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2`
+    builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0`
+    builtin # offset_of((u8, u8), 01); //~ ERROR no field `01`
+    builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_`
+    //~| ERROR suffixes on a tuple index
+
+    offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2`
+    offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2`
+    offset_of!(((u8, u16), (u32, u16, u8)), 1.2);
+    offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); //~ ERROR no field `0`
+}
diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr
new file mode 100644
index 00000000000..4da0d851650
--- /dev/null
+++ b/tests/ui/offset-of/offset-of-tuple-field.stderr
@@ -0,0 +1,81 @@
+error: suffixes on a tuple index are invalid
+  --> $DIR/offset-of-tuple-field.rs:15:35
+   |
+LL |     builtin # offset_of((u8, u8), 1_u8);
+   |                                   ^^^^ invalid suffix `u8`
+
+error: suffixes on a tuple index are invalid
+  --> $DIR/offset-of-tuple-field.rs:9:26
+   |
+LL |     offset_of!((u8, u8), 1_u8);
+   |                          ^^^^ invalid suffix `u8`
+
+error[E0609]: no field `_0` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:6:26
+   |
+LL |     offset_of!((u8, u8), _0);
+   |                          ^^
+
+error[E0609]: no field `01` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:7:26
+   |
+LL |     offset_of!((u8, u8), 01);
+   |                          ^^
+
+error[E0609]: no field `1e2` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:8:26
+   |
+LL |     offset_of!((u8, u8), 1e2);
+   |                          ^^^
+
+error[E0609]: no field `1_` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:9:26
+   |
+LL |     offset_of!((u8, u8), 1_u8);
+   |                          ^^^^
+
+error[E0609]: no field `1e2` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:12:35
+   |
+LL |     builtin # offset_of((u8, u8), 1e2);
+   |                                   ^^^
+
+error[E0609]: no field `_0` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:13:35
+   |
+LL |     builtin # offset_of((u8, u8), _0);
+   |                                   ^^
+
+error[E0609]: no field `01` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:14:35
+   |
+LL |     builtin # offset_of((u8, u8), 01);
+   |                                   ^^
+
+error[E0609]: no field `1_` on type `(u8, u8)`
+  --> $DIR/offset-of-tuple-field.rs:15:35
+   |
+LL |     builtin # offset_of((u8, u8), 1_u8);
+   |                                   ^^^^
+
+error[E0609]: no field `2` on type `(u8, u16)`
+  --> $DIR/offset-of-tuple-field.rs:18:47
+   |
+LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.2);
+   |                                               ^
+
+error[E0609]: no field `1e2` on type `(u8, u16)`
+  --> $DIR/offset-of-tuple-field.rs:19:47
+   |
+LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2);
+   |                                               ^^^
+
+error[E0609]: no field `0` on type `u8`
+  --> $DIR/offset-of-tuple-field.rs:21:49
+   |
+LL |     offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0);
+   |                                                 ^
+
+error: aborting due to 13 previous errors
+
+For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs
index e8447249441..ddbaee97b1b 100644
--- a/tests/ui/offset-of/offset-of-tuple.rs
+++ b/tests/ui/offset-of/offset-of-tuple.rs
@@ -3,20 +3,10 @@
 use std::mem::offset_of;
 
 fn main() {
-    offset_of!((u8, u8), _0); //~ ERROR no field `_0`
-    offset_of!((u8, u8), 01); //~ ERROR no field `01`
-    offset_of!((u8, u8), 1e2); //~ ERROR no field `1e2`
-    offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_`
-    //~| ERROR suffixes on a tuple index
     offset_of!((u8, u8), +1); //~ ERROR no rules expected
     offset_of!((u8, u8), -1); //~ ERROR offset_of expects dot-separated field and variant names
     offset_of!((u8, u8), 1.); //~ ERROR offset_of expects dot-separated field and variant names
     offset_of!((u8, u8), 1 .); //~ ERROR unexpected token: `)`
-    builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2`
-    builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0`
-    builtin # offset_of((u8, u8), 01); //~ ERROR no field `01`
-    builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_`
-    //~| ERROR suffixes on a tuple index
     // We need to put these into curly braces, otherwise only one of the
     // errors will be emitted and the others suppressed.
     { builtin # offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported
@@ -27,11 +17,6 @@ fn main() {
 type ComplexTup = (((u8, u8), u8), u8);
 
 fn nested() {
-    offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2`
-    offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2); //~ ERROR no field `1e2`
-    offset_of!(((u8, u16), (u32, u16, u8)), 1.2);
-    offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); //~ ERROR no field `0`
-
     // All combinations of spaces (this sends different tokens to the parser)
     offset_of!(ComplexTup, 0.0.1.); //~ ERROR unexpected token: `)`
     offset_of!(ComplexTup, 0 .0.1.); //~ ERROR unexpected token: `)`
diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr
index 38ce49c9179..33dea9918ca 100644
--- a/tests/ui/offset-of/offset-of-tuple.stderr
+++ b/tests/ui/offset-of/offset-of-tuple.stderr
@@ -1,11 +1,5 @@
-error: suffixes on a tuple index are invalid
-  --> $DIR/offset-of-tuple.rs:18:35
-   |
-LL |     builtin # offset_of((u8, u8), 1_u8);
-   |                                   ^^^^ invalid suffix `u8`
-
 error: leading `+` is not supported
-  --> $DIR/offset-of-tuple.rs:22:37
+  --> $DIR/offset-of-tuple.rs:12:37
    |
 LL |     { builtin # offset_of((u8, u8), +1) };
    |                                     ^ unexpected `+`
@@ -17,67 +11,61 @@ LL +     { builtin # offset_of((u8, u8), 1) };
    |
 
 error: offset_of expects dot-separated field and variant names
-  --> $DIR/offset-of-tuple.rs:23:38
+  --> $DIR/offset-of-tuple.rs:13:38
    |
 LL |     { builtin # offset_of((u8, u8), 1.) };
    |                                      ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:24:40
+  --> $DIR/offset-of-tuple.rs:14:40
    |
 LL |     { builtin # offset_of((u8, u8), 1 .) };
    |                                        ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:47:45
+  --> $DIR/offset-of-tuple.rs:32:45
    |
 LL |     { builtin # offset_of(ComplexTup, 0.0.1.) };
    |                                             ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:48:46
+  --> $DIR/offset-of-tuple.rs:33:46
    |
 LL |     { builtin # offset_of(ComplexTup, 0 .0.1.) };
    |                                              ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:49:47
+  --> $DIR/offset-of-tuple.rs:34:47
    |
 LL |     { builtin # offset_of(ComplexTup, 0 . 0.1.) };
    |                                               ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:50:46
+  --> $DIR/offset-of-tuple.rs:35:46
    |
 LL |     { builtin # offset_of(ComplexTup, 0. 0.1.) };
    |                                              ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:51:46
+  --> $DIR/offset-of-tuple.rs:36:46
    |
 LL |     { builtin # offset_of(ComplexTup, 0.0 .1.) };
    |                                              ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:52:47
+  --> $DIR/offset-of-tuple.rs:37:47
    |
 LL |     { builtin # offset_of(ComplexTup, 0.0 . 1.) };
    |                                               ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:53:46
+  --> $DIR/offset-of-tuple.rs:38:46
    |
 LL |     { builtin # offset_of(ComplexTup, 0.0. 1.) };
    |                                              ^
 
-error: suffixes on a tuple index are invalid
-  --> $DIR/offset-of-tuple.rs:9:26
-   |
-LL |     offset_of!((u8, u8), 1_u8);
-   |                          ^^^^ invalid suffix `u8`
-
 error: no rules expected `+`
-  --> $DIR/offset-of-tuple.rs:11:26
+  --> $DIR/offset-of-tuple.rs:6:26
    |
 LL |     offset_of!((u8, u8), +1);
    |                          ^ no rules expected this token in macro call
@@ -86,131 +74,64 @@ note: while trying to match meta-variable `$fields:expr`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
 
 error: offset_of expects dot-separated field and variant names
-  --> $DIR/offset-of-tuple.rs:12:26
+  --> $DIR/offset-of-tuple.rs:7:26
    |
 LL |     offset_of!((u8, u8), -1);
    |                          ^^
 
 error: offset_of expects dot-separated field and variant names
-  --> $DIR/offset-of-tuple.rs:13:27
+  --> $DIR/offset-of-tuple.rs:8:27
    |
 LL |     offset_of!((u8, u8), 1.);
    |                           ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:14:29
+  --> $DIR/offset-of-tuple.rs:9:29
    |
 LL |     offset_of!((u8, u8), 1 .);
    |                             ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:36:34
+  --> $DIR/offset-of-tuple.rs:21:34
    |
 LL |     offset_of!(ComplexTup, 0.0.1.);
    |                                  ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:37:35
+  --> $DIR/offset-of-tuple.rs:22:35
    |
 LL |     offset_of!(ComplexTup, 0 .0.1.);
    |                                   ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:38:36
+  --> $DIR/offset-of-tuple.rs:23:36
    |
 LL |     offset_of!(ComplexTup, 0 . 0.1.);
    |                                    ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:39:35
+  --> $DIR/offset-of-tuple.rs:24:35
    |
 LL |     offset_of!(ComplexTup, 0. 0.1.);
    |                                   ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:40:35
+  --> $DIR/offset-of-tuple.rs:25:35
    |
 LL |     offset_of!(ComplexTup, 0.0 .1.);
    |                                   ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:41:36
+  --> $DIR/offset-of-tuple.rs:26:36
    |
 LL |     offset_of!(ComplexTup, 0.0 . 1.);
    |                                    ^
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-tuple.rs:42:35
+  --> $DIR/offset-of-tuple.rs:27:35
    |
 LL |     offset_of!(ComplexTup, 0.0. 1.);
    |                                   ^
 
-error[E0609]: no field `_0` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:6:26
-   |
-LL |     offset_of!((u8, u8), _0);
-   |                          ^^
-
-error[E0609]: no field `01` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:7:26
-   |
-LL |     offset_of!((u8, u8), 01);
-   |                          ^^
-
-error[E0609]: no field `1e2` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:8:26
-   |
-LL |     offset_of!((u8, u8), 1e2);
-   |                          ^^^
-
-error[E0609]: no field `1_` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:9:26
-   |
-LL |     offset_of!((u8, u8), 1_u8);
-   |                          ^^^^
-
-error[E0609]: no field `1e2` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:15:35
-   |
-LL |     builtin # offset_of((u8, u8), 1e2);
-   |                                   ^^^
-
-error[E0609]: no field `_0` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:16:35
-   |
-LL |     builtin # offset_of((u8, u8), _0);
-   |                                   ^^
-
-error[E0609]: no field `01` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:17:35
-   |
-LL |     builtin # offset_of((u8, u8), 01);
-   |                                   ^^
-
-error[E0609]: no field `1_` on type `(u8, u8)`
-  --> $DIR/offset-of-tuple.rs:18:35
-   |
-LL |     builtin # offset_of((u8, u8), 1_u8);
-   |                                   ^^^^
-
-error[E0609]: no field `2` on type `(u8, u16)`
-  --> $DIR/offset-of-tuple.rs:30:47
-   |
-LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.2);
-   |                                               ^
-
-error[E0609]: no field `1e2` on type `(u8, u16)`
-  --> $DIR/offset-of-tuple.rs:31:47
-   |
-LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2);
-   |                                               ^^^
-
-error[E0609]: no field `0` on type `u8`
-  --> $DIR/offset-of-tuple.rs:33:49
-   |
-LL |     offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0);
-   |                                                 ^
-
-error: aborting due to 34 previous errors
+error: aborting due to 21 previous errors
 
-For more information about this error, try `rustc --explain E0609`.
diff --git a/tests/ui/proc-macro/attribute.rs b/tests/ui/proc-macro/attribute.rs
index 30ed8ff8247..988cdcd0403 100644
--- a/tests/ui/proc-macro/attribute.rs
+++ b/tests/ui/proc-macro/attribute.rs
@@ -6,68 +6,85 @@
 extern crate proc_macro;
 use proc_macro::*;
 
-#[proc_macro_derive] //~ ERROR malformed `proc_macro_derive` attribute
+#[proc_macro_derive]
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected this to be a list
 pub fn foo1(input: TokenStream) -> TokenStream { input }
 
-#[proc_macro_derive = ""] //~ ERROR malformed `proc_macro_derive` attribute
+#[proc_macro_derive = ""]
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected this to be a list
 pub fn foo2(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d3, a, b)]
-//~^ ERROR attribute must have either one or two arguments
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE the only valid argument here is `attributes`
 pub fn foo3(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d4, attributes(a), b)]
-//~^ ERROR attribute must have either one or two arguments
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect any arguments here
 pub fn foo4(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive("a")]
-//~^ ERROR: not a meta item
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect a literal here
 pub fn foo5(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d6 = "")]
-//~^ ERROR: must only be one word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect any arguments here
 pub fn foo6(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(m::d7)]
-//~^ ERROR: must only be one word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected a valid identifier here
 pub fn foo7(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d8(a))]
-//~^ ERROR: must only be one word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect any arguments here
 pub fn foo8(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(self)]
-//~^ ERROR: `self` cannot be a name of derive macro
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected a valid identifier here
 pub fn foo9(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(PartialEq)] // OK
 pub fn foo10(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d11, a)]
-//~^ ERROR: second argument must be `attributes`
-//~| ERROR: attribute must be of form: `attributes(foo, bar)`
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE the only valid argument here is `attributes`
 pub fn foo11(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d12, attributes)]
-//~^ ERROR: attribute must be of form: `attributes(foo, bar)`
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected this to be a list
 pub fn foo12(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d13, attributes("a"))]
-//~^ ERROR: attribute must be a meta item, not a literal
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected a valid identifier here
 pub fn foo13(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d14, attributes(a = ""))]
-//~^ ERROR: attribute must only be a single word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect any arguments here
 pub fn foo14(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d15, attributes(m::a))]
-//~^ ERROR: attribute must only be a single word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected a valid identifier here
 pub fn foo15(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d16, attributes(a(b)))]
-//~^ ERROR: attribute must only be a single word
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE didn't expect any arguments here
 pub fn foo16(input: TokenStream) -> TokenStream { input }
 
 #[proc_macro_derive(d17, attributes(self))]
-//~^ ERROR: `self` cannot be a name of derive helper attribute
+//~^ ERROR malformed `proc_macro_derive` attribute
+//~| NOTE expected a valid identifier here
 pub fn foo17(input: TokenStream) -> TokenStream { input }
diff --git a/tests/ui/proc-macro/attribute.stderr b/tests/ui/proc-macro/attribute.stderr
index 3269aaf7f91..db59a1fdfb3 100644
--- a/tests/ui/proc-macro/attribute.stderr
+++ b/tests/ui/proc-macro/attribute.stderr
@@ -1,104 +1,148 @@
-error: malformed `proc_macro_derive` attribute input
+error[E0539]: malformed `proc_macro_derive` attribute input
   --> $DIR/attribute.rs:9:1
    |
 LL | #[proc_macro_derive]
-   | ^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+   | ^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: malformed `proc_macro_derive` attribute input
-  --> $DIR/attribute.rs:12:1
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:14:1
    |
 LL | #[proc_macro_derive = ""]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |
+   | expected this to be a list
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must have either one or two arguments
-  --> $DIR/attribute.rs:15:1
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:19:1
    |
 LL | #[proc_macro_derive(d3, a, b)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^
+   | |                       |
+   | |                       the only valid argument here is `attributes`
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must have either one or two arguments
-  --> $DIR/attribute.rs:19:1
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:24:1
    |
 LL | #[proc_macro_derive(d4, attributes(a), b)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
+   | |                                      |
+   | |                                      didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: not a meta item
-  --> $DIR/attribute.rs:23:21
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:29:1
    |
 LL | #[proc_macro_derive("a")]
-   |                     ^^^
+   | ^^^^^^^^^^^^^^^^^^^^---^^
+   | |                   |
+   | |                   didn't expect a literal here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: must only be one word
-  --> $DIR/attribute.rs:27:21
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:34:1
    |
 LL | #[proc_macro_derive(d6 = "")]
-   |                     ^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^----^^
+   | |                      |
+   | |                      didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: must only be one word
-  --> $DIR/attribute.rs:31:21
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:39:1
    |
 LL | #[proc_macro_derive(m::d7)]
-   |                     ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^-----^^
+   | |                   |
+   | |                   expected a valid identifier here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: must only be one word
-  --> $DIR/attribute.rs:35:21
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:44:1
    |
 LL | #[proc_macro_derive(d8(a))]
-   |                     ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^---^^
+   | |                     |
+   | |                     didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: `self` cannot be a name of derive macro
-  --> $DIR/attribute.rs:39:21
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:49:1
    |
 LL | #[proc_macro_derive(self)]
-   |                     ^^^^
-
-error: second argument must be `attributes`
-  --> $DIR/attribute.rs:46:26
-   |
-LL | #[proc_macro_derive(d11, a)]
-   |                          ^
+   | ^^^^^^^^^^^^^^^^^^^^----^^
+   | |                   |
+   | |                   expected a valid identifier here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must be of form: `attributes(foo, bar)`
-  --> $DIR/attribute.rs:46:26
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:57:1
    |
 LL | #[proc_macro_derive(d11, a)]
-   |                          ^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^-^^
+   | |                        |
+   | |                        the only valid argument here is `attributes`
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must be of form: `attributes(foo, bar)`
-  --> $DIR/attribute.rs:51:26
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:62:1
    |
 LL | #[proc_macro_derive(d12, attributes)]
-   |                          ^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
+   | |                        |
+   | |                        expected this to be a list
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must be a meta item, not a literal
-  --> $DIR/attribute.rs:55:37
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:67:1
    |
 LL | #[proc_macro_derive(d13, attributes("a"))]
-   |                                     ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^
+   | |                                   |
+   | |                                   expected a valid identifier here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must only be a single word
-  --> $DIR/attribute.rs:59:37
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:72:1
    |
 LL | #[proc_macro_derive(d14, attributes(a = ""))]
-   |                                     ^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^
+   | |                                     |
+   | |                                     didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must only be a single word
-  --> $DIR/attribute.rs:63:37
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:77:1
    |
 LL | #[proc_macro_derive(d15, attributes(m::a))]
-   |                                     ^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^
+   | |                                   |
+   | |                                   expected a valid identifier here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: attribute must only be a single word
-  --> $DIR/attribute.rs:67:37
+error[E0565]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:82:1
    |
 LL | #[proc_macro_derive(d16, attributes(a(b)))]
-   |                                     ^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^^^
+   | |                                    |
+   | |                                    didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: `self` cannot be a name of derive helper attribute
-  --> $DIR/attribute.rs:71:37
+error[E0539]: malformed `proc_macro_derive` attribute input
+  --> $DIR/attribute.rs:87:1
    |
 LL | #[proc_macro_derive(d17, attributes(self))]
-   |                                     ^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----^^^
+   | |                                   |
+   | |                                   expected a valid identifier here
+   | help: must be of the form: `#[proc_macro_derive(TraitName, /*opt*/ attributes(name1, name2, ...))]`
 
-error: aborting due to 17 previous errors
+error: aborting due to 16 previous errors
 
+Some errors have detailed explanations: E0539, E0565.
+For more information about an error, try `rustc --explain E0539`.
diff --git a/tests/ui/proc-macro/invalid-attributes.rs b/tests/ui/proc-macro/invalid-attributes.rs
index a70c73e9b8f..703defad69b 100644
--- a/tests/ui/proc-macro/invalid-attributes.rs
+++ b/tests/ui/proc-macro/invalid-attributes.rs
@@ -7,20 +7,32 @@ extern crate proc_macro;
 
 use proc_macro::TokenStream;
 
-#[proc_macro = "test"] //~ ERROR malformed `proc_macro` attribute
+#[proc_macro = "test"]
+//~^ ERROR malformed `proc_macro` attribute
+//~| NOTE didn't expect any arguments here
 pub fn a(a: TokenStream) -> TokenStream { a }
 
-#[proc_macro()] //~ ERROR malformed `proc_macro` attribute
+#[proc_macro()]
+//~^ ERROR malformed `proc_macro` attribute
+//~| NOTE didn't expect any arguments here
 pub fn c(a: TokenStream) -> TokenStream { a }
 
-#[proc_macro(x)] //~ ERROR malformed `proc_macro` attribute
+#[proc_macro(x)]
+//~^ ERROR malformed `proc_macro` attribute
+//~| NOTE didn't expect any arguments here
 pub fn d(a: TokenStream) -> TokenStream { a }
 
-#[proc_macro_attribute = "test"] //~ ERROR malformed `proc_macro_attribute` attribute
+#[proc_macro_attribute = "test"]
+//~^ ERROR malformed `proc_macro_attribute` attribute
+//~| NOTE didn't expect any arguments here
 pub fn e(_: TokenStream, a: TokenStream) -> TokenStream { a }
 
-#[proc_macro_attribute()] //~ ERROR malformed `proc_macro_attribute` attribute
+#[proc_macro_attribute()]
+//~^ ERROR malformed `proc_macro_attribute` attribute
+//~| NOTE didn't expect any arguments here
 pub fn g(_: TokenStream, a: TokenStream) -> TokenStream { a }
 
-#[proc_macro_attribute(x)] //~ ERROR malformed `proc_macro_attribute` attribute
+#[proc_macro_attribute(x)]
+//~^ ERROR malformed `proc_macro_attribute` attribute
+//~| NOTE didn't expect any arguments here
 pub fn h(_: TokenStream, a: TokenStream) -> TokenStream { a }
diff --git a/tests/ui/proc-macro/invalid-attributes.stderr b/tests/ui/proc-macro/invalid-attributes.stderr
index fe411fa5e1f..11c182ee03a 100644
--- a/tests/ui/proc-macro/invalid-attributes.stderr
+++ b/tests/ui/proc-macro/invalid-attributes.stderr
@@ -1,38 +1,57 @@
-error: malformed `proc_macro` attribute input
+error[E0565]: malformed `proc_macro` attribute input
   --> $DIR/invalid-attributes.rs:10:1
    |
 LL | #[proc_macro = "test"]
-   | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+   | ^^^^^^^^^^^^^--------^
+   | |            |
+   | |            didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro]`
 
-error: malformed `proc_macro` attribute input
-  --> $DIR/invalid-attributes.rs:13:1
+error[E0565]: malformed `proc_macro` attribute input
+  --> $DIR/invalid-attributes.rs:15:1
    |
 LL | #[proc_macro()]
-   | ^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+   | ^^^^^^^^^^^^--^
+   | |           |
+   | |           didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro]`
 
-error: malformed `proc_macro` attribute input
-  --> $DIR/invalid-attributes.rs:16:1
+error[E0565]: malformed `proc_macro` attribute input
+  --> $DIR/invalid-attributes.rs:20:1
    |
 LL | #[proc_macro(x)]
-   | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro]`
+   | ^^^^^^^^^^^^---^
+   | |           |
+   | |           didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro]`
 
-error: malformed `proc_macro_attribute` attribute input
-  --> $DIR/invalid-attributes.rs:19:1
+error[E0565]: malformed `proc_macro_attribute` attribute input
+  --> $DIR/invalid-attributes.rs:25:1
    |
 LL | #[proc_macro_attribute = "test"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+   | ^^^^^^^^^^^^^^^^^^^^^^^--------^
+   | |                      |
+   | |                      didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_attribute]`
 
-error: malformed `proc_macro_attribute` attribute input
-  --> $DIR/invalid-attributes.rs:22:1
+error[E0565]: malformed `proc_macro_attribute` attribute input
+  --> $DIR/invalid-attributes.rs:30:1
    |
 LL | #[proc_macro_attribute()]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+   | ^^^^^^^^^^^^^^^^^^^^^^--^
+   | |                     |
+   | |                     didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_attribute]`
 
-error: malformed `proc_macro_attribute` attribute input
-  --> $DIR/invalid-attributes.rs:25:1
+error[E0565]: malformed `proc_macro_attribute` attribute input
+  --> $DIR/invalid-attributes.rs:35:1
    |
 LL | #[proc_macro_attribute(x)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[proc_macro_attribute]`
+   | ^^^^^^^^^^^^^^^^^^^^^^---^
+   | |                     |
+   | |                     didn't expect any arguments here
+   | help: must be of the form: `#[proc_macro_attribute]`
 
 error: aborting due to 6 previous errors
 
+For more information about this error, try `rustc --explain E0565`.
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.rs
new file mode 100644
index 00000000000..9d86ebc5331
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.rs
@@ -0,0 +1,14 @@
+// gate-test-if_let_guard
+
+fn main() {
+    macro_rules! use_expr {
+        ($e:expr) => {
+            match () {
+                () if $e => {}
+                _ => {}
+            }
+        }
+    }
+    use_expr!(let 0 = 1);
+    //~^ ERROR no rules expected keyword `let`
+}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.stderr
new file mode 100644
index 00000000000..411fde890a1
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate-macro.stderr
@@ -0,0 +1,17 @@
+error: no rules expected keyword `let`
+  --> $DIR/feature-gate-macro.rs:12:15
+   |
+LL |     macro_rules! use_expr {
+   |     --------------------- when calling this macro
+...
+LL |     use_expr!(let 0 = 1);
+   |               ^^^ no rules expected this token in macro call
+   |
+note: while trying to match meta-variable `$e:expr`
+  --> $DIR/feature-gate-macro.rs:5:10
+   |
+LL |         ($e:expr) => {
+   |          ^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
index b1e305834cb..eb9e5dff37e 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.rs
@@ -64,8 +64,6 @@ fn _macros() {
         //~^ ERROR `if let` guards are experimental
         _ => {}
     }
-    use_expr!(let 0 = 1);
-    //~^ ERROR no rules expected keyword `let`
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
index 19d1f4b0a57..759f1478350 100644
--- a/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
+++ b/tests/ui/rfcs/rfc-2294-if-let-guard/feature-gate.stderr
@@ -149,21 +149,6 @@ LL |     use_expr!((let 0 = 1));
    = note: only supported directly in conditions of `if` and `while` expressions
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: no rules expected keyword `let`
-  --> $DIR/feature-gate.rs:67:15
-   |
-LL |     macro_rules! use_expr {
-   |     --------------------- when calling this macro
-...
-LL |     use_expr!(let 0 = 1);
-   |               ^^^ no rules expected this token in macro call
-   |
-note: while trying to match meta-variable `$e:expr`
-  --> $DIR/feature-gate.rs:48:10
-   |
-LL |         ($e:expr) => {
-   |          ^^^^^^^
-
 error[E0658]: `if let` guards are experimental
   --> $DIR/feature-gate.rs:7:12
    |
@@ -230,6 +215,6 @@ LL |         () if let 0 = 1 => {}
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = help: you can write `if matches!(<expr>, <pattern>)` instead of `if let <pattern> = <expr>`
 
-error: aborting due to 20 previous errors
+error: aborting due to 19 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/self/self_type_keyword.rs b/tests/ui/self/self_type_keyword.rs
index 96d24715edb..bd051279a72 100644
--- a/tests/ui/self/self_type_keyword.rs
+++ b/tests/ui/self/self_type_keyword.rs
@@ -18,8 +18,6 @@ pub fn main() {
         //~| ERROR cannot find unit struct, unit variant or constant `Self`
         ref mut Self => (),
         //~^ ERROR expected identifier, found keyword `Self`
-        Self!() => (),
-        //~^ ERROR cannot find macro `Self` in this scope
         Foo { Self } => (),
         //~^ ERROR expected identifier, found keyword `Self`
         //~| ERROR mismatched types
diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr
index f9cde810cad..f22d04bb227 100644
--- a/tests/ui/self/self_type_keyword.stderr
+++ b/tests/ui/self/self_type_keyword.stderr
@@ -36,35 +36,29 @@ LL |         ref mut Self => (),
    |                 ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:23:15
+  --> $DIR/self_type_keyword.rs:21:15
    |
 LL |         Foo { Self } => (),
    |               ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:31:26
+  --> $DIR/self_type_keyword.rs:29:26
    |
 LL |     extern crate core as Self;
    |                          ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:36:32
+  --> $DIR/self_type_keyword.rs:34:32
    |
 LL |     use std::option::Option as Self;
    |                                ^^^^ expected identifier, found keyword
 
 error: expected identifier, found keyword `Self`
-  --> $DIR/self_type_keyword.rs:41:11
+  --> $DIR/self_type_keyword.rs:39:11
    |
 LL |     trait Self {}
    |           ^^^^ expected identifier, found keyword
 
-error: cannot find macro `Self` in this scope
-  --> $DIR/self_type_keyword.rs:21:9
-   |
-LL |         Self!() => (),
-   |         ^^^^
-
 error[E0531]: cannot find unit struct, unit variant or constant `Self` in this scope
   --> $DIR/self_type_keyword.rs:16:13
    |
@@ -86,7 +80,7 @@ LL | struct Bar<'Self>;
    = help: consider removing `'Self`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0308]: mismatched types
-  --> $DIR/self_type_keyword.rs:23:9
+  --> $DIR/self_type_keyword.rs:21:9
    |
 LL |     match 15 {
    |           -- this expression has type `{integer}`
@@ -95,12 +89,12 @@ LL |         Foo { Self } => (),
    |         ^^^^^^^^^^^^ expected integer, found `Foo`
 
 error[E0026]: struct `Foo` does not have a field named `Self`
-  --> $DIR/self_type_keyword.rs:23:15
+  --> $DIR/self_type_keyword.rs:21:15
    |
 LL |         Foo { Self } => (),
    |               ^^^^ struct `Foo` does not have this field
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
 Some errors have detailed explanations: E0026, E0308, E0392, E0531.
 For more information about an error, try `rustc --explain E0026`.
diff --git a/tests/ui/self/self_type_macro_name.rs b/tests/ui/self/self_type_macro_name.rs
new file mode 100644
index 00000000000..b92b23b3b4e
--- /dev/null
+++ b/tests/ui/self/self_type_macro_name.rs
@@ -0,0 +1,6 @@
+pub fn main() {
+    match 15 {
+        Self!() => (),
+        //~^ ERROR cannot find macro `Self` in this scope
+    }
+}
diff --git a/tests/ui/self/self_type_macro_name.stderr b/tests/ui/self/self_type_macro_name.stderr
new file mode 100644
index 00000000000..25f766b758c
--- /dev/null
+++ b/tests/ui/self/self_type_macro_name.stderr
@@ -0,0 +1,8 @@
+error: cannot find macro `Self` in this scope
+  --> $DIR/self_type_macro_name.rs:3:9
+   |
+LL |         Self!() => (),
+   |         ^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/static/issue-24446.rs b/tests/ui/static/issue-24446.rs
index 830e373c189..ffd6dfabc28 100644
--- a/tests/ui/static/issue-24446.rs
+++ b/tests/ui/static/issue-24446.rs
@@ -1,8 +1,6 @@
 fn main() {
     static foo: dyn Fn() -> u32 = || -> u32 {
         //~^ ERROR the size for values of type
-        //~| ERROR cannot be shared between threads safely
-        //~| ERROR mismatched types
         0
     };
 }
diff --git a/tests/ui/static/issue-24446.stderr b/tests/ui/static/issue-24446.stderr
index ed195634f12..497ce8ccfb6 100644
--- a/tests/ui/static/issue-24446.stderr
+++ b/tests/ui/static/issue-24446.stderr
@@ -1,12 +1,3 @@
-error[E0277]: `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
-  --> $DIR/issue-24446.rs:2:17
-   |
-LL |     static foo: dyn Fn() -> u32 = || -> u32 {
-   |                 ^^^^^^^^^^^^^^^ `(dyn Fn() -> u32 + 'static)` cannot be shared between threads safely
-   |
-   = help: the trait `Sync` is not implemented for `(dyn Fn() -> u32 + 'static)`
-   = note: shared static variables must have a type that implements `Sync`
-
 error[E0277]: the size for values of type `(dyn Fn() -> u32 + 'static)` cannot be known at compilation time
   --> $DIR/issue-24446.rs:2:5
    |
@@ -16,19 +7,6 @@ LL |     static foo: dyn Fn() -> u32 = || -> u32 {
    = help: the trait `Sized` is not implemented for `(dyn Fn() -> u32 + 'static)`
    = note: statics and constants must have a statically known size
 
-error[E0308]: mismatched types
-  --> $DIR/issue-24446.rs:2:35
-   |
-LL |       static foo: dyn Fn() -> u32 = || -> u32 {
-   |  ___________________________________^
-...  |
-LL | |     };
-   | |_____^ expected `dyn Fn`, found closure
-   |
-   = note: expected trait object `(dyn Fn() -> u32 + 'static)`
-                   found closure `{closure@$DIR/issue-24446.rs:2:35: 2:44}`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.rs b/tests/ui/traits/bound/on-structs-and-enums-static.rs
index d734893dd7c..61e8e2ace60 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-static.rs
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.rs
@@ -6,9 +6,7 @@ struct Foo<T:Trait> {
     x: T,
 }
 
-static X: Foo<usize> = Foo {
-//~^ ERROR E0277
-//~| ERROR E0277
+static X: Foo<usize> = Foo { //~ ERROR E0277
     x: 1, //~ ERROR: E0277
 };
 
diff --git a/tests/ui/traits/bound/on-structs-and-enums-static.stderr b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
index 42ebcc07571..1413422794a 100644
--- a/tests/ui/traits/bound/on-structs-and-enums-static.stderr
+++ b/tests/ui/traits/bound/on-structs-and-enums-static.stderr
@@ -15,29 +15,11 @@ note: required by a bound in `Foo`
 LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
-error[E0277]: the trait bound `usize: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-static.rs:9:11
-   |
-LL | static X: Foo<usize> = Foo {
-   |           ^^^^^^^^^^ the trait `Trait` is not implemented for `usize`
-   |
-help: this trait has no implementations, consider adding one
-  --> $DIR/on-structs-and-enums-static.rs:1:1
-   |
-LL | trait Trait {
-   | ^^^^^^^^^^^
-note: required by a bound in `Foo`
-  --> $DIR/on-structs-and-enums-static.rs:5:14
-   |
-LL | struct Foo<T:Trait> {
-   |              ^^^^^ required by this bound in `Foo`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0277]: the trait bound `usize: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-static.rs:12:8
+error[E0277]: the trait bound `{integer}: Trait` is not satisfied
+  --> $DIR/on-structs-and-enums-static.rs:10:8
    |
 LL |     x: 1,
-   |        ^ the trait `Trait` is not implemented for `usize`
+   |        ^ the trait `Trait` is not implemented for `{integer}`
    |
 help: this trait has no implementations, consider adding one
   --> $DIR/on-structs-and-enums-static.rs:1:1
@@ -50,6 +32,6 @@ note: required by a bound in `Foo`
 LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.rs b/tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.rs
index a5f6ae198f6..ee04f74c8a6 100644
--- a/tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.rs
+++ b/tests/ui/traits/const-traits/macro-bare-trait-objects-const-trait-bounds.rs
@@ -13,7 +13,7 @@ macro_rules! check {
         compile_error!("ty");
     };
     (const $Trait:path) => {};
-    ([const] $Trait:path) => {};
+    ([const] $Trait:path) => { [const] Trait };
 }
 
 check! { const Trait }
diff --git a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs
index 3dcdb0cad94..35e964eacec 100644
--- a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs
+++ b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.rs
@@ -4,18 +4,19 @@
 // Setting the edition to 2018 since we don't regress `demo! { dyn const }` in Rust <2018.
 //@ edition:2018
 
+trait Trait {}
+
 macro_rules! demo {
-    ($ty:ty) => { compile_error!("ty"); };
-    //~^ ERROR ty
-    //~| ERROR ty
-    (impl $c:ident Trait) => {};
-    (dyn $c:ident Trait) => {};
+    (impl $c:ident Trait) => { impl $c Trait {} };
+    //~^ ERROR inherent
+    //~| WARN trait objects without an explicit `dyn` are deprecated
+    //~| WARN this is accepted in the current edition
+    (dyn $c:ident Trait) => { dyn $c Trait {} }; //~ ERROR macro expansion
 }
 
 demo! { impl const Trait }
 //~^ ERROR const trait impls are experimental
 
 demo! { dyn const Trait }
-//~^ ERROR const trait impls are experimental
 
 fn main() {}
diff --git a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr
index b500e4858d1..af160a45f3e 100644
--- a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr
+++ b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr
@@ -1,27 +1,31 @@
-error: ty
-  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:8:19
+error: macro expansion ignores keyword `dyn` and any tokens following
+  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:14:31
    |
-LL |     ($ty:ty) => { compile_error!("ty"); };
-   |                   ^^^^^^^^^^^^^^^^^^^^
+LL |     (dyn $c:ident Trait) => { dyn $c Trait {} };
+   |                               ^^^
 ...
-LL | demo! { impl const Trait }
-   | -------------------------- in this macro invocation
+LL | demo! { dyn const Trait }
+   | ------------------------- caused by the macro expansion here
    |
-   = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
+   = note: the usage of `demo!` is likely invalid in item context
 
-error: ty
-  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:8:19
+error: inherent impls cannot be `const`
+  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40
    |
-LL |     ($ty:ty) => { compile_error!("ty"); };
-   |                   ^^^^^^^^^^^^^^^^^^^^
+LL |     (impl $c:ident Trait) => { impl $c Trait {} };
+   |                                        ^^^^^ inherent impl for this type
 ...
-LL | demo! { dyn const Trait }
-   | ------------------------- in this macro invocation
+LL | demo! { impl const Trait }
+   | --------------------------
+   | |            |
+   | |            `const` because of this
+   | in this macro invocation
    |
+   = note: only trait implementations may be annotated with `const`
    = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0658]: const trait impls are experimental
-  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:15:14
+  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:17:14
    |
 LL | demo! { impl const Trait }
    |              ^^^^^
@@ -30,16 +34,24 @@ LL | demo! { impl const Trait }
    = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: const trait impls are experimental
-  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:18:13
+warning: trait objects without an explicit `dyn` are deprecated
+  --> $DIR/macro-const-trait-bound-theoretical-regression.rs:10:40
    |
-LL | demo! { dyn const Trait }
-   |             ^^^^^
+LL |     (impl $c:ident Trait) => { impl $c Trait {} };
+   |                                        ^^^^^
+...
+LL | demo! { impl const Trait }
+   | -------------------------- in this macro invocation
    |
-   = note: see issue #143874 <https://github.com/rust-lang/rust/issues/143874> for more information
-   = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(bare_trait_objects)]` on by default
+   = note: this warning originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: you might have intended to implement this trait for a given type
+   |
+LL |     (impl $c:ident Trait) => { impl $c Trait for /* Type */ {} };
+   |                                              ++++++++++++++
 
-error: aborting due to 4 previous errors
+error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/wf/wf-static-type.rs b/tests/ui/wf/wf-static-type.rs
index 1980c5de40c..1c35e1daf44 100644
--- a/tests/ui/wf/wf-static-type.rs
+++ b/tests/ui/wf/wf-static-type.rs
@@ -9,8 +9,6 @@ struct NotCopy;
 
 static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
 //~^ ERROR E0277
-//~| ERROR E0277
-//~| ERROR E0277
 
 
 fn main() { }
diff --git a/tests/ui/wf/wf-static-type.stderr b/tests/ui/wf/wf-static-type.stderr
index 53b90c69960..2fa8ae06c45 100644
--- a/tests/ui/wf/wf-static-type.stderr
+++ b/tests/ui/wf/wf-static-type.stderr
@@ -16,43 +16,6 @@ LL + #[derive(Copy)]
 LL | struct NotCopy;
    |
 
-error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
-  --> $DIR/wf-static-type.rs:10:13
-   |
-LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
-   |
-   = note: required for `Option<NotCopy>` to implement `Copy`
-note: required by a bound in `IsCopy`
-  --> $DIR/wf-static-type.rs:7:17
-   |
-LL | struct IsCopy<T:Copy> { t: T }
-   |                 ^^^^ required by this bound in `IsCopy`
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-help: consider annotating `NotCopy` with `#[derive(Copy)]`
-   |
-LL + #[derive(Copy)]
-LL | struct NotCopy;
-   |
-
-error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
-  --> $DIR/wf-static-type.rs:10:51
-   |
-LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
-   |                                                   ^^^^ the trait `Copy` is not implemented for `NotCopy`
-   |
-   = note: required for `Option<NotCopy>` to implement `Copy`
-note: required by a bound in `IsCopy`
-  --> $DIR/wf-static-type.rs:7:17
-   |
-LL | struct IsCopy<T:Copy> { t: T }
-   |                 ^^^^ required by this bound in `IsCopy`
-help: consider annotating `NotCopy` with `#[derive(Copy)]`
-   |
-LL + #[derive(Copy)]
-LL | struct NotCopy;
-   |
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.