Auto merge of #151363 - JonathanBrouwer:rollup-yIXELnN, r=JonathanBrouwer

Rollup of 2 pull requests

Successful merges:

 - rust-lang/rust#151336 (Port rustc codegen attrs)
 - rust-lang/rust#151359 (compiler: Temporarily re-export `assert_matches!` to reduce stabilization churn)

r? @ghost



diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml
index 80ffd67..7c721c7 100644
--- a/.github/workflows/dependencies.yml
+++ b/.github/workflows/dependencies.yml
@@ -62,19 +62,9 @@
           rustup toolchain install --no-self-update --profile minimal $TOOLCHAIN
           rustup default $TOOLCHAIN
 
-      - name: cargo update compiler & tools
-        # Remove first line that always just says "Updating crates.io index"
-        run: |
-          echo -e "\ncompiler & tools dependencies:" >> cargo_update.log
-          cargo update 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
-      - name: cargo update library
-        run: |
-          echo -e "\nlibrary dependencies:" >> cargo_update.log
-          cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
-      - name: cargo update rustbook
-        run: |
-          echo -e "\nrustbook dependencies:" >> cargo_update.log
-          cargo update --manifest-path src/tools/rustbook/Cargo.toml 2>&1 | sed '/crates.io index/d' | tee -a cargo_update.log
+      - name: cargo update
+        run: ./src/tools/update-lockfile.sh
+
       - name: upload Cargo.lock artifact for use in PR
         uses: actions/upload-artifact@v4
         with:
diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
index b8eb4f0..084d403 100644
--- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs
@@ -55,6 +55,10 @@ pub(crate) fn declare(cx: &CodegenCx<'ll, '_>) -> Self {
         let init_ty = cx.type_func(&[], cx.type_void());
         let init_rtls = declare_offload_fn(cx, "__tgt_init_all_rtls", init_ty);
 
+        // We want LLVM's openmp-opt pass to pick up and optimize this module, since it covers both
+        // openmp and offload optimizations.
+        llvm::add_module_flag_u32(cx.llmod(), llvm::ModuleFlagMergeBehavior::Max, "openmp", 51);
+
         OffloadGlobals {
             launcher_fn,
             launcher_ty,
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 185d070..7e784e3 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -4,12 +4,10 @@
 
 use proc_macro2::TokenStream;
 use quote::quote;
-use syn::spanned::Spanned;
 use synstructure::Structure;
 
 use crate::diagnostics::diagnostic_builder::DiagnosticDeriveKind;
-use crate::diagnostics::error::{DiagnosticDeriveError, span_err};
-use crate::diagnostics::utils::SetOnce;
+use crate::diagnostics::error::DiagnosticDeriveError;
 
 /// The central struct for constructing the `into_diag` method from an annotated struct.
 pub(crate) struct DiagnosticDerive<'a> {
@@ -29,36 +27,16 @@ pub(crate) fn into_tokens(self) -> TokenStream {
             let preamble = builder.preamble(variant);
             let body = builder.body(variant);
 
-            let init = match builder.slug.value_ref() {
-                None => {
-                    span_err(builder.span, "diagnostic slug not specified")
-                        .help(
-                            "specify the slug as the first argument to the `#[diag(...)]` \
-                            attribute, such as `#[diag(hir_analysis_example_error)]`",
-                        )
-                        .emit();
-                    return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                }
-                Some(slug)
-                    if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
-                        Mismatch::check(slug) =>
-                {
-                    span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
-                        .note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
-                        .help(format!("expected a slug starting with `{slug_prefix}_...`"))
-                        .emit();
-                    return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                }
-                Some(slug) => {
-                    slugs.borrow_mut().push(slug.clone());
-                    quote! {
-                        let mut diag = rustc_errors::Diag::new(
-                            dcx,
-                            level,
-                            crate::fluent_generated::#slug
-                        );
-                    }
-                }
+            let Some(slug) = builder.primary_message() else {
+                return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+            };
+            slugs.borrow_mut().push(slug.clone());
+            let init = quote! {
+                let mut diag = rustc_errors::Diag::new(
+                    dcx,
+                    level,
+                    crate::fluent_generated::#slug
+                );
             };
 
             let formatting_init = &builder.formatting_init;
@@ -113,32 +91,12 @@ pub(crate) fn into_tokens(self) -> TokenStream {
             let preamble = builder.preamble(variant);
             let body = builder.body(variant);
 
-            let primary_message = match builder.slug.value_ref() {
-                None => {
-                    span_err(builder.span, "diagnostic slug not specified")
-                        .help(
-                            "specify the slug as the first argument to the attribute, such as \
-                            `#[diag(compiletest_example)]`",
-                        )
-                        .emit();
-                    DiagnosticDeriveError::ErrorHandled.to_compile_error()
-                }
-                Some(slug)
-                    if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
-                        Mismatch::check(slug) =>
-                {
-                    span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
-                        .note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
-                        .help(format!("expected a slug starting with `{slug_prefix}_...`"))
-                        .emit();
-                    DiagnosticDeriveError::ErrorHandled.to_compile_error()
-                }
-                Some(slug) => {
-                    slugs.borrow_mut().push(slug.clone());
-                    quote! {
-                        diag.primary_message(crate::fluent_generated::#slug);
-                    }
-                }
+            let Some(slug) = builder.primary_message() else {
+                return DiagnosticDeriveError::ErrorHandled.to_compile_error();
+            };
+            slugs.borrow_mut().push(slug.clone());
+            let primary_message = quote! {
+                diag.primary_message(crate::fluent_generated::#slug);
             };
 
             let formatting_init = &builder.formatting_init;
@@ -172,30 +130,6 @@ fn decorate_lint<'__b>(
     }
 }
 
-struct Mismatch {
-    slug_name: String,
-    crate_name: String,
-    slug_prefix: String,
-}
-
-impl Mismatch {
-    /// Checks whether the slug starts with the crate name it's in.
-    fn check(slug: &syn::Path) -> Option<Mismatch> {
-        // If this is missing we're probably in a test, so bail.
-        let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
-
-        // If we're not in a "rustc_" crate, bail.
-        let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
-
-        let slug_name = slug.segments.first()?.ident.to_string();
-        if !slug_name.starts_with(slug_prefix) {
-            Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
-        } else {
-            None
-        }
-    }
-}
-
 /// Generates a `#[test]` that verifies that all referenced variables
 /// exist on this structure.
 fn generate_test(slug: &syn::Path, structure: &Structure<'_>) -> TokenStream {
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 1055f27..cbc70b5 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -110,6 +110,31 @@ pub(crate) fn each_variant<'s, F>(self, structure: &mut Structure<'s>, f: F) ->
 }
 
 impl DiagnosticDeriveVariantBuilder {
+    pub(crate) fn primary_message(&self) -> Option<&Path> {
+        match self.slug.value_ref() {
+            None => {
+                span_err(self.span, "diagnostic slug not specified")
+                    .help(
+                        "specify the slug as the first argument to the `#[diag(...)]` \
+                            attribute, such as `#[diag(hir_analysis_example_error)]`",
+                    )
+                    .emit();
+                None
+            }
+            Some(slug)
+                if let Some(Mismatch { slug_name, crate_name, slug_prefix }) =
+                    Mismatch::check(slug) =>
+            {
+                span_err(slug.span().unwrap(), "diagnostic slug and crate name do not match")
+                    .note(format!("slug is `{slug_name}` but the crate name is `{crate_name}`"))
+                    .help(format!("expected a slug starting with `{slug_prefix}_...`"))
+                    .emit();
+                None
+            }
+            Some(slug) => Some(slug),
+        }
+    }
+
     /// Generates calls to `code` and similar functions based on the attributes on the type or
     /// variant.
     pub(crate) fn preamble(&mut self, variant: &VariantInfo<'_>) -> TokenStream {
@@ -504,3 +529,27 @@ fn type_err(span: &Span) -> Result<!, DiagnosticDeriveError> {
         }
     }
 }
+
+struct Mismatch {
+    slug_name: String,
+    crate_name: String,
+    slug_prefix: String,
+}
+
+impl Mismatch {
+    /// Checks whether the slug starts with the crate name it's in.
+    fn check(slug: &syn::Path) -> Option<Mismatch> {
+        // If this is missing we're probably in a test, so bail.
+        let crate_name = std::env::var("CARGO_CRATE_NAME").ok()?;
+
+        // If we're not in a "rustc_" crate, bail.
+        let Some(("rustc", slug_prefix)) = crate_name.split_once('_') else { return None };
+
+        let slug_name = slug.segments.first()?.ident.to_string();
+        if slug_name.starts_with(slug_prefix) {
+            return None;
+        }
+
+        Some(Mismatch { slug_name, slug_prefix: slug_prefix.to_string(), crate_name })
+    }
+}
diff --git a/src/tools/update-lockfile.sh b/src/tools/update-lockfile.sh
new file mode 100755
index 0000000..a968d83
--- /dev/null
+++ b/src/tools/update-lockfile.sh
@@ -0,0 +1,18 @@
+#!/bin/sh
+
+# Updates the workspaces in `.`, `library` and `src/tools/rustbook`
+# Logs are written to `cargo_update.log`
+# Used as part of regular dependency bumps
+
+set -euo pipefail
+
+echo -e "\ncompiler & tools dependencies:" > cargo_update.log
+# Remove first line that always just says "Updating crates.io index"
+cargo update 2>&1 | sed '/crates.io index/d' | \
+    tee -a cargo_update.log
+echo -e "\nlibrary dependencies:" >> cargo_update.log
+cargo update --manifest-path library/Cargo.toml 2>&1 | sed '/crates.io index/d' | \
+    tee -a cargo_update.log
+echo -e "\nrustbook dependencies:" >> cargo_update.log
+cargo update --manifest-path src/tools/rustbook/Cargo.toml 2>&1 | sed '/crates.io index/d' | \
+    tee -a cargo_update.log
diff --git a/tests/codegen-llvm/gpu_offload/gpu_host.rs b/tests/codegen-llvm/gpu_offload/gpu_host.rs
index dcbd65b..27ff6f3 100644
--- a/tests/codegen-llvm/gpu_offload/gpu_host.rs
+++ b/tests/codegen-llvm/gpu_offload/gpu_host.rs
@@ -104,3 +104,5 @@ fn main() {
 // CHECK-NEXT:   call void @__tgt_unregister_lib(ptr nonnull %EmptyDesc)
 // CHECK-NEXT:   ret void
 // CHECK-NEXT: }
+
+// CHECK: !{i32 7, !"openmp", i32 51}
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 90ad21e..77c48ac 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -384,7 +384,7 @@
 LL | #[lint(no_crate_example, code = E0123)]
    | ^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[diag(compiletest_example)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(hir_analysis_example_error)]`
 
 error: derive(Diagnostic): attribute specified multiple times
   --> $DIR/diagnostic-derive.rs:613:53
diff --git a/tests/ui/lint/unused/unused_assignments_across_match_guards.rs b/tests/ui/lint/unused/unused_assignments_across_match_guards.rs
new file mode 100644
index 0000000..666a529
--- /dev/null
+++ b/tests/ui/lint/unused/unused_assignments_across_match_guards.rs
@@ -0,0 +1,19 @@
+// Regression test for <https://github.com/rust-lang/rust/issues/138069>
+// This test ensures that unused_assignments does not report assignments used in a match.
+//@ check-pass
+
+fn pnk(x: usize) -> &'static str {
+    let mut k1 = "k1";
+    let mut h1 = "h1";
+    match x & 3 {
+        3 if { k1 = "unused?"; false } => (),
+        _ if { h1 = k1; true } => (),
+        _ => (),
+    }
+    h1
+}
+
+#[deny(unused_assignments)]
+fn main() {
+    pnk(3);
+}