From e245570def155191b61f73647eb543dd45685b2f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 24 Jun 2025 22:29:54 +0000 Subject: [PATCH 1/2] Add rust-invalid ABI --- compiler/rustc_abi/src/extern_abi.rs | 5 +++++ compiler/rustc_ast_lowering/src/stability.rs | 3 +++ compiler/rustc_middle/src/ty/layout.rs | 3 ++- compiler/rustc_smir/src/rustc_internal/internal.rs | 1 + compiler/rustc_smir/src/rustc_smir/convert/ty.rs | 1 + compiler/rustc_smir/src/stable_mir/ty.rs | 1 + compiler/rustc_target/src/spec/abi_map.rs | 3 ++- tests/ui/abi/invalid-call-abi.rs | 12 ++++++++++++ tests/ui/abi/invalid-call-abi.stderr | 9 +++++++++ tests/ui/print-calling-conventions.stdout | 1 + 10 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 tests/ui/abi/invalid-call-abi.rs create mode 100644 tests/ui/abi/invalid-call-abi.stderr diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs index 7457ae1f03344..1b8c2de15880e 100644 --- a/compiler/rustc_abi/src/extern_abi.rs +++ b/compiler/rustc_abi/src/extern_abi.rs @@ -36,6 +36,10 @@ pub enum ExternAbi { /// Stronger than just `#[cold]` because `fn` pointers might be incompatible. RustCold, + /// An always-invalid ABI that's used to test "this ABI is not supported by this platform" + /// in a platform-agnostic way. + RustInvalid, + /// Unstable impl detail that directly uses Rust types to describe the ABI to LLVM. /// Even normally-compatible Rust types can become ABI-incompatible with this ABI! Unadjusted, @@ -157,6 +161,7 @@ abi_impls! { RiscvInterruptS =><= "riscv-interrupt-s", RustCall =><= "rust-call", RustCold =><= "rust-cold", + RustInvalid =><= "rust-invalid", Stdcall { unwind: false } =><= "stdcall", Stdcall { unwind: true } =><= "stdcall-unwind", System { unwind: false } =><= "system", diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs index b8fa2dd3dd626..9b60807e65085 100644 --- a/compiler/rustc_ast_lowering/src/stability.rs +++ b/compiler/rustc_ast_lowering/src/stability.rs @@ -96,6 +96,9 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> { ExternAbi::RustCold => { Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental }) } + ExternAbi::RustInvalid => { + Err(UnstableAbi { abi, feature: sym::rustc_attrs, explain: GateReason::ImplDetail }) + } ExternAbi::GpuKernel => Err(UnstableAbi { abi, feature: sym::abi_gpu_kernel, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 13c281a618270..5cb943b0d8c66 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1253,7 +1253,8 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option, abi: ExternAbi) | CCmseNonSecureCall | CCmseNonSecureEntry | Custom - | Unadjusted => false, + | Unadjusted + | RustInvalid => false, Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind, } } diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index a4c6f18622218..c0d9937e34de6 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -494,6 +494,7 @@ impl RustcInternal for Abi { Abi::RustCall => rustc_abi::ExternAbi::RustCall, Abi::Unadjusted => rustc_abi::ExternAbi::Unadjusted, Abi::RustCold => rustc_abi::ExternAbi::RustCold, + Abi::RustInvalid => rustc_abi::ExternAbi::RustInvalid, Abi::RiscvInterruptM => rustc_abi::ExternAbi::RiscvInterruptM, Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS, Abi::Custom => rustc_abi::ExternAbi::Custom, diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index b4239ddd896ec..2c652c7546e9c 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -877,6 +877,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi { ExternAbi::RustCall => Abi::RustCall, ExternAbi::Unadjusted => Abi::Unadjusted, ExternAbi::RustCold => Abi::RustCold, + ExternAbi::RustInvalid => Abi::RustInvalid, ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM, ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS, ExternAbi::Custom => Abi::Custom, diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/rustc_smir/src/stable_mir/ty.rs index 4415cd6e2e3ba..1ae79491642d5 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/rustc_smir/src/stable_mir/ty.rs @@ -1126,6 +1126,7 @@ pub enum Abi { RustCold, RiscvInterruptM, RiscvInterruptS, + RustInvalid, Custom, } diff --git a/compiler/rustc_target/src/spec/abi_map.rs b/compiler/rustc_target/src/spec/abi_map.rs index 42ec10a8e157b..ce1bdcbb8acc5 100644 --- a/compiler/rustc_target/src/spec/abi_map.rs +++ b/compiler/rustc_target/src/spec/abi_map.rs @@ -156,7 +156,8 @@ impl AbiMap { | ExternAbi::Msp430Interrupt | ExternAbi::RiscvInterruptM | ExternAbi::RiscvInterruptS - | ExternAbi::X86Interrupt, + | ExternAbi::X86Interrupt + | ExternAbi::RustInvalid, _, ) => return AbiMapping::Invalid, }; diff --git a/tests/ui/abi/invalid-call-abi.rs b/tests/ui/abi/invalid-call-abi.rs new file mode 100644 index 0000000000000..076ddd91ab0f2 --- /dev/null +++ b/tests/ui/abi/invalid-call-abi.rs @@ -0,0 +1,12 @@ +// Tests the `"rustc-invalid"` ABI, which is never canonizable. + +#![feature(rustc_attrs)] + +const extern "rust-invalid" fn foo() { + //~^ ERROR "rust-invalid" is not a supported ABI for the current target + panic!() +} + +fn main() { + foo(); +} diff --git a/tests/ui/abi/invalid-call-abi.stderr b/tests/ui/abi/invalid-call-abi.stderr new file mode 100644 index 0000000000000..c4a90158dcfeb --- /dev/null +++ b/tests/ui/abi/invalid-call-abi.stderr @@ -0,0 +1,9 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/invalid-call-abi.rs:5:14 + | +LL | const extern "rust-invalid" fn foo() { + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`. diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout index 7b5ae49566062..4df6bd27f457f 100644 --- a/tests/ui/print-calling-conventions.stdout +++ b/tests/ui/print-calling-conventions.stdout @@ -20,6 +20,7 @@ riscv-interrupt-m riscv-interrupt-s rust-call rust-cold +rust-invalid stdcall stdcall-unwind system From e776065164f22872e8cadf5bc5e47352c27982dc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 24 Jun 2025 19:32:29 +0000 Subject: [PATCH 2/2] Taint body on invalid call ABI --- compiler/rustc_hir_typeck/src/callee.rs | 11 ++++++++++- tests/ui/abi/invalid-call-abi-ctfe.rs | 14 ++++++++++++++ tests/ui/abi/invalid-call-abi-ctfe.stderr | 9 +++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/ui/abi/invalid-call-abi-ctfe.rs create mode 100644 tests/ui/abi/invalid-call-abi-ctfe.stderr diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 7a3647df0c405..f790c51f8f195 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -156,7 +156,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn check_call_abi(&self, abi: ExternAbi, span: Span) { let canon_abi = match AbiMap::from_target(&self.sess().target).canonize_abi(abi, false) { AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => canon_abi, - AbiMapping::Invalid => return, + AbiMapping::Invalid => { + // This should be reported elsewhere, but we want to taint this body + // so that we don't try to evaluate calls to ABIs that are invalid. + let guar = self.dcx().span_delayed_bug( + span, + format!("invalid abi for platform should have reported an error: {abi}"), + ); + self.set_tainted_by_errors(guar); + return; + } }; let valid = match canon_abi { diff --git a/tests/ui/abi/invalid-call-abi-ctfe.rs b/tests/ui/abi/invalid-call-abi-ctfe.rs new file mode 100644 index 0000000000000..343cc728fe3b7 --- /dev/null +++ b/tests/ui/abi/invalid-call-abi-ctfe.rs @@ -0,0 +1,14 @@ +// Fix for #142969 where an invalid ABI in a signature still had its call ABI computed +// because CTFE tried to evaluate it, despite previous errors during AST-to-HIR lowering. + +#![feature(rustc_attrs)] + +const extern "rust-invalid" fn foo() { + //~^ ERROR "rust-invalid" is not a supported ABI for the current target + panic!() +} + +const _: () = foo(); + + +fn main() {} diff --git a/tests/ui/abi/invalid-call-abi-ctfe.stderr b/tests/ui/abi/invalid-call-abi-ctfe.stderr new file mode 100644 index 0000000000000..402de4b69b97f --- /dev/null +++ b/tests/ui/abi/invalid-call-abi-ctfe.stderr @@ -0,0 +1,9 @@ +error[E0570]: "rust-invalid" is not a supported ABI for the current target + --> $DIR/invalid-call-abi-ctfe.rs:6:14 + | +LL | const extern "rust-invalid" fn foo() { + | ^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0570`.