From cd86be17678c27109b4d3c1437b5b9d69798af8a Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Fri, 10 Jul 2026 12:01:47 +0000 Subject: [PATCH 1/3] [PAC] Include discriminator in `FnAbi`, add `llvm.ptrauth.resign` This patch introduces the following: * Extends `FnAbi` (`callconv`) with a `ptrauth_type_discriminator` field. This field is only used when emitting pointer authentication call bundles. It is stored in `FnAbi` because the call site is not guaranteed to have access to an `Instance`, so the discriminator cannot always be computed on demand. * Adds support for `llvm.ptrauth.resign`. This intrinsic will be used when support for semantic transmute is added. * Performs a minor API redesign as groundwork for allowing call sites to modify schemas in place. --- compiler/rustc_codegen_gcc/src/builder.rs | 11 ++++++++ compiler/rustc_codegen_gcc/src/common.rs | 2 +- compiler/rustc_codegen_gcc/src/context.rs | 2 +- compiler/rustc_codegen_gcc/src/int.rs | 1 + compiler/rustc_codegen_llvm/src/builder.rs | 28 ++++++++++++++++++- compiler/rustc_codegen_llvm/src/common.rs | 23 ++++++++------- compiler/rustc_codegen_llvm/src/context.rs | 4 +-- .../rustc_codegen_ssa/src/traits/builder.rs | 9 ++++++ .../rustc_codegen_ssa/src/traits/consts.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/misc.rs | 2 +- compiler/rustc_session/src/session.rs | 25 ++++++++++++++--- compiler/rustc_target/src/callconv/mod.rs | 8 ++++-- compiler/rustc_ty_utils/src/abi.rs | 6 ++++ tests/ui/abi/c-zst.aarch64-darwin.stderr | 1 + tests/ui/abi/c-zst.powerpc-linux.stderr | 1 + tests/ui/abi/c-zst.s390x-linux.stderr | 1 + tests/ui/abi/c-zst.sparc-linux.stderr | 1 + tests/ui/abi/c-zst.sparc-none.stderr | 1 + tests/ui/abi/c-zst.sparc64-linux.stderr | 1 + tests/ui/abi/c-zst.x86_64-linux.stderr | 1 + .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 1 + tests/ui/abi/debug.generic.stderr | 12 ++++++++ tests/ui/abi/debug.loongarch64.stderr | 12 ++++++++ tests/ui/abi/debug.riscv64.stderr | 12 ++++++++ .../x86-64-sysv64-arg-ext.apple.stderr | 6 ++++ .../x86-64-sysv64-arg-ext.other.stderr | 6 ++++ tests/ui/abi/pass-indirectly-attr.stderr | 2 ++ tests/ui/abi/sysv64-zst.stderr | 1 + .../pass-by-value-abi.aarch64.stderr | 1 + .../c-variadic/pass-by-value-abi.win.stderr | 1 + .../pass-by-value-abi.x86_64.stderr | 3 ++ 31 files changed, 164 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 79b85942d33b9..b60bb27308fe2 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1917,6 +1917,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn fptosi_sat(&mut self, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> { self.fptoint_sat(true, val, dest_ty) } + + fn ptrauth_resign( + &mut self, + _value: Self::Value, + _old_key: u32, + _old_discriminator: u64, + _new_key: u32, + _new_discriminator: u64, + ) -> Self::Value { + bug!("Resigning of pointers not implemented"); + } } impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs index 21d92c6cc2936..42b92f55e0e80 100644 --- a/compiler/rustc_codegen_gcc/src/common.rs +++ b/compiler/rustc_codegen_gcc/src/common.rs @@ -332,7 +332,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>, - _schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index b57e0fb2cd23a..34eaef676a7d3 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -456,7 +456,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - _pointer_auth_schema: Option<&PointerAuthSchema>, + _ptrauth_schema: Option, ) -> RValue<'gcc> { let func_name = self.tcx.symbol_name(instance).name; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 5cb4b712b9297..f2abf08e54ed3 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -424,6 +424,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fixed_count: 3, conv: CanonAbi::C, can_unwind: false, + ptrauth_discriminator: 0, }; fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 7d59beb958104..9dbbd589c8769 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1563,6 +1563,30 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx); attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]); } + + fn ptrauth_resign( + &mut self, + value: &'ll Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> &'ll Value { + let ptr_as_int = self.ptrtoint(value, self.type_i64()); + let resigned_int = self.call_intrinsic( + "llvm.ptrauth.resign", + &[], + &[ + ptr_as_int, + self.const_i32(old_key as i32), + self.const_i64(old_discriminator as i64), + self.const_i32(new_key as i32), + self.const_i64(new_discriminator as i64), + ], + ); + + self.inttoptr(resigned_int, self.val_ty(value)) + } } impl<'ll> StaticBuilderMethods for Builder<'_, 'll, '_> { @@ -2204,11 +2228,13 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // bundles. // Once this is resolved, we should analyze each call and skip direct calls. See the // discussion in the rust-lang issue: + let discriminator = fn_abi?.ptrauth_discriminator; + Some(llvm::OperandBundleBox::new( "ptrauth", &[ self.const_u32(schema.key as u32), - self.const_u64(schema.constant_discriminator as u64), + self.const_u64(discriminator as u64), ], )) } diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 6e8f005be9569..caeda834dd775 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -30,11 +30,9 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( cx: &CodegenCx<'ll, '_>, instance: Instance<'tcx>, llfn: &'ll llvm::Value, - schema: &PointerAuthSchema, + ptrauth_schema: PointerAuthSchema, ) -> &'ll llvm::Value { - if cx.tcx.sess.pointer_authentication_functions().is_none() { - return llfn; - } + assert!(cx.tcx.sess.pointer_authentication_functions().is_some()); // Only free functions or methods let def_id = instance.def_id(); @@ -54,7 +52,7 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( return llfn; } - let addr_diversity = match schema.is_address_discriminated { + let addr_diversity = match ptrauth_schema.is_address_discriminated { PointerAuthAddressDiscriminator::HardwareAddress(true) => Some(llfn), PointerAuthAddressDiscriminator::HardwareAddress(false) => None, PointerAuthAddressDiscriminator::Synthetic(val) => { @@ -63,7 +61,12 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( Some(unsafe { llvm::LLVMConstIntToPtr(llval, llty) }) } }; - const_ptr_auth(llfn, schema.key as u32, schema.constant_discriminator as u64, addr_diversity) + const_ptr_auth( + llfn, + ptrauth_schema.key as u32, + ptrauth_schema.constant_discriminator as u64, + addr_diversity, + ) } /* @@ -179,11 +182,11 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { &self, global_alloc: GlobalAlloc<'tcx>, need_symbol_name: bool, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Result<&'ll Value, u64> { let alloc = match global_alloc { GlobalAlloc::Function { instance, .. } => { - return Ok(self.get_fn_addr(instance, schema)); + return Ok(self.get_fn_addr(instance, ptrauth_schema)); } GlobalAlloc::Static(def_id) => { assert!(self.tcx.is_static(def_id)); @@ -405,7 +408,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { cv: Scalar, layout: abi::Scalar, llty: &'ll Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() }; match cv { @@ -422,7 +425,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> { let (prov, offset) = ptr.prov_and_relative_offset(); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); let base_addr_space = global_alloc.address_space(self); - let base_addr = match self.alloc_to_backend(global_alloc, false, schema) { + let base_addr = match self.alloc_to_backend(global_alloc, false, ptrauth_schema) { Ok(base_addr) => base_addr, Err(base_addr) => { let val = base_addr.wrapping_add(offset.bytes()); diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 1a323e550623b..1026e21126838 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -956,7 +956,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> &'ll Value { // When pointer authentication metadata is provided, `get_fn_addr` will // attempt to sign the pointer using LLVM's `ConstPtrAuth` constant @@ -971,7 +971,7 @@ impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> { // , and comment in // builder's `ptrauth_operand_bundle`. let llfn = get_fn(self, instance); - match pointer_auth_schema { + match ptrauth_schema { Some(schema) => common::maybe_sign_fn_ptr(self, instance, llfn, schema), None => llfn, } diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 203274ccbb9fb..54ca0a7555ae1 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -690,4 +690,13 @@ pub trait BuilderMethods<'a, 'tcx>: fn zext(&mut self, val: Self::Value, dest_ty: Self::Type) -> Self::Value; fn apply_attrs_to_cleanup_callsite(&mut self, llret: Self::Value); + + fn ptrauth_resign( + &mut self, + value: Self::Value, + old_key: u32, + old_discriminator: u64, + new_key: u32, + new_discriminator: u64, + ) -> Self::Value; } diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs index b4eba38d39c19..b45b5667be6c9 100644 --- a/compiler/rustc_codegen_ssa/src/traits/consts.rs +++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs @@ -47,7 +47,7 @@ pub trait ConstCodegenMethods: BackendTypes { cv: Scalar, layout: abi::Scalar, llty: Self::Type, - schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn const_ptr_byte_offset(&self, val: Self::Value, offset: abi::Size) -> Self::Value; diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs index add7128a2974b..3d1a931a12e83 100644 --- a/compiler/rustc_codegen_ssa/src/traits/misc.rs +++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs @@ -22,7 +22,7 @@ pub trait MiscCodegenMethods<'tcx>: BackendTypes { fn get_fn_addr( &self, instance: Instance<'tcx>, - pointer_auth_schema: Option<&PointerAuthSchema>, + ptrauth_schema: Option, ) -> Self::Value; fn eh_personality(&self) -> Self::Function; fn sess(&self) -> &Session; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index f068aaa584dce..1c39124b995e7 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -95,6 +95,7 @@ pub enum PointerAuthARM8_3Key { } /// Forms of extra discrimination. +#[derive(Clone, Debug, PartialEq)] pub enum PointerAuthDiscrimination { /// No additional discrimination. None, @@ -107,6 +108,7 @@ pub enum PointerAuthDiscrimination { } /// Types of address discrimination. +#[derive(Clone, Debug)] pub enum PointerAuthAddressDiscriminator { /// Enable/disable hardware address discrimination. HardwareAddress(bool), @@ -115,6 +117,7 @@ pub enum PointerAuthAddressDiscriminator { Synthetic(u64), } +#[derive(Clone, Debug)] pub struct PointerAuthSchema { pub is_address_discriminated: PointerAuthAddressDiscriminator, pub discrimination_kind: PointerAuthDiscrimination, @@ -1268,12 +1271,26 @@ impl Session { self.pointer_auth_config.is_some() } - pub fn pointer_authentication_functions(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.as_ref()) + pub fn pointer_authentication_functions(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.function_pointers.clone()) } - pub fn pointer_authentication_init_fini(&self) -> Option<&PointerAuthSchema> { - self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.as_ref()) + pub fn pointer_authentication_init_fini(&self) -> Option { + self.pointer_auth_config.as_ref().and_then(|cfg| cfg.init_fini.clone()) + } + + pub fn pointer_authentication_fn_ptr_type_discrimination(&self) -> bool { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .is_some_and(|schema| schema.discrimination_kind == PointerAuthDiscrimination::Type) + } + + pub fn pointer_authentication_fn_ptr_key(&self) -> Option { + self.pointer_auth_config + .as_ref() + .and_then(|cfg| cfg.function_pointers.as_ref()) + .map(|schema| schema.key) } } diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index bb9dd84962060..4784b83799d1d 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -676,12 +676,15 @@ pub struct FnAbi<'a, Ty> { pub conv: CanonAbi, /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, + /// Computed type discriminator for pointer authentication purpose. + pub ptrauth_discriminator: u64, } // Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl. impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind } = self; + let FnAbi { args, ret, c_variadic, fixed_count, conv, can_unwind, ptrauth_discriminator } = + self; f.debug_struct("FnAbi") .field("args", args) .field("ret", ret) @@ -689,6 +692,7 @@ impl<'a, Ty: fmt::Display> fmt::Debug for FnAbi<'a, Ty> { .field("fixed_count", fixed_count) .field("conv", conv) .field("can_unwind", can_unwind) + .field("ptrauth_discriminator", ptrauth_discriminator) .finish() } } @@ -1020,6 +1024,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ArgAbi<'_, usize>, 56); - static_assert_size!(FnAbi<'_, usize>, 80); + static_assert_size!(FnAbi<'_, usize>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 5c72f6cba3989..baf0e4d27dfe3 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -6,6 +6,7 @@ use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; +use rustc_middle::ptrauth::ptrauth_compute_fn_ptr_type_discriminator_for; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ FnAbiError, HasTyCtxt, HasTypingEnv, LayoutCx, LayoutOf, TyAndLayout, fn_can_unwind, @@ -613,6 +614,11 @@ fn fn_abi_new_uncached<'tcx>( }), sig.abi(), ), + ptrauth_discriminator: if tcx.sess.pointer_authentication_fn_ptr_type_discrimination() { + ptrauth_compute_fn_ptr_type_discriminator_for(tcx, sig).unwrap_or(0).into() + } else { + 0 + }, }; fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi()); debug!("fn_abi_new_uncached = {:?}", fn_abi); diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.sparc-linux.stderr b/tests/ui/abi/c-zst.sparc-linux.stderr index da26a7b651ddd..845992fcf57c6 100644 --- a/tests/ui/abi/c-zst.sparc-linux.stderr +++ b/tests/ui/abi/c-zst.sparc-linux.stderr @@ -72,6 +72,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.sparc-none.stderr b/tests/ui/abi/c-zst.sparc-none.stderr index da26a7b651ddd..845992fcf57c6 100644 --- a/tests/ui/abi/c-zst.sparc-none.stderr +++ b/tests/ui/abi/c-zst.sparc-none.stderr @@ -72,6 +72,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 9241ea32d9693..8bfa285b05e30 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -61,6 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 6f2b69f80ae45..63e38800c527a 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -108,6 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:31:1 | @@ -285,6 +286,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:43:1 | @@ -358,6 +360,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:46:1 | @@ -438,6 +441,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -506,6 +510,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:65:1 | @@ -587,6 +592,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -662,6 +668,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:68:1 | @@ -736,6 +743,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -804,6 +812,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:71:1 | @@ -878,6 +887,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -946,6 +956,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:75:1 | @@ -1042,6 +1053,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 2159753e15fcd..cabe9bdcb267f 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -108,6 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:31:1 | @@ -285,6 +286,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:43:1 | @@ -358,6 +360,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:46:1 | @@ -438,6 +441,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -506,6 +510,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:65:1 | @@ -587,6 +592,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -662,6 +668,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:68:1 | @@ -736,6 +743,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -804,6 +812,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:71:1 | @@ -878,6 +887,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -946,6 +956,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:75:1 | @@ -1042,6 +1053,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 2159753e15fcd..cabe9bdcb267f 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -108,6 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:31:1 | @@ -285,6 +286,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:43:1 | @@ -358,6 +360,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:46:1 | @@ -438,6 +441,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -506,6 +510,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:65:1 | @@ -587,6 +592,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -662,6 +668,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:68:1 | @@ -736,6 +743,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -804,6 +812,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:71:1 | @@ -878,6 +887,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } right ABI = FnAbi { args: [ @@ -946,6 +956,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:75:1 | @@ -1042,6 +1053,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: 0, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr index 74763e490f332..38059f903eb43 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr @@ -71,6 +71,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -150,6 +151,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -229,6 +231,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -308,6 +311,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -387,6 +391,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -466,6 +471,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr index f8e8cbfae6af5..74ebb52aabaf6 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr @@ -71,6 +71,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -150,6 +151,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -229,6 +231,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -308,6 +311,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -387,6 +391,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -466,6 +471,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index 6231c8b2682da..849d9aecf866c 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -85,6 +85,7 @@ error: fn_abi_of(extern_c) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-indirectly-attr.rs:20:1 | @@ -178,6 +179,7 @@ error: fn_abi_of(extern_rust) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-indirectly-attr.rs:27:1 | diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 5fc85190db529..9b14e216399ca 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -63,6 +63,7 @@ error: fn_abi_of(pass_zst) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/sysv64-zst.rs:8:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index 052f21ad81f57..af87c771037c4 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -72,6 +72,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr index 08e196c7a88aa..7e49d362e1143 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.win.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -68,6 +68,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index a8aa8f15b497f..e0558c3d52e6e 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -72,6 +72,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-by-value-abi.rs:27:1 | @@ -154,6 +155,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { SysV64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-by-value-abi.rs:37:1 | @@ -236,6 +238,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { Win64, ), can_unwind: false, + ptrauth_discriminator: 0, } --> $DIR/pass-by-value-abi.rs:44:1 | From eb922054414ed139efe6ae61f25edf2d80e3bd59 Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 20 Aug 2026 06:47:34 +0000 Subject: [PATCH 2/3] [PAC] Use Option in FnAbi's discriminator field --- compiler/rustc_codegen_gcc/src/int.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 7 +++++- compiler/rustc_target/src/callconv/mod.rs | 4 +-- compiler/rustc_ty_utils/src/abi.rs | 4 +-- tests/ui/abi/c-zst.aarch64-darwin.stderr | 2 +- tests/ui/abi/c-zst.powerpc-linux.stderr | 2 +- tests/ui/abi/c-zst.s390x-linux.stderr | 2 +- tests/ui/abi/c-zst.sparc64-linux.stderr | 2 +- tests/ui/abi/c-zst.x86_64-linux.stderr | 2 +- .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 2 +- tests/ui/abi/debug.generic.stderr | 25 ++++++++++--------- tests/ui/abi/debug.loongarch64.stderr | 25 ++++++++++--------- tests/ui/abi/debug.riscv64.stderr | 25 ++++++++++--------- .../x86-64-sysv64-arg-ext.apple.stderr | 12 ++++----- .../x86-64-sysv64-arg-ext.other.stderr | 12 ++++----- tests/ui/abi/pass-indirectly-attr.stderr | 4 +-- tests/ui/abi/sysv64-zst.stderr | 2 +- .../pass-by-value-abi.aarch64.stderr | 2 +- .../c-variadic/pass-by-value-abi.win.stderr | 2 +- .../pass-by-value-abi.x86_64.stderr | 6 ++--- 20 files changed, 76 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index f2abf08e54ed3..99a8ff4a6345b 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -424,7 +424,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { fixed_count: 3, conv: CanonAbi::C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, }; fn_abi.adjust_for_foreign_abi(self.cx, ExternAbi::C { unwind: false }); diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9dbbd589c8769..16c7528740019 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2228,7 +2228,12 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { // bundles. // Once this is resolved, we should analyze each call and skip direct calls. See the // discussion in the rust-lang issue: - let discriminator = fn_abi?.ptrauth_discriminator; + // + // If sess().pointer_authentication_fn_ptr_type_discrimination() is enabled, this contains + // the function pointer type discriminator; otherwise, it is None and we fall back to the + // schema's constant discriminator. + let discriminator = + fn_abi?.ptrauth_discriminator.unwrap_or(schema.constant_discriminator.into()); Some(llvm::OperandBundleBox::new( "ptrauth", diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 4784b83799d1d..d9332880040e3 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -677,7 +677,7 @@ pub struct FnAbi<'a, Ty> { /// Indicates if an unwind may happen across a call to this function. pub can_unwind: bool, /// Computed type discriminator for pointer authentication purpose. - pub ptrauth_discriminator: u64, + pub ptrauth_discriminator: Option, } // Needs to be a custom impl because of the bounds on the `TyAndLayout` debug impl. @@ -1024,6 +1024,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ArgAbi<'_, usize>, 56); - static_assert_size!(FnAbi<'_, usize>, 88); + static_assert_size!(FnAbi<'_, usize>, 96); // tidy-alphabetical-end } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index baf0e4d27dfe3..07efc134d5248 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -615,9 +615,9 @@ fn fn_abi_new_uncached<'tcx>( sig.abi(), ), ptrauth_discriminator: if tcx.sess.pointer_authentication_fn_ptr_type_discrimination() { - ptrauth_compute_fn_ptr_type_discriminator_for(tcx, sig).unwrap_or(0).into() + Some(ptrauth_compute_fn_ptr_type_discriminator_for(tcx, sig).unwrap_or(0).into()) } else { - 0 + None }, }; fn_abi_adjust_for_abi(cx, &mut fn_abi, sig.abi()); diff --git a/tests/ui/abi/c-zst.aarch64-darwin.stderr b/tests/ui/abi/c-zst.aarch64-darwin.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.aarch64-darwin.stderr +++ b/tests/ui/abi/c-zst.aarch64-darwin.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.x86_64-linux.stderr b/tests/ui/abi/c-zst.x86_64-linux.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.x86_64-linux.stderr +++ b/tests/ui/abi/c-zst.x86_64-linux.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 8bfa285b05e30..0150534e8e61e 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -61,7 +61,7 @@ error: fn_abi_of(pass_zst) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/c-zst.rs:67:1 | diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 63e38800c527a..62728320a522b 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -108,7 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -203,6 +203,7 @@ error: fn_abi_of(test_unsized) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -286,7 +287,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:43:1 | @@ -360,7 +361,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:46:1 | @@ -441,7 +442,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -510,7 +511,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -592,7 +593,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -668,7 +669,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:68:1 | @@ -743,7 +744,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -812,7 +813,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:71:1 | @@ -887,7 +888,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -956,7 +957,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:75:1 | @@ -1053,7 +1054,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index cabe9bdcb267f..7672e0ea2fc68 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -108,7 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -203,6 +203,7 @@ error: fn_abi_of(test_unsized) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -286,7 +287,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:43:1 | @@ -360,7 +361,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:46:1 | @@ -441,7 +442,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -510,7 +511,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -592,7 +593,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -668,7 +669,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:68:1 | @@ -743,7 +744,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -812,7 +813,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:71:1 | @@ -887,7 +888,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -956,7 +957,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:75:1 | @@ -1053,7 +1054,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index cabe9bdcb267f..7672e0ea2fc68 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -108,7 +108,7 @@ error: fn_abi_of(test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:31:1 | @@ -203,6 +203,7 @@ error: fn_abi_of(test_unsized) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, + ptrauth_discriminator: None, } --> $DIR/debug.rs:37:1 | @@ -286,7 +287,7 @@ error: fn_abi_of(TestFnPtr) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:43:1 | @@ -360,7 +361,7 @@ error: fn_abi_of(test_generic) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:46:1 | @@ -441,7 +442,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -510,7 +511,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:65:1 | @@ -592,7 +593,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -668,7 +669,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:68:1 | @@ -743,7 +744,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -812,7 +813,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:71:1 | @@ -887,7 +888,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } right ABI = FnAbi { args: [ @@ -956,7 +957,7 @@ error: ABIs are not compatible fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:75:1 | @@ -1053,7 +1054,7 @@ error: fn_abi_of(assoc_test) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: $SOME_BOOL, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/debug.rs:58:5 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr index 38059f903eb43..8a61bc36c7696 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.apple.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -151,7 +151,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -231,7 +231,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -311,7 +311,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -391,7 +391,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -471,7 +471,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr index 74ebb52aabaf6..9ecb265c57fb9 100644 --- a/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr +++ b/tests/ui/abi/numbers-arithmetic/x86-64-sysv64-arg-ext.other.stderr @@ -71,7 +71,7 @@ error: fn_abi_of(i8) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:13:1 | @@ -151,7 +151,7 @@ error: fn_abi_of(u8) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:19:1 | @@ -231,7 +231,7 @@ error: fn_abi_of(i16) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:25:1 | @@ -311,7 +311,7 @@ error: fn_abi_of(u16) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:31:1 | @@ -391,7 +391,7 @@ error: fn_abi_of(i32) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:37:1 | @@ -471,7 +471,7 @@ error: fn_abi_of(u32) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/x86-64-sysv64-arg-ext.rs:43:1 | diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index 849d9aecf866c..aa644800ef9f4 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -85,7 +85,7 @@ error: fn_abi_of(extern_c) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:20:1 | @@ -179,7 +179,7 @@ error: fn_abi_of(extern_rust) = FnAbi { fixed_count: 1, conv: Rust, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-indirectly-attr.rs:27:1 | diff --git a/tests/ui/abi/sysv64-zst.stderr b/tests/ui/abi/sysv64-zst.stderr index 9b14e216399ca..e8a9f9489749b 100644 --- a/tests/ui/abi/sysv64-zst.stderr +++ b/tests/ui/abi/sysv64-zst.stderr @@ -63,7 +63,7 @@ error: fn_abi_of(pass_zst) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/sysv64-zst.rs:8:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index af87c771037c4..484a1fefcb0f0 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -72,7 +72,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.win.stderr b/tests/ui/c-variadic/pass-by-value-abi.win.stderr index 7e49d362e1143..5abbb48ed6240 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.win.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.win.stderr @@ -68,7 +68,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index e0558c3d52e6e..68ebe20b4974e 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -72,7 +72,7 @@ error: fn_abi_of(take_va_list) = FnAbi { fixed_count: 1, conv: C, can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:27:1 | @@ -155,7 +155,7 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { SysV64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:37:1 | @@ -238,7 +238,7 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { Win64, ), can_unwind: false, - ptrauth_discriminator: 0, + ptrauth_discriminator: None, } --> $DIR/pass-by-value-abi.rs:44:1 | From 3eef4a299b6afe3e39bc5e37f20c5d9c8f8e2e1d Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 10 Sep 2026 13:33:36 +0000 Subject: [PATCH 3/3] [PAC] repr(transparent) and correct handling of Option in encoder Also tighten the handling of enums. --- compiler/rustc_codegen_llvm/src/builder.rs | 5 +- .../rustc_middle/src/ptrauth/discriminator.rs | 72 ++++++++++++------- 2 files changed, 46 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 16c7528740019..6a00e56f9ab6a 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2237,10 +2237,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { Some(llvm::OperandBundleBox::new( "ptrauth", - &[ - self.const_u32(schema.key as u32), - self.const_u64(discriminator as u64), - ], + &[self.const_u32(schema.key as u32), self.const_u64(discriminator as u64)], )) } diff --git a/compiler/rustc_middle/src/ptrauth/discriminator.rs b/compiler/rustc_middle/src/ptrauth/discriminator.rs index d44ecafb775ef..0ff48ff3d54db 100644 --- a/compiler/rustc_middle/src/ptrauth/discriminator.rs +++ b/compiler/rustc_middle/src/ptrauth/discriminator.rs @@ -81,6 +81,7 @@ use rustc_session::PointerAuthSchema; use rustc_span::sym; use crate::ptrauth::llvm_siphash::llvm_pointer_auth_stable_siphash; +use crate::ty::layout::LayoutCx; /// Types that can serve as a source for function pointer type discrimination. /// @@ -315,35 +316,46 @@ enum ClangDiscTy<'tcx> { Void, } -// Canonicalize Option-wrapped pointer types used to model C nullable pointers. +// Canonicalize types that are ABI-compatible with C's nullable pointer +// convention, so the rest of this encoder can treat them like the corresponding +// plain pointer type. // -// Rust and Clang should compute identical discriminators for equivalent C APIs. -// Clang does not distinguish nullable from non-nullable pointer types when -// computing function pointer authentication discriminators, so -// `Option` and `Option<*mut T>` are encoded identically to their -// underlying pointer types. +// Rust guarantees the null-pointer optimization for references, function +// pointers, Box, NonNull, and NonZero*. `Option` and `Option<&T>` are +// therefore unwrapped here. `Option<*mut T>` and `Option<*const T>` are +// deliberately left unchanged: raw pointers are not covered by the NPO +// guarantee and are handled by the general `Adt` arm in `to_clang_disc_ty`. // -// Although `Option<*mut T>` is not considered FFI-safe by Rust and triggers the -// `improper_ctypes`/`improper_ctypes_definitions` lints, this is a warning -// rather than a hard error. Canonicalizing it here preserves Clang-compatible -// discriminator computation. -// -// Please see the following tests for sample use cases: -// pauth-fn-ptr-type-discrimination-option-callback.rs, -// pauth-fn-ptr-type-discrimination-option-return.rs and pauth-fn-ptr-type-discrimination-option.rs -fn canonicalize_c_type<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { - if let ty::Adt(def, args) = ty.kind() - && tcx.is_diagnostic_item(sym::Option, def.did()) - { - let inner = args.type_at(0); - - match inner.kind() { - ty::FnPtr(..) | ty::RawPtr(..) => return inner, - _ => {} +// Also peels `repr(transparent)` wrappers to canonicalize them to their +// underlying type. +fn canonicalize_c_type<'tcx>(tcx: TyCtxt<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> { + loop { + let before = ty; + + if let ty::Adt(def, args) = ty.kind() + && tcx.is_diagnostic_item(sym::Option, def.did()) + { + let inner = args.type_at(0); + if let ty::FnPtr(..) | ty::Ref(..) = inner.kind() { + ty = inner; + } } - } - ty + // Only ADTs can be repr(transparent); skip the layout query entirely + // for everything else. + if matches!(ty.kind(), ty::Adt(..)) { + let typing_env = ty::TypingEnv::fully_monomorphized(); + + if let Ok(layout) = tcx.layout_of(typing_env.as_query_input(ty)) { + let cx = LayoutCx::new(tcx, typing_env); + ty = layout.peel_transparent_wrappers_from_non_1zst(&cx).ty; + } + } + + if ty == before { + return ty; + } + } } /// Lowers a Rust type into a Clang-compatible discriminator type. @@ -386,8 +398,14 @@ fn to_clang_disc_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ClangDiscTy<'tcx> // arrays ignore size ty::Array(elem, _) => ClangDiscTy::Array { elem: *elem }, - // enums to integer collapse - ty::Adt(def, _) if def.is_enum() => ClangDiscTy::EnumLikeInt, + // enums to integer collapse - mirrors Clang's Type::Enum handling, + // which recurses into the enum's underlying integer type per C11 + // 6.7.2.2p4. + // A non-niche, data-carrying enum (e.g. Option<*mut T>) is not an + // "enumerated type" in the C11 sense, such enums fall through to the + // general Adt(_) => AdtName(..) arm below instead. + ty::Adt(def, _) if def.is_enum() && def.is_payloadfree() => ClangDiscTy::EnumLikeInt, + // simd vectors ty::Adt(def, args) if def.repr().simd() => { // Clang encodes SIMD vectors by their total size