Repository: rust-lang/rust
Pull request #138601: add FCW to warn about wasm ABI transition
Author: login: RalfJung
Labels: name: T-compiler
description: Relevant to the compiler team, which will review and decide on the PR/issue.
name: O-wasm
description: Target: WASM (WebAssembly), http://webassembly.org/
name: S-waiting-on-bors
description: Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
name: merged-by-bors
description: This PR was explicitly merged by bors.
Created: 2025-03-17T11:18:27Z | Merged: 2025-03-26T03:20:21Z

See https://github.com/rust-lang/rust/issues/122532 for context: the "C" ABI on wasm32-unk-unk will change. The goal of this lint is to warn about any function definition and calls whose behavior will be affected by the change. My understanding is the following:
- scalar arguments are fine
  - including 128 bit types, they get passed as two `i64` arguments in both ABIs
- `repr(C)` structs (recursively) wrapping a single scalar argument are fine (unless they have extra padding due to over-alignment attributes)
- all return values are fine

@bjorn3 @alexcrichton @Manishearth is that correct?

I am making this a "show up in future compat reports" lint to maximize the chances people become aware of this. OTOH this likely means warnings for most users of Diplomat so maybe we shouldn't do this?

IIUC, wasm-bindgen should be unaffected by this lint as they only pass scalar types as arguments.

Tracking issue: https://github.com/rust-lang/rust/issues/138762
Transition plan blog post: https://github.com/rust-lang/blog.rust-lang.org/pull/1531

try-job: dist-various-2


Diff:
diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
index bc9cde1b2a15f..3a6b1f8d4efc9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs
@@ -332,7 +332,7 @@ fn wasm_functype<'tcx>(tcx: TyCtxt<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, def_id
     // please also add `wasm32-unknown-unknown` back in `tests/assembly/wasm32-naked-fn.rs`
     // basically the commit introducing this comment should be reverted
     if let PassMode::Pair { .. } = fn_abi.ret.mode {
-        let _ = WasmCAbi::Legacy;
+        let _ = WasmCAbi::Legacy { with_lint: true };
         span_bug!(
             tcx.def_span(def_id),
             "cannot return a pair (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
@@ -384,7 +384,7 @@ fn wasm_type<'tcx>(
                 BackendRepr::SimdVector { .. } => "v128",
                 BackendRepr::Memory { .. } => {
                     // FIXME: remove this branch once the wasm32-unknown-unknown ABI is fixed
-                    let _ = WasmCAbi::Legacy;
+                    let _ = WasmCAbi::Legacy { with_lint: true };
                     span_bug!(
                         tcx.def_span(def_id),
                         "cannot use memory args (the wasm32-unknown-unknown ABI is broken, see https://github.com/rust-lang/rust/issues/115666"
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 592c934997c01..8a761a0a0969b 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -143,6 +143,7 @@ declare_lint_pass! {
         UNUSED_VARIABLES,
         USELESS_DEPRECATED,
         WARNINGS,
+        WASM_C_ABI,
         // tidy-alphabetical-end
     ]
 }
@@ -5082,6 +5083,8 @@ declare_lint! {
     /// }
     /// ```
     ///
+    /// This will produce:
+    ///
     /// ```text
     /// warning: ABI error: this function call uses a avx vector type, which is not enabled in the caller
     ///  --> lint_example.rs:18:12
@@ -5125,3 +5128,46 @@ declare_lint! {
         reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
     };
 }
+
+declare_lint! {
+    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
+    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
+    /// of this target.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs wasm32-unknown-unknown)
+    /// #[repr(C)]
+    /// struct MyType(i32, i32);
+    ///
+    /// extern "C" my_fun(x: MyType) {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+    /// --> $DIR/wasm_c_abi_transition.rs:17:1
+    ///  |
+    ///  | pub extern "C" fn my_fun(_x: MyType) {}
+    ///  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///  |
+    ///  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    ///  = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+    ///  = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
+    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
+    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
+    /// stop functioning.
+    pub WASM_C_ABI,
+    Warn,
+    "detects code relying on rustc's non-spec-compliant wasm C ABI",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #138762 <https://github.com/rust-lang/rust/issues/138762>",
+    };
+}
diff --git a/compiler/rustc_monomorphize/messages.ftl b/compiler/rustc_monomorphize/messages.ftl
index bdeab12ab503b..aae2d79c16109 100644
--- a/compiler/rustc_monomorphize/messages.ftl
+++ b/compiler/rustc_monomorphize/messages.ftl
@@ -63,4 +63,11 @@ monomorphize_symbol_already_defined = symbol `{$symbol}` is already defined
 monomorphize_unknown_cgu_collection_mode =
     unknown codegen-item collection mode '{$mode}', falling back to 'lazy' mode
 
+monomorphize_wasm_c_abi_transition =
+    this function {$is_call ->
+      [true] call
+      *[false] definition
+    } involves an argument of type `{$ty}` which is affected by the wasm ABI transition
+    .help = the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
 monomorphize_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 8dafbbca905f7..dffa372279f9f 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -103,3 +103,12 @@ pub(crate) struct AbiRequiredTargetFeature<'a> {
     /// Whether this is a problem at a call site or at a declaration.
     pub is_call: bool,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(monomorphize_wasm_c_abi_transition)]
+#[help]
+pub(crate) struct WasmCAbiTransition<'a> {
+    pub ty: Ty<'a>,
+    /// Whether this is a problem at a call site or at a declaration.
+    pub is_call: bool,
+}
diff --git a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
index 06d6c3ab8050e..0f5bdc8d7683f 100644
--- a/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
+++ b/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
@@ -1,13 +1,15 @@
 //! This module ensures that if a function's ABI requires a particular target feature,
 //! that target feature is enabled both on the callee and all callers.
 use rustc_abi::{BackendRepr, RegKind};
-use rustc_hir::CRATE_HIR_ID;
-use rustc_middle::mir::{self, traversal};
-use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt};
-use rustc_session::lint::builtin::ABI_UNSUPPORTED_VECTOR_TYPES;
+use rustc_hir::{CRATE_HIR_ID, HirId};
+use rustc_middle::mir::{self, Location, traversal};
+use rustc_middle::ty::layout::LayoutCx;
+use rustc_middle::ty::{self, Instance, InstanceKind, Ty, TyCtxt, TypingEnv};
+use rustc_session::lint::builtin::{ABI_UNSUPPORTED_VECTOR_TYPES, WASM_C_ABI};
 use rustc_span::def_id::DefId;
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
-use rustc_target::callconv::{Conv, FnAbi, PassMode};
+use rustc_target::callconv::{ArgAbi, Conv, FnAbi, PassMode};
+use rustc_target::spec::{HasWasmCAbiOpt, WasmCAbi};
 
 use crate::errors;
 
@@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
 /// for a certain function.
 /// `is_call` indicates whether this is a call-site check or a definition-site check;
 /// this is only relevant for the wording in the emitted error.
-fn do_check_abi<'tcx>(
+fn do_check_simd_vector_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     abi: &FnAbi<'tcx, Ty<'tcx>>,
     def_id: DefId,
     is_call: bool,
-    span: impl Fn() -> Span,
+    loc: impl Fn() -> (Span, HirId),
 ) {
+    // We check this on all functions, including those using the "Rust" ABI.
+    // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
     let feature_def = tcx.sess.target.features_for_correct_vector_abi();
     let codegen_attrs = tcx.codegen_fn_attrs(def_id);
     let have_feature = |feat: Symbol| {
@@ -46,10 +50,10 @@ fn do_check_abi<'tcx>(
             let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
                 Some((_, feature)) => feature,
                 None => {
-                    let span = span();
+                    let (span, hir_id) = loc();
                     tcx.emit_node_span_lint(
                         ABI_UNSUPPORTED_VECTOR_TYPES,
-                        CRATE_HIR_ID,
+                        hir_id,
                         span,
                         errors::AbiErrorUnsupportedVectorType {
                             span,
@@ -62,10 +66,10 @@ fn do_check_abi<'tcx>(
             };
             if !have_feature(Symbol::intern(feature)) {
                 // Emit error.
-                let span = span();
+                let (span, hir_id) = loc();
                 tcx.emit_node_span_lint(
                     ABI_UNSUPPORTED_VECTOR_TYPES,
-                    CRATE_HIR_ID,
+                    hir_id,
                     span,
                     errors::AbiErrorDisabledVectorType {
                         span,
@@ -79,8 +83,9 @@ fn do_check_abi<'tcx>(
     }
     // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
     if abi.conv == Conv::X86VectorCall && !have_feature(sym::sse2) {
+        let (span, _hir_id) = loc();
         tcx.dcx().emit_err(errors::AbiRequiredTargetFeature {
-            span: span(),
+            span,
             required_feature: "sse2",
             abi: "vectorcall",
             is_call,
@@ -88,6 +93,61 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Determines whether the given argument is passed the same way on the old and new wasm ABIs.
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    loc: impl Fn() -> (Span, HirId),
+) {
+    // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`),
+    // and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy { with_lint: true }
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. Return values are not affected by this change.
+    for arg_abi in abi.args.iter() {
+        if wasm_abi_safe(tcx, arg_abi) {
+            continue;
+        }
+        let (span, hir_id) = loc();
+        tcx.emit_node_span_lint(
+            WASM_C_ABI,
+            hir_id,
+            span,
+            errors::WasmCAbiTransition { ty: arg_abi.layout.ty, is_call },
+        );
+        // Let's only warn once per function.
+        break;
+    }
+}
+
 /// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
 /// or return values for which the corresponding target feature is not enabled.
 fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
@@ -98,13 +158,15 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
         // function.
         return;
     };
-    do_check_abi(
-        tcx,
-        abi,
-        instance.def_id(),
-        /*is_call*/ false,
-        || tcx.def_span(instance.def_id()),
-    )
+    let loc = || {
+        let def_id = instance.def_id();
+        (
+            tcx.def_span(def_id),
+            def_id.as_local().map(|did| tcx.local_def_id_to_hir_id(did)).unwrap_or(CRATE_HIR_ID),
+        )
+    };
+    do_check_simd_vector_abi(tcx, abi, instance.def_id(), /*is_call*/ false, loc);
+    do_check_wasm_abi(tcx, abi, /*is_call*/ false, loc);
 }
 
 /// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -112,8 +174,8 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
 fn check_call_site_abi<'tcx>(
     tcx: TyCtxt<'tcx>,
     callee: Ty<'tcx>,
-    span: Span,
     caller: InstanceKind<'tcx>,
+    loc: impl Fn() -> (Span, HirId) + Copy,
 ) {
     if callee.fn_sig(tcx).abi().is_rustic_abi() {
         // we directly handle the soundness of Rust ABIs
@@ -141,7 +203,8 @@ fn check_call_site_abi<'tcx>(
         // ABI failed to compute; this will not get through codegen.
         return;
     };
-    do_check_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, || span);
+    do_check_simd_vector_abi(tcx, callee_abi, caller.def_id(), /*is_call*/ true, loc);
+    do_check_wasm_abi(tcx, callee_abi, /*is_call*/ true, loc);
 }
 
 fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &mir::Body<'tcx>) {
@@ -157,7 +220,19 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
                     ty::TypingEnv::fully_monomorphized(),
                     ty::EarlyBinder::bind(callee_ty),
                 );
-                check_call_site_abi(tcx, callee_ty, *fn_span, body.source.instance);
+                check_call_site_abi(tcx, callee_ty, body.source.instance, || {
+                    let loc = Location {
+                        block: bb,
+                        statement_index: body.basic_blocks[bb].statements.len(),
+                    };
+                    (
+                        *fn_span,
+                        body.source_info(loc)
+                            .scope
+                            .lint_root(&body.source_scopes)
+                            .unwrap_or(CRATE_HIR_ID),
+                    )
+                });
             }
             _ => {}
         }
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b3be4b611f03f..828230f2fe669 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1886,7 +1886,8 @@ pub mod parse {
     pub(crate) fn parse_wasm_c_abi(slot: &mut WasmCAbi, v: Option<&str>) -> bool {
         match v {
             Some("spec") => *slot = WasmCAbi::Spec,
-            Some("legacy") => *slot = WasmCAbi::Legacy,
+            // Explicitly setting the `-Z` flag suppresses the lint.
+            Some("legacy") => *slot = WasmCAbi::Legacy { with_lint: false },
             _ => return false,
         }
         true
@@ -2599,7 +2600,7 @@ written to standard error output)"),
         Requires `-Clto[=[fat,yes]]`"),
     wasi_exec_model: Option<WasiExecModel> = (None, parse_wasi_exec_model, [TRACKED],
         "whether to build a wasi command or reactor"),
-    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy, parse_wasm_c_abi, [TRACKED],
+    wasm_c_abi: WasmCAbi = (WasmCAbi::Legacy { with_lint: true }, parse_wasm_c_abi, [TRACKED],
         "use spec-compliant C ABI for `wasm32-unknown-unknown` (default: legacy)"),
     write_long_types_to_disk: bool = (true, parse_bool, [UNTRACKED],
         "whether long type names should be written to files instead of being printed in errors"),
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 6d0ee3c7ee58a..a52b2b76bc1ee 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -705,7 +705,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             "xtensa" => xtensa::compute_abi_info(cx, self),
             "riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
             "wasm32" => {
-                if spec.os == "unknown" && cx.wasm_c_abi_opt() == WasmCAbi::Legacy {
+                if spec.os == "unknown" && matches!(cx.wasm_c_abi_opt(), WasmCAbi::Legacy { .. }) {
                     wasm::compute_wasm_abi_info(self)
                 } else {
                     wasm::compute_c_abi_info(cx, self)
diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs
index 364a655113114..881168c98c32e 100644
--- a/compiler/rustc_target/src/callconv/wasm.rs
+++ b/compiler/rustc_target/src/callconv/wasm.rs
@@ -10,6 +10,9 @@ where
     if val.layout.is_aggregate() {
         if let Some(unit) = val.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()) {
             let size = val.layout.size;
+            // This size check also catches over-aligned scalars as `size` will be rounded up to a
+            // multiple of the alignment, and the default alignment of all scalar types on wasm
+            // equals their size.
             if unit.size == size {
                 val.cast_to(unit);
                 return true;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 1887134c5757d..1a823f47d9d92 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -2234,7 +2234,10 @@ pub enum WasmCAbi {
     /// Spec-compliant C ABI.
     Spec,
     /// Legacy ABI. Which is non-spec-compliant.
-    Legacy,
+    Legacy {
+        /// Indicates whether the `wasm_c_abi` lint should be emitted.
+        with_lint: bool,
+    },
 }
 
 pub trait HasWasmCAbiOpt {
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 03c3e697cfe2b..52cc8fba0438d 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
 
 use std::hash::Hash;
 use std::ops::{Bound, Range};
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 64e65ece85d68..be649029c8630 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -62,7 +62,6 @@
 //@[nvptx64] needs-llvm-components: nvptx
 #![feature(no_core, rustc_attrs, lang_items)]
 #![feature(unsized_fn_params, transparent_unions)]
-#![no_std]
 #![no_core]
 #![allow(unused, improper_ctypes_definitions, internal_features)]
 
diff --git a/tests/ui/lint/wasm_c_abi_transition.rs b/tests/ui/lint/wasm_c_abi_transition.rs
new file mode 100644
index 0000000000000..1fe81679e65d0
--- /dev/null
+++ b/tests/ui/lint/wasm_c_abi_transition.rs
@@ -0,0 +1,41 @@
+//@ compile-flags: --target wasm32-unknown-unknown
+//@ needs-llvm-components: webassembly
+//@ add-core-stubs
+//@ build-fail
+
+#![feature(no_core)]
+#![no_core]
+#![crate_type = "lib"]
+#![deny(wasm_c_abi)]
+
+extern crate minicore;
+use minicore::*;
+
+pub extern "C" fn my_fun_trivial(_x: i32, _y: f32) {}
+
+#[repr(C)]
+pub struct MyType(i32, i32);
+pub extern "C" fn my_fun(_x: MyType) {} //~ERROR: wasm ABI transition
+//~^WARN: previously accepted
+
+// This one is ABI-safe as it only wraps a single field,
+// and the return type can be anything.
+#[repr(C)]
+pub struct MySafeType(i32);
+pub extern "C" fn my_fun_safe(_x: MySafeType) -> MyType { loop {} }
+
+// This one not ABI-safe due to the alignment.
+#[repr(C, align(16))]
+pub struct MyAlignedType(i32);
+pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {} //~ERROR: wasm ABI transition
+//~^WARN: previously accepted
+
+// Check call-site warning
+extern "C" {
+    fn other_fun(x: MyType);
+}
+
+pub fn call_other_fun(x: MyType) {
+    unsafe { other_fun(x) } //~ERROR: wasm ABI transition
+    //~^WARN: previously accepted
+}
diff --git a/tests/ui/lint/wasm_c_abi_transition.stderr b/tests/ui/lint/wasm_c_abi_transition.stderr
new file mode 100644
index 0000000000000..389710d5cb3a2
--- /dev/null
+++ b/tests/ui/lint/wasm_c_abi_transition.stderr
@@ -0,0 +1,85 @@
+error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:18:1
+   |
+LL | pub extern "C" fn my_fun(_x: MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:30:1
+   |
+LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
+error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:39:14
+   |
+LL |     unsafe { other_fun(x) }
+   |              ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+
+error: aborting due to 3 previous errors
+
+Future incompatibility report: Future breakage diagnostic:
+error: this function definition involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:18:1
+   |
+LL | pub extern "C" fn my_fun(_x: MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+Future breakage diagnostic:
+error: this function definition involves an argument of type `MyAlignedType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:30:1
+   |
+LL | pub extern "C" fn my_fun_aligned(_x: MyAlignedType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+
+Future breakage diagnostic:
+error: this function call involves an argument of type `MyType` which is affected by the wasm ABI transition
+  --> $DIR/wasm_c_abi_transition.rs:39:14
+   |
+LL |     unsafe { other_fun(x) }
+   |              ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
+   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+note: the lint level is defined here
+  --> $DIR/wasm_c_abi_transition.rs:9:9
+   |
+LL | #![deny(wasm_c_abi)]
+   |         ^^^^^^^^^^
+


Reviews:
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T11:22:19Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T11:31:34Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T11:33:44Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T11:35:52Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T12:28:04Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T12:29:07Z
user: login: alexcrichton
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T15:51:16Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T16:30:30Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:22:25Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:23:56Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:27:31Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:33:55Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:40:35Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:41:28Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:43:19Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T17:45:46Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:01:19Z
user: login: hanna-kruppe
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-17T18:07:46Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:10:57Z
user: login: alexcrichton
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:27:25Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:30:42Z
user: login: alexcrichton
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:44:43Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:54:04Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T18:58:51Z
user: login: alexcrichton
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T19:00:20Z
user: login: Manishearth
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T19:20:01Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T19:39:55Z
user: login: alexcrichton
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T19:57:46Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T21:55:34Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-17T22:09:08Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:07:57Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:12:50Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:16:26Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:28:56Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:31:47Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:33:36Z
user: login: bjorn3
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T10:43:40Z
user: login: RalfJung
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-25T11:06:04Z

Review comments:
diff_hunk: @@ -0,0 +1,59 @@
+error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+  --> $DIR/wasm_c_abi_transition.rs:17:1
+   |
+LL | pub extern "C" fn my_fun(_x: MyType) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
path: tests/ui/lint/wasm_c_abi_transition.stderr
user: login: RalfJung
body: It's not technically correct that this will become a hard error (we'll just do the ABI switch), but I don't know how to make an FCW that does not have this message...
created_at: 2025-03-17T11:22:19Z
author_association: MEMBER
diff_hunk: @@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    span: impl Fn() -> Span,
+) {
+    // Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
+    // Return values are not affected by this change. (FIXME: is this true?)
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: bjorn3
body: Return types indeed shouldn't be affected. They were already returned by-ref.
created_at: 2025-03-17T11:31:33Z
author_association: MEMBER
diff_hunk: @@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    span: impl Fn() -> Span,
+) {
+    // Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
+    // Return values are not affected by this change. (FIXME: is this true?)
+    for arg_abi in abi.args.iter() {
+        if matches!(arg_abi.layout.backend_repr, BackendRepr::Scalar(_)) {
+            continue;
+        }
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: bjorn3
body: Structs that recursively only contain a single scalar and don't specify a larger alignment than the default are passed by-val with the new abi too.
created_at: 2025-03-17T11:33:44Z
author_association: MEMBER
diff_hunk: @@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    span: impl Fn() -> Span,
+) {
+    // Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
+    // Return values are not affected by this change. (FIXME: is this true?)
+    for arg_abi in abi.args.iter() {
+        if matches!(arg_abi.layout.backend_repr, BackendRepr::Scalar(_)) {
+            continue;
+        }
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: bjorn3
body: And 1-ZST types are ignored by both abis too.
created_at: 2025-03-17T11:35:52Z
author_association: MEMBER
diff_hunk: @@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    span: impl Fn() -> Span,
+) {
+    // Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
+    // Return values are not affected by this change. (FIXME: is this true?)
+    for arg_abi in abi.args.iter() {
+        if matches!(arg_abi.layout.backend_repr, BackendRepr::Scalar(_)) {
+            continue;
+        }
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: ZST are generally not safe to pass to non-Rust code anyway so I won't bother with them here.
created_at: 2025-03-17T12:28:03Z
author_association: MEMBER
diff_hunk: @@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
     }
 }
 
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    abi: &FnAbi<'tcx, Ty<'tcx>>,
+    is_call: bool,
+    span: impl Fn() -> Span,
+) {
+    // Only proceed for `extern "C" fn`` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`).
+    if !(tcx.sess.target.arch == "wasm32"
+        && tcx.sess.target.os == "unknown"
+        && tcx.wasm_c_abi_opt() == WasmCAbi::Legacy
+        && abi.conv == Conv::C)
+    {
+        return;
+    }
+    // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
+    // Return values are not affected by this change. (FIXME: is this true?)
+    for arg_abi in abi.args.iter() {
+        if matches!(arg_abi.layout.backend_repr, BackendRepr::Scalar(_)) {
+            continue;
+        }
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: > Structs that recursively only contain a single scalar and don't specify a larger alignment than the default are passed by-val with the new abi too.

I copied the wasm ABI adjustment logic for this.
created_at: 2025-03-17T12:29:07Z
author_association: MEMBER
diff_hunk: @@ -5125,3 +5128,46 @@ declare_lint! {
         reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
     };
 }
+
+declare_lint! {
+    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
+    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
+    /// of this target.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs wasm32-unknown-unknown)
+    /// #[repr(C)]
+    /// struct MyType(i32, i32);
+    ///
+    /// extern "C" my_fun(x: MyType) {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+    /// --> $DIR/wasm_c_abi_transition.rs:17:1
+    ///  |
+    ///  | pub extern "C" fn my_fun(_x: MyType) {}
+    ///  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///  |
+    ///  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    ///  = note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
+    ///  = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
+    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
+    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
+    /// stop functioning.
+    pub WASM_C_ABI,
+    Warn,
+    "detects code relying on rustc's non-spec-compliant wasm C ABI",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #122532 <https://github.com/rust-lang/rust/issues/122532>",
path: compiler/rustc_lint_defs/src/builtin.rs
user: login: alexcrichton
body: Before landing this I think it might be best to open a fresh issue here. This one's got ~100 comments and is quite old. I'm happy to open a fresh issue to fill in here once we're more settled on a final transition plan.
created_at: 2025-03-17T15:51:16Z
author_association: MEMBER
diff_hunk: @@ -5125,3 +5128,46 @@ declare_lint! {
         reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
     };
 }
+
+declare_lint! {
+    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
+    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
+    /// of this target.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs wasm32-unknown-unknown)
+    /// #[repr(C)]
+    /// struct MyType(i32, i32);
+    ///
+    /// extern "C" my_fun(x: MyType) {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+    /// --> $DIR/wasm_c_abi_transition.rs:17:1
+    ///  |
+    ///  | pub extern "C" fn my_fun(_x: MyType) {}
+    ///  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///  |
+    ///  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    ///  = note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
+    ///  = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
+    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
+    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
+    /// stop functioning.
+    pub WASM_C_ABI,
+    Warn,
+    "detects code relying on rustc's non-spec-compliant wasm C ABI",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #122532 <https://github.com/rust-lang/rust/issues/122532>",
path: compiler/rustc_lint_defs/src/builtin.rs
user: login: RalfJung
body: I don't think it's 100 comments, and it is from May last year. But sure happy to update this to another issue number if you tell me the number :)
created_at: 2025-03-17T16:30:30Z
author_association: MEMBER
diff_hunk: @@ -5125,3 +5128,46 @@ declare_lint! {
         reference: "issue #116558 <https://github.com/rust-lang/rust/issues/116558>",
     };
 }
+
+declare_lint! {
+    /// The `wasm_c_abi` lint detects usage of the `extern "C"` ABI of wasm that is affected
+    /// by a planned ABI change that has the goal of aligning Rust with the standard C ABI
+    /// of this target.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,ignore (needs wasm32-unknown-unknown)
+    /// #[repr(C)]
+    /// struct MyType(i32, i32);
+    ///
+    /// extern "C" my_fun(x: MyType) {}
+    /// ```
+    ///
+    /// This will produce:
+    ///
+    /// ```text
+    /// error: this function function definition is affected by the wasm ABI transition: it passes an argument of non-scalar type `MyType`
+    /// --> $DIR/wasm_c_abi_transition.rs:17:1
+    ///  |
+    ///  | pub extern "C" fn my_fun(_x: MyType) {}
+    ///  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+    ///  |
+    ///  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+    ///  = note: for more information, see issue #122532 <https://github.com/rust-lang/rust/issues/122532>
+    ///  = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
+    /// ```
+    ///
+    /// ### Explanation
+    ///
+    /// Rust has historically implemented a non-spec-compliant C ABI on wasm32-unknown-unknown. This
+    /// has caused incompatibilities with other compilers and Wasm targets. In a future version
+    /// of Rust, this will be fixed, and therefore code relying on the non-spec-compliant C ABI will
+    /// stop functioning.
+    pub WASM_C_ABI,
+    Warn,
+    "detects code relying on rustc's non-spec-compliant wasm C ABI",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #122532 <https://github.com/rust-lang/rust/issues/122532>",
path: compiler/rustc_lint_defs/src/builtin.rs
user: login: Manishearth
body: Yeah I think we should have a separate issue that helps talk about mitigation strategies.
created_at: 2025-03-17T17:22:25Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: proposal: should this lint be silenced when an explicit `-Zwasm-c-abi` is passed in? I think that's a good mitigation strategy.

Alternatively in the issue we file we can talk about pairing `-Zwasm-c-abi` with `allow(wasm_c_abi)`.
created_at: 2025-03-17T17:23:56Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: So you mean even `-Zwasm-c-abi=legacy` should disable the lint?

I'm not sure how to do that, rustc does not keep around the info whether the flag was passed for the rest of the compilation session.
created_at: 2025-03-17T17:27:31Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: yeah, perhaps in that case we ask people to stick `allow`s in their code when doing the transition.

(can FCWs be `allow`d? I think so?)
created_at: 2025-03-17T17:33:55Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: > (can FCWs be allowd? I think so?)

The warning itself, for sure. But it may still show up in the future-compat report cargo prints, if we mark it as `FutureReleaseErrorReportInDeps` as this PR does right now...
EDIT: yes, it does still show up there.
created_at: 2025-03-17T17:40:35Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: > ask people to stick allows in their code 

`-Awasm-c-abi` should also work. Since people are anyway passing a flag, adding another flag should be the easiest approach.
created_at: 2025-03-17T17:41:28Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: Oh good point
created_at: 2025-03-17T17:43:19Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: Seems increasingly  like `FutureReleaseErrorReportInDeps`  is a bad call. If we make this a normal lint, we can also avoid the wording saying this will be a hard error in the future.

However, then people won't be warned if the issue shows up in their dependencies. Only the crate author would see it, and only if they actually build for wasm32-u-u.
created_at: 2025-03-17T17:45:46Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: Hm. Does this _matter_ in dependencies? It's not that normal to have extern C exposed functions in deps.

Diplomat does this a _little bit_ in the diplomat-runtime crate but that gets paired with extern C functions in the actual end crate.


We could add a new FutureIncompatibilityReason: for things that aren't going to go away but will go through a period of cross-version brokenness. That sounds potentially useful for other similar soundness issues, giving people a chance to handle them the way they need.
created_at: 2025-03-17T18:01:19Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: hanna-kruppe
body: I think that's probably okay because by far the most common case where it matters are application-specific (as opposed to something like WASI) interfaces between Rust compiled to wasm and a host embedding the wasm module. Mixing Rust with C code *on wasm32-unknown-unknown* is not common because of the lack of serious C toolchain for this target and glaring C-ABI-incompatibility. And Rust libraries compiled to that target generally can't assume any particular interfaces with the embedder, unless they use a binding generator that lets any library in the dependency tree register new things to bind. Thus:

- Hand-authored bespoke bindings are tied to the application (workspace), not hidden away in third party dependencies, so the right person will see the warning.
- With wasm-bindgen any random library can emit imports/exports, and the wasm module is post-processed afterwards without rustc being involved, so projects that indirectly depend on something like `js-sys` won't get the warning. But wasm-bindgen users have already been getting a proper FWC previously, and can just upgrade wasm-bindgen.
- For Diplomat, I believe the usual workflow has the application author in charge of defining a "bridge module" in their own project, so the warning should get emitted. @Manishearth can correct me if I'm wrong.
created_at: 2025-03-17T18:07:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: (you are correct)
created_at: 2025-03-17T18:10:57Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: alexcrichton
body: If possible I would personally like to keep this as a FCW because while we have Manish and Diplomat in this discussion there could be other folks. Using a FCW for deps feels like the most likely way to get users to come out of the woodwork to talk about this if necessary.

In some sense though I also see it as a feature of being unable to silence this warning. The purpose of the warning is to alert users "this behavior is guaranteed to change in the future, please be aware". If users simply silence the warning they've not actually done anything to address the upcoming change and things are likely to just stop working one day when rustc is updated. 

The issue would outline 3 ways to silence the warning of (1) change the C API to not use aggregates, (2) pin to an older rustc, or (3) update to nightly and use `-Zwasm-c-abi=spec` (or legacy temporarily). The exact change for Diplomat is a bit different for this 1/2/3 but this is more broadly targeted at anyone seeing this warning. Diplomat would tell users to do (2) or (3) with "legacy" since (1) is un-tenable as the C API is not wasm-specific.
created_at: 2025-03-17T18:27:25Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: Yeah, I'm definitely wary to speak for anyone other than diplomat.

> In some sense though I also see it as a feature of being unable to silence this warning. The purpose of the warning is to alert users "this behavior is guaranteed to change in the future, please be aware". If users simply silence the warning they've not actually done anything to address the upcoming change and things are likely to just stop working one day when rustc is updated.


Well, if you use `-Zwasm-c-abi=spec` then you have actually done something, yes? So you should be allowed to silence it. 

But it's probably not a huge deal, as long as it's not build-blocking it's not super bothersome to have piles of warnings on the wasm build. Probably.
created_at: 2025-03-17T18:30:42Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: alexcrichton
body: As-written though this PR already silences the lint with `-Zwasm-c-abi=spec` as I believe [this line](https://github.com/rust-lang/rust/pull/138601/files#diff-b1bcaba5ec6f5fcf5192c9a2c4d32c4fa6c75b95a5c18b88967883642a92579aR126) bails out when that's set. In that I would agree that `-Zwasm-c-abi=spec` should silence the lint, but I aslo beleive it currently does.
created_at: 2025-03-17T18:44:43Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: Correct, the lint gets silenced with `-Zwasm-c-abi=spec`.

To also make it silent with `-Zwasm-c-abi=legacy` requires more work. It's certainly possible somehow though so if silencing the lint for that flag is useful for the transition plan, we should to it.

> We could add a new FutureIncompatibilityReason: for things that aren't going to go away but will go through a period of cross-version brokenness. That sounds potentially useful for other similar soundness issues, giving people a chance to handle them the way they need.

That sounds like a deep change reaching far through the compiler. Might be a good change, but it's more than I will attempt in this PR. (But of course someone else could take over. :)
created_at: 2025-03-17T18:54:03Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: Ah, that should be fine.
created_at: 2025-03-17T18:58:51Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: alexcrichton
body: Hm I actually hadn't fully thought through "I don't want warnings after passing `-Zwasm-c-abi=legacy`". On one hand the FCW is correct, builds will break as `-Zwasm-c-abi` will be removed. On the other hand then the only way to silence warnings is to not update rustc.

How hard would it be to define two lints? One FCW lint that happens if `-Zwasm-c-abi` is not present in flags, and one normal lint if `-Zwasm-c-abi=legacy` is passed. That way you can `-Anormal-lint` to silence the warning, and deps surface FCW warnings as usual.
created_at: 2025-03-17T19:00:19Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: Manishearth
body: oh that works.

Overall "I don't want warnings after passing -Zwasm-c-abi=legacy" wasn't the main request, as long as it's silent on `spec` it should be fine. But having that level of control over the warnings is nicer, idk if it's _necessary_.
created_at: 2025-03-17T19:20:01Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: I don't quite get the point of having two lints. I think the fact that `-Z` is a nightly-only flag is a clear enough signal that this can be changed/removed any time, so we don't need another lint there IMO.
created_at: 2025-03-17T19:39:55Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: alexcrichton
body: Under the assumption that a FCW cannot be fully silenced with `-A` flags, the second lint satisfies the use case of "I know breakage is coming but I want a warning-free build for now" which can't otherwise be fulfilled. If no one actually wants such a construction though I definitely won't push for it myself.
created_at: 2025-03-17T19:57:46Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: The option of having `-Zwasm-c-abi=legacy` just not emit the lint would also achieve that, and would definitely be easier to implement than two lints.
created_at: 2025-03-17T21:55:34Z
author_association: MEMBER
diff_hunk: @@ -88,6 +92,60 @@ fn do_check_abi<'tcx>(
     }
 }
 
+fn wasm_abi_safe<'tcx>(tcx: TyCtxt<'tcx>, arg: &ArgAbi<'tcx, Ty<'tcx>>) -> bool {
+    if matches!(arg.layout.backend_repr, BackendRepr::Scalar(_)) {
+        return true;
+    }
+
+    // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.
+    if arg.layout.is_aggregate() {
+        let cx = LayoutCx::new(tcx, TypingEnv::fully_monomorphized());
+        if let Some(unit) = arg.layout.homogeneous_aggregate(&cx).ok().and_then(|ha| ha.unit()) {
+            let size = arg.layout.size;
+            // Ensure there's just a single `unit` element in `arg`.
+            if unit.size == size {
+                return true;
+            }
+        }
+    }
+
+    false
+}
+
+/// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
+/// ABI transition.
+fn do_check_wasm_abi<'tcx>(
path: compiler/rustc_monomorphize/src/mono_checks/abi_check.rs
user: login: RalfJung
body: > The option of having -Zwasm-c-abi=legacy just not emit the lint would also achieve that,

I have now implemented that.
created_at: 2025-03-17T22:09:08Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: bjorn3
body: You need to allow it at the root of the crate as you passed `CRATE_HIR_ID` to `emit_node_span_lint`.
created_at: 2025-03-25T10:07:56Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: RalfJung
body: Ah, that's how that works. :)
Is there a better HIR ID we can pass? For the call-site check we have a MIR location, and for the callee-site check we have an `Instance`. Can one get a HIR ID from those?
created_at: 2025-03-25T10:12:50Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: bjorn3
body: If the caller or callee is codegened in a different crate than it was defined, there is no way to get the lint level of its definition AFAIK. HIR only exists for the local crate.
created_at: 2025-03-25T10:16:26Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: RalfJung
body: Yeah fair, but in many cases this will be local to the crate and then we should be able to get a proper HirId. I've added a commit that attempts to do that.
created_at: 2025-03-25T10:28:56Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: bjorn3
body: Now that I think of it, having a fallback to the `CRATE_HIR_ID` would actually cause warnings to depend on the exact crate in which rustc decides to codegen functions.
created_at: 2025-03-25T10:31:47Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: RalfJung
body: That's already the case anyway, right? With my patch we just use a better HirId when we can.

This is a mono-time check, so it fundamentally can indeed occur in other crates. There's not a lot we can do about that; ABI concerns can only be reliably checked during monomorphization.
created_at: 2025-03-25T10:33:36Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: bjorn3
body: > That's already the case anyway, right? With my patch we just use a better HirId when we can.

Yeah, your last commit is strictly an improvement with respect to this.

> This is a mono-time check, so it fundamentally can indeed occur in other crates.

Currently all of them are hard errors, so it doesn't matter in which crate they get codegened. Only if they get codegened at all. With this PR however a crate may need to add `#![allow(...)]` because an indirect dependency happened to use this attribute. And which crates need to add it even depends on the rustc version and exact build configuration that the end user decided.
created_at: 2025-03-25T10:43:40Z
author_association: MEMBER
diff_hunk: @@ -7,6 +7,10 @@
 //! Rust ABIs (e.g., stage0/bin/rustc vs stage1/bin/rustc during bootstrap).
 
 #![deny(unsafe_code)]
+// proc_macros anyway don't work on wasm hosts so while both sides of this bridge can
+// be built with different versions of rustc, the wasm ABI changes don't really matter.
+#![cfg_attr(bootstrap, allow(unknown_lints))]
+#![allow(wasm_c_abi)]
path: library/proc_macro/src/bridge/mod.rs
user: login: RalfJung
body: > Currently all of them are hard errors

No, ABI_UNSUPPORTED_VECTOR_TYPES is also a FCW.
created_at: 2025-03-25T11:06:03Z
author_association: MEMBER

PR comments:
user: login: rustbot
created_at: 2025-03-17T11:18:32Z
body: r? @wesleywiser

rustbot has assigned @wesleywiser.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use `r?` to explicitly pick a reviewer
author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-03-17T11:28:28Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/13898128551/job/38883369555) [(plain)](https://github.com/rust-lang/rust/commit/7863065b49c95b719cda463d9aa920b5289d5c19/checks/38883369555/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 2.932 Building wheels for collected packages: reuse
#12 2.933   Building wheel for reuse (pyproject.toml): started
#12 3.150   Building wheel for reuse (pyproject.toml): finished with status 'done'
#12 3.151   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132720 sha256=0c2fd2aaf7b0bf8d6e131220aff14712a774c2ca462f3204d25460cbcf610b63
#12 3.151   Stored in directory: /tmp/pip-ephem-wheel-cache-bpz5y9ms/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#12 3.154 Successfully built reuse
#12 3.154 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#12 3.557 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#12 3.557 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 4.113 Collecting virtualenv
#12 4.162   Downloading virtualenv-20.29.3-py3-none-any.whl (4.3 MB)
#12 4.318      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 28.1 MB/s eta 0:00:00
#12 4.380 Collecting distlib<1,>=0.3.7
#12 4.387   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.404      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 32.0 MB/s eta 0:00:00
#12 4.450 Collecting filelock<4,>=3.12.2
#12 4.457   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.495 Collecting platformdirs<5,>=3.9.1
#12 4.502   Downloading platformdirs-4.3.6-py3-none-any.whl (18 kB)
#12 4.584 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 4.770 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.6 virtualenv-20.29.3
#12 4.770 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 4.9s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      135104 kB
DirectMap2M:     5107712 kB
DirectMap1G:    13631488 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.215
---
fmt check
fmt: checked 5907 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs:102: comment with odd number of backticks
##[error]tidy error: /checkout/tests/ui/lint/wasm_c_abi_transition.rs:27: trailing whitespace
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:52
  local time: Mon Mar 17 11:28:16 UTC 2025
  network time: Mon, 17 Mar 2025 11:28:16 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: bjorn3
created_at: 2025-03-17T11:29:20Z
body: > I am a bit concerned about 128bit scalar types as wasm doesn't have those. Do we have to warn about those as well?

That doesn't seem to be necessary. Both the old abi and new abi pass it as two i64 arguments.
author_association: MEMBER
user: login: hanna-kruppe
created_at: 2025-03-17T12:10:12Z
body: Re: i128, we just had an ABI break (independent of -Zwasm-c-abi) in 1.85 but it only changed alignment not the by-value ABI I believe https://github.com/rust-lang/rust/pull/134165
author_association: CONTRIBUTOR
user: login: rust-log-analyzer
created_at: 2025-03-17T12:43:08Z
body: 
The job **`mingw-check-tidy`** failed! Check out the build log: [(web)](https://github.com/rust-lang/rust/actions/runs/13899509283/job/38887749734) [(plain)](https://github.com/rust-lang/rust/commit/fe72062c20abbb1ec7d10fdb763184fdb012b5bc/checks/38887749734/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
info: removing rustup binaries
info: rustup is uninstalled
##[group]Image checksum input
mingw-check-tidy
# We use the ghcr base image because ghcr doesn't have a rate limit
# and the mingw-check-tidy job doesn't cache docker images in CI.
FROM ghcr.io/rust-lang/ubuntu:22.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y --no-install-recommends \
  g++ \
  make \
---

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
#
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#12 3.367 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 3.903 Collecting virtualenv
#12 3.941   Downloading virtualenv-20.29.3-py3-none-any.whl (4.3 MB)
#12 4.006      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 4.3/4.3 MB 70.6 MB/s eta 0:00:00
#12 4.064 Collecting platformdirs<5,>=3.9.1
#12 4.068   Downloading platformdirs-4.3.6-py3-none-any.whl (18 kB)
#12 4.104 Collecting filelock<4,>=3.12.2
#12 4.124   Downloading filelock-3.18.0-py3-none-any.whl (16 kB)
#12 4.142 Collecting distlib<1,>=0.3.7
#12 4.147   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#12 4.155      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 86.4 MB/s eta 0:00:00
#12 4.236 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#12 4.421 Successfully installed distlib-0.3.9 filelock-3.18.0 platformdirs-4.3.6 virtualenv-20.29.3
#12 4.422 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#12 DONE 4.5s

#13 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#13 DONE 0.0s
---
DirectMap4k:      137152 kB
DirectMap2M:     7202816 kB
DirectMap1G:    11534336 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py,cpp
##[group]Building bootstrap
    Finished `dev` profile [unoptimized] target(s) in 0.05s
##[endgroup]
WARN: currently no CI rustc builds have rustc debug assertions enabled. Please either set `rust.debug-assertions` to `false` if you want to use download CI rustc or set `rust.download-rustc` to `false`.
[TIMING] core::build_steps::tool::LibcxxVersionTool { target: x86_64-unknown-linux-gnu } -- 0.216
---
fmt check
fmt: checked 5907 files
tidy check
tidy: Skipping binary file check, read-only filesystem
##[error]tidy error: /checkout/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs:100: comment with odd number of backticks
##[error]tidy error: /checkout/compiler/rustc_monomorphize/src/mono_checks/abi_check.rs:122: comment with odd number of backticks
##[error]tidy error: /checkout/tests/ui/lint/wasm_c_abi_transition.rs:41: trailing whitespace
removing old virtual environment
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'venv'
creating virtual environment at '/checkout/obj/build/venv' using 'python3.10' and 'virtualenv'
Requirement already satisfied: pip in ./build/venv/lib/python3.10/site-packages (25.0.1)
linting python files
All checks passed!
checking python file formatting
26 files already formatted
checking C++ file formatting
some tidy checks failed
Command has failed. Rerun with -v to see more details.
Build completed unsuccessfully in 0:01:46
  local time: Mon Mar 17 12:42:52 UTC 2025
  network time: Mon, 17 Mar 2025 12:42:52 GMT
##[error]Process completed with exit code 1.
Post job cleanup.
```

</details>

author_association: COLLABORATOR
user: login: alexcrichton
created_at: 2025-03-17T15:48:08Z
body: > ... @alexcrichton ... is that correct?

Honestly I'm not actually sure. The ABI bits have always been a black box to me and I don't feel confident that I would be able to enumerate the list of differences between `-Zwasm-c-abi={spec,legacy}`. I think the problem is that the before state is "whatever rustc/llvm together do, pending private details".

That being said what you listed matches my rough understanding. I mostly want to clarify in that I do not have certainty on the exhaustiveness of my understanding.

Would it be possible to "run both ABIs and look for a difference"? That'd help make me more confident in the exhaustiveness of the check, but I'm not sure if that's possible given the structure of the code.

What I can perhaps clarify is that the "official definition" is [this](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md#function-arguments-and-return-values) for params/results. I'm not knowledgable enough of rustc ABI internals to diff that with what the previous behavior was myself though.
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-17T16:10:38Z
body: > Would it be possible to "run both ABIs and look for a difference"? That'd help make me more confident in the exhaustiveness of the check, but I'm not sure if that's possible given the structure of the code.

No, it's not possible unfortunately. The entire issue is that the legacy ABI relies on LLVM details rustc has no knowledge about, and on rustc_codegen_llvm details the rest of rustc has no knowledge about.
author_association: MEMBER
user: login: alexcrichton
created_at: 2025-03-17T16:13:11Z
body: Ok thanks for clarifying, in that case I think we can mitigate that by (a) adding appropriate wording to the blog post about this change and perhaps (b) calling out in the release notes for the next release of Rust "hey things are changing in wasm go read this blog post for more info". Basically just doing our best to raise awareness and get folks testing out `-Zwasm-c-abi=spec`. If things come up we can continue to refine the lint.
author_association: MEMBER
user: login: rustbot
created_at: 2025-03-17T22:00:12Z
body: Some changes occurred in compiler/rustc_codegen_ssa

cc @WaffleLapkin

These commits modify **compiler targets**.
(See the [Target Tier Policy](https://doc.rust-lang.org/nightly/rustc/target-tier-policy.html).)

author_association: COLLABORATOR
user: login: alexcrichton
created_at: 2025-03-21T00:27:23Z
body: I've filed https://github.com/rust-lang/rust/issues/138762 as a landing page for this lint
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-21T07:08:31Z
body: Thanks, I have updated the PR to link to that issue. The PR should be good to go then?

Nowhere in the blog post or the tracking issue do we mention that `-Zwasm-c-abi=legacy` suppresses the lint. That seemed to be a key part of Diplomat's transition plan, or is that not the case any more? This PR becomes simpler if we don't have that flag suppress the lint.
author_association: MEMBER
user: login: alexcrichton
created_at: 2025-03-21T15:25:49Z
body: Oh that's just an oversight on my part. @Manishearth I know you said it would be nice for `-Zwasm-c-abi=legacy` to suppress the lint, but can you confirm that it's desirable enough for the extra complexity in this PR?
author_association: MEMBER
user: login: Manishearth
created_at: 2025-03-21T15:27:55Z
body: Having spec turn off the lint is desirable, having legacy turn off the lint is ... only somewhat a benefit, so it's fine if you don't.

Ultimately it's just a warning
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-21T15:29:41Z
body: Ultimately I already wrote the code so it doesn't need to be a huge benefit. ;) But it if provides a benefit, it should probably occur somewhere in our recommended transition plan.
author_association: MEMBER
user: login: alexcrichton
created_at: 2025-03-21T15:37:52Z
body: Ok I've updated both https://github.com/rust-lang/rust/issues/138762 and https://github.com/rust-lang/blog.rust-lang.org/pull/1531 to mention the lint-silencing nature of `-Zwasm-c-abi=legacy`, and in that case...

@bors: r+
author_association: MEMBER
user: login: bors
created_at: 2025-03-21T15:37:55Z
body: :pushpin: Commit 3301e0ea826ca58a199f09ed08b4d0e4d0f76990 has been approved by `alexcrichton`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust) for this repository.

<!-- @bors r=alexcrichton 3301e0ea826ca58a199f09ed08b4d0e4d0f76990 -->
<!-- homu: {"type":"Approved","sha":"3301e0ea826ca58a199f09ed08b4d0e4d0f76990","approver":"alexcrichton","queue":"https://bors.rust-lang.org/homu/queue/rust"} -->
author_association: COLLABORATOR
user: login: matthiaskrgr
created_at: 2025-03-22T10:58:40Z
body: @bors r-
https://github.com/rust-lang/rust/pull/138827#issuecomment-2745209958
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-22T13:50:56Z
body: Seems our own internal proc macro ABI is affected. That should be fine though as long as both sides of this are compiled with the same rustc.
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-22T17:42:58Z
body: I just allowed the lint in the proc_macro bridge. I hope that makes sense?
Not sure whom to ping for that bridge... @eddyb and @petrochenkov maybe?
author_association: MEMBER
user: login: hanna-kruppe
created_at: 2025-03-22T17:49:47Z
body: Why’s the bridge being compiled for wasm32-unknown-unknown anyway?
author_association: CONTRIBUTOR
user: login: alexcrichton
created_at: 2025-03-22T17:51:11Z
body: @bors: r+

I believe the comment Ralf left is right, both sides of the bridge are rustc and JS isn't involved, so it doesn't matter what the exact ABI is. I believe this is built for wasm32-unknown-unknown as a standard part of any std-containing sysroot for a target. For example `extern crate proc_macro;` is valid on wasm32-unknown-unknown
author_association: MEMBER
user: login: bors
created_at: 2025-03-22T17:51:13Z
body: :pushpin: Commit a75a841fcc800905443ed20018d54768ccb3149f has been approved by `alexcrichton`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust) for this repository.

<!-- @bors r=alexcrichton a75a841fcc800905443ed20018d54768ccb3149f -->
<!-- homu: {"type":"Approved","sha":"a75a841fcc800905443ed20018d54768ccb3149f","approver":"alexcrichton","queue":"https://bors.rust-lang.org/homu/queue/rust"} -->
author_association: COLLABORATOR
user: login: bjorn3
created_at: 2025-03-22T18:17:22Z
body: > I believe the comment Ralf left is right, both sides of the bridge are rustc and JS isn't involved, so it doesn't matter what the exact ABI is.

While both sides of the bridge are rustc, they can be different versions of rustc. That is why the bridge exists in the first place and uses the C ABI rather than the Rust ABI. That said as rustc doesn't even support loading proc-macros when it is itself compiled to wasm, it doesn't really matter that the ABI changes just on wasm.
author_association: MEMBER
user: login: matthiaskrgr
created_at: 2025-03-24T19:39:12Z
body: @bors r- rollup=iffy
https://github.com/rust-lang/rust/pull/138890#issuecomment-2749167015
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-25T07:16:31Z
body: Eh, but I have allowed the lint for the entire module, why does it still trigger?
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-25T07:22:59Z
body: Locally a wasm32-unknown-unknown build of proc_macro works just fine... wtf.

@bors try
author_association: MEMBER
user: login: bors
created_at: 2025-03-25T07:24:12Z
body: :hourglass: Trying commit 61e24e630d5eea7bbff63e46051de509ceb46c33 with merge cb87fb8ade9ebde8ee368f236e61795631f523a2...
<!-- homu: {"type":"TryBuildStarted","head_sha":"61e24e630d5eea7bbff63e46051de509ceb46c33","merge_sha":"cb87fb8ade9ebde8ee368f236e61795631f523a2"} -->
author_association: COLLABORATOR
user: login: rust-log-analyzer
created_at: 2025-03-25T08:17:05Z
body: 
The job **`dist-various-2`** failed! Check out the build log: [(web)](https://github.com/rust-lang-ci/rust/actions/runs/14053906006/job/39349203759) [(plain)](https://github.com/rust-lang-ci/rust/commit/cb87fb8ade9ebde8ee368f236e61795631f523a2/checks/39349203759/logs)

<details><summary><i>Click to see the possible cause of the failure (guessed by this bot)</i></summary>

```plain
file:.git/config remote.origin.url=https://github.com/rust-lang-ci/rust
file:.git/config remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
file:.git/config gc.auto=0
file:.git/config http.https://github.com/.extraheader=AUTHORIZATION: basic ***
file:.git/config branch.try.remote=origin
file:.git/config branch.try.merge=refs/heads/try
file:.git/config remote.upstream.url=https://github.com/rust-lang/rust
file:.git/config remote.upstream.fetch=+refs/heads/*:refs/remotes/upstream/*
file:.git/config submodule.library/backtrace.active=true
file:.git/config submodule.library/backtrace.url=https://github.com/rust-lang/backtrace-rs.git
file:.git/config submodule.library/stdarch.active=true
---
[RUSTC-TIMING] getopts test:false 0.966
error: this function definition involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
   --> library/proc_macro/src/bridge/buffer.rs:143:9
    |
143 |         extern "C" fn reserve(b: Buffer, additional: usize) -> Buffer {
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
    = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
---

error: this function call involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
  --> library/proc_macro/src/bridge/closure.rs:30:18
   |
30 |         unsafe { (self.call)(self.env, arg) }
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target
---

error: this function call involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
  --> library/proc_macro/src/bridge/buffer.rs:93:21
   |
93 |             *self = (b.reserve)(b, 1);
   |                     ^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target

error: this function call involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
   --> library/proc_macro/src/bridge/buffer.rs:125:9
    |
125 |         (b.drop)(b);
    |         ^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
    = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target

error: this function call involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
  --> library/proc_macro/src/bridge/buffer.rs:66:21
   |
66 |             *self = (b.reserve)(b, xs.len());
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target

note: the above error was encountered while instantiating `fn bridge::buffer::Buffer::extend_from_array::<4>`
   --> library/proc_macro/src/bridge/rpc.rs:28:17
    |
24  | / macro_rules! rpc_encode_decode {
25  | |     (le $ty:ty) => {
26  | |         impl<S> Encode<S> for $ty {
27  | |             fn encode(self, w: &mut Writer, _: &mut S) {
28  | |                 w.extend_from_array(&self.to_le_bytes());
    | |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...   |
105 | | }
    | |_- in this expansion of `rpc_encode_decode!`
...
129 |   rpc_encode_decode!(le u32);
    |   -------------------------- in this macro invocation

note: the above error was encountered while instantiating `fn bridge::client::<impl bridge::symbol::Symbol>::normalize_and_validate_ident::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

error: this function call involves an argument of type `buffer::Buffer` which is affected by the wasm ABI transition
  --> library/proc_macro/src/bridge/buffer.rs:78:21
   |
78 |             *self = (b.reserve)(b, xs.len());
   |                     ^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
   = note: for more information, see issue #138762 <https://github.com/rust-lang/rust/issues/138762>
   = help: the "C" ABI Rust uses on wasm32-unknown-unknown will change to align with the standard "C" ABI for this target

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::clone::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::drop::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::concat_trees::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

---
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::FreeFunctions::drop::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::SourceFile::drop::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

---
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::expand_expr::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

---
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::from_token_tree::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::TokenStream::concat_streams::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

---
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::Span::column::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::Span::join::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::Span::resolved_at::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

---
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn bridge::client::SourceFile::eq::{closure#0}`
   --> library/proc_macro/src/bridge/client.rs:233:13
    |
233 |             f(&mut bridge)
    |             ^^^^^^^^^^^^^^

```

</details>

author_association: COLLABORATOR
user: login: bors
created_at: 2025-03-25T08:17:18Z
body: :broken_heart: Test failed - [checks-actions](https://github.com/rust-lang-ci/rust/actions/runs/14053906006/job/39351634060)
<!-- homu: {"type":"TryBuildFailed","builder_url":"https://github.com/rust-lang-ci/rust/actions/runs/14053906006/job/39351634060","builder_name":"checks-actions"} -->
author_association: COLLABORATOR
user: login: RalfJung
created_at: 2025-03-25T10:04:43Z
body: Yeah same error. No idea what is happening.
author_association: MEMBER
user: login: RalfJung
created_at: 2025-03-25T10:29:48Z
body: @bors try
author_association: MEMBER
user: login: bors
created_at: 2025-03-25T10:31:04Z
body: :hourglass: Trying commit 782a79710ef3e5edc954a44937c6a5684e2e7fe7 with merge fde8c7793c0fdf859d230a4b86205a9495d2965e...
<!-- homu: {"type":"TryBuildStarted","head_sha":"782a79710ef3e5edc954a44937c6a5684e2e7fe7","merge_sha":"fde8c7793c0fdf859d230a4b86205a9495d2965e"} -->
author_association: COLLABORATOR
user: login: RalfJung
created_at: 2025-03-25T10:32:10Z
body: @bors try
author_association: MEMBER
user: login: bors
created_at: 2025-03-25T10:33:23Z
body: :hourglass: Trying commit e88c49c454b965c4c60edf19d1305087c9758a29 with merge c19c3fbac0c3230987fe8ccfcb40573cd8ef9b14...
<!-- homu: {"type":"TryBuildStarted","head_sha":"e88c49c454b965c4c60edf19d1305087c9758a29","merge_sha":"c19c3fbac0c3230987fe8ccfcb40573cd8ef9b14"} -->
author_association: COLLABORATOR
user: login: RalfJung
created_at: 2025-03-25T11:18:25Z
body: r? @alexcrichton 
Hopefully CI will pass this time... but there's a new commit someone should look at :)
author_association: MEMBER
user: login: bors
created_at: 2025-03-25T11:43:56Z
body: :sunny: Try build successful - [checks-actions](https://github.com/rust-lang-ci/rust/actions/runs/14057457007/job/39364171058)
Build commit: c19c3fbac0c3230987fe8ccfcb40573cd8ef9b14 (`c19c3fbac0c3230987fe8ccfcb40573cd8ef9b14`)
<!-- homu: {"type":"TryBuildCompleted","builders":{"checks-actions":"https://github.com/rust-lang-ci/rust/actions/runs/14057457007/job/39364171058"},"merge_sha":"c19c3fbac0c3230987fe8ccfcb40573cd8ef9b14"} -->
author_association: COLLABORATOR
user: login: alexcrichton
created_at: 2025-03-25T14:38:47Z
body: @bors: r+
author_association: MEMBER
user: login: bors
created_at: 2025-03-25T14:38:51Z
body: :pushpin: Commit e88c49c454b965c4c60edf19d1305087c9758a29 has been approved by `alexcrichton`

It is now in the [queue](https://bors.rust-lang.org/homu/queue/rust) for this repository.

<!-- @bors r=alexcrichton e88c49c454b965c4c60edf19d1305087c9758a29 -->
<!-- homu: {"type":"Approved","sha":"e88c49c454b965c4c60edf19d1305087c9758a29","approver":"alexcrichton","queue":"https://bors.rust-lang.org/homu/queue/rust"} -->
author_association: COLLABORATOR
user: login: bors
created_at: 2025-03-26T00:06:49Z
body: :hourglass: Testing commit e88c49c454b965c4c60edf19d1305087c9758a29 with merge 068609ce766e55d2e7371cd2a86143a6d7e8e2e4...
<!-- homu: {"type":"BuildStarted","head_sha":"e88c49c454b965c4c60edf19d1305087c9758a29","merge_sha":"068609ce766e55d2e7371cd2a86143a6d7e8e2e4"} -->
author_association: COLLABORATOR
user: login: bors
created_at: 2025-03-26T03:20:18Z
body: :sunny: Test successful - [checks-actions](https://github.com/rust-lang-ci/rust/actions/runs/14072495238/job/39415629776)
Approved by: alexcrichton
Pushing 068609ce766e55d2e7371cd2a86143a6d7e8e2e4 to master...
<!-- homu: {"type":"BuildCompleted","approved_by":"alexcrichton","base_ref":"master","builders":{"checks-actions":"https://github.com/rust-lang-ci/rust/actions/runs/14072495238/job/39415629776"},"merge_sha":"068609ce766e55d2e7371cd2a86143a6d7e8e2e4"} -->
author_association: COLLABORATOR
user: login: github-actions[bot]
created_at: 2025-03-26T03:22:22Z
body: <details>
<summary>What is this?</summary>
This is an experimental post-merge analysis report that shows differences in test outcomes between the merged PR and its parent PR.
</details>


Comparing 43f0014ef0f242418674f49052ed39b70f73bc1c (parent) -> 068609ce766e55d2e7371cd2a86143a6d7e8e2e4 (this PR)

# Test differences
<details>
<summary>Show 288 test diffs
</summary>


- `errors::verify_monomorphize_wasm_c_abi_transition_11 (stage 1)`: [missing] -> pass (**J0**)
- `[ui] tests/ui/lint/wasm_c_abi_transition.rs (stage 2)`: [missing] -> pass (**J1**)
- `[ui] tests/ui/lint/wasm_c_abi_transition.rs (stage 1)`: [missing] -> pass (**J2**)

Additionally, 285 doctest diffs were found. These are ignored, as they are noisy.

**Job group index**

- **J0**: `aarch64-apple`, `aarch64-gnu`, `i686-gnu-2`, `i686-gnu-nopt-2`, `i686-mingw-2`, `i686-mingw-3`, `i686-msvc-2`, `x86_64-apple-1`, `x86_64-gnu`, `x86_64-gnu-llvm-18-3`, `x86_64-gnu-llvm-19-3`, `x86_64-gnu-nopt`, `x86_64-gnu-stable`, `x86_64-mingw-2`, `x86_64-msvc-2`
- **J1**: `aarch64-apple`, `aarch64-gnu`, `arm-android`, `armhf-gnu`, `dist-i586-gnu-i586-i686-musl`, `i686-gnu-1`, `i686-gnu-nopt-1`, `i686-msvc-1`, `test-various`, `x86_64-apple-2`, `x86_64-gnu`, `x86_64-gnu-llvm-18-1`, `x86_64-gnu-llvm-18-2`, `x86_64-gnu-llvm-19-1`, `x86_64-gnu-llvm-19-2`, `x86_64-gnu-nopt`, `x86_64-gnu-stable`, `x86_64-mingw-1`, `x86_64-msvc-1`
- **J2**: `x86_64-gnu-llvm-18-3`, `x86_64-gnu-llvm-19-3`
</details>


author_association: CONTRIBUTOR
user: login: rust-timer
created_at: 2025-03-26T04:38:12Z
body: Finished benchmarking commit (068609ce766e55d2e7371cd2a86143a6d7e8e2e4): [comparison URL](https://perf.rust-lang.org/compare.html?start=43f0014ef0f242418674f49052ed39b70f73bc1c&end=068609ce766e55d2e7371cd2a86143a6d7e8e2e4&stat=instructions:u).

### Overall result: no relevant changes - no action needed


@rustbot label: -perf-regression



### [Instruction count](https://perf.rust-lang.org/compare.html?start=43f0014ef0f242418674f49052ed39b70f73bc1c&end=068609ce766e55d2e7371cd2a86143a6d7e8e2e4&stat=instructions:u)
This benchmark run did not return any relevant results for this metric.

### [Max RSS (memory usage)](https://perf.rust-lang.org/compare.html?start=43f0014ef0f242418674f49052ed39b70f73bc1c&end=068609ce766e55d2e7371cd2a86143a6d7e8e2e4&stat=max-rss)
<details>
<summary>Results (primary -1.1%, secondary -0.6%)</summary>

This is a less reliable metric that may be of interest but was not used to determine the overall result at the top of this comment.

|                                    | mean  | range          | count |
|:----------------------------------:|:-----:|:--------------:|:-----:|
| Regressions ❌ <br /> (primary)    | -     | -              | 0     |
| Regressions ❌ <br /> (secondary)  | 3.4%  | [3.4%, 3.4%]   | 1     |
| Improvements ✅ <br /> (primary)   | -1.1% | [-1.1%, -1.1%] | 1     |
| Improvements ✅ <br /> (secondary) | -2.6% | [-2.7%, -2.5%] | 2     |
| All ❌✅ (primary)                 | -1.1% | [-1.1%, -1.1%] | 1     |
</details>

### [Cycles](https://perf.rust-lang.org/compare.html?start=43f0014ef0f242418674f49052ed39b70f73bc1c&end=068609ce766e55d2e7371cd2a86143a6d7e8e2e4&stat=cycles:u)
This benchmark run did not return any relevant results for this metric.

### [Binary size](https://perf.rust-lang.org/compare.html?start=43f0014ef0f242418674f49052ed39b70f73bc1c&end=068609ce766e55d2e7371cd2a86143a6d7e8e2e4&stat=size:linked_artifact)
This benchmark run did not return any relevant results for this metric.

**Bootstrap**: 777.618s -> 777.496s (-0.02%)
**Artifact size**: 365.81 MiB -> 365.89 MiB (0.02%)
author_association: COLLABORATOR