Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Debug, Pointer, etc on function pointers for all calling conventions #92964

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,21 @@
#![feature(const_is_char_boundary)]
//
// Language features:
#![feature(abi_amdgpu_kernel)]
#![feature(abi_avr_interrupt)]
#![feature(abi_c_cmse_nonsecure_call)]
#![feature(abi_efiapi)]
#![feature(abi_msp430_interrupt)]
#![feature(abi_ptx)]
#![feature(abi_thiscall)]
#![feature(abi_unadjusted)]
#![feature(abi_vectorcall)]
#![feature(abi_x86_interrupt)]
#![feature(allow_internal_unsafe)]
#![feature(allow_internal_unstable)]
#![feature(associated_type_bounds)]
#![feature(auto_traits)]
#![feature(c_unwind)]
#![feature(cfg_target_has_atomic)]
#![feature(cfg_target_has_atomic_equal_alignment)]
#![feature(const_fn_floating_point_arithmetic)]
Expand Down Expand Up @@ -206,6 +216,7 @@
#![feature(try_blocks)]
#![feature(unboxed_closures)]
#![feature(unsized_fn_params)]
#![feature(wasm_abi)]
#![feature(asm_const)]
//
// Target features:
Expand Down
5 changes: 3 additions & 2 deletions library/core/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,8 +1394,9 @@ mod prim_ref {}
/// [`Pointer`]: fmt::Pointer
///
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
/// may change.
/// functions that take 12 arguments or less. In the future, this may change.
///
/// These traits are implemented on all available ABIs, though the documentation hides them.
///
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
Expand Down
84 changes: 70 additions & 14 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1839,7 +1839,8 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {

// Impls for function pointers
macro_rules! fnptr_impls_safety_abi {
($FnTy: ty, $($Arg: ident),*) => {
($(#[$Meta:meta])? $FnTy: ty, $($Arg: ident),*) => {
$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> PartialEq for $FnTy {
#[inline]
Expand All @@ -1848,9 +1849,11 @@ macro_rules! fnptr_impls_safety_abi {
}
}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> Eq for $FnTy {}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
#[inline]
Expand All @@ -1859,6 +1862,7 @@ macro_rules! fnptr_impls_safety_abi {
}
}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> Ord for $FnTy {
#[inline]
Expand All @@ -1867,13 +1871,15 @@ macro_rules! fnptr_impls_safety_abi {
}
}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
state.write_usize(*self as usize)
}
}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -1886,6 +1892,7 @@ macro_rules! fnptr_impls_safety_abi {
}
}

$(#[$Meta])?
#[stable(feature = "fnptr_impls", since = "1.4.0")]
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Expand All @@ -1900,21 +1907,70 @@ macro_rules! fnptr_impls_safety_abi {
}
}

macro_rules! fnptr_impls_args {
($($Arg: ident),+) => {
fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
// #[doc(hidden)] is applied by default due to how many permutations are made.
// Without this, the documentation page for `fn` becomes 14 MB.
// In the future, this could be replaced by having rustdoc collapse repetitive ABI impls.
macro_rules! fnptr_impl_for_abi {
($Abi:tt, $($Arg: ident),*) => {
fnptr_impls_safety_abi! { #[doc(hidden)] extern $Abi fn($($Arg),*) -> Ret, $($Arg),* }
fnptr_impls_safety_abi! { #[doc(hidden)] unsafe extern $Abi fn($($Arg),*) -> Ret, $($Arg),* }
};
}

macro_rules! fnptr_impl_for_abi_with_docs {
($Abi:tt, $($Arg: ident),*) => {
fnptr_impls_safety_abi! { extern $Abi fn($($Arg),*) -> Ret, $($Arg),* }
fnptr_impls_safety_abi! { unsafe extern $Abi fn($($Arg),*) -> Ret, $($Arg),* }
};
() => {
}

macro_rules! fnptr_impl_for_abi_variadic_support {
($Abi:tt, ) => {
// No variadic functions with 0 parameters
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
fnptr_impls_safety_abi! { #[doc(hidden)] extern $Abi fn() -> Ret, }
fnptr_impls_safety_abi! { #[doc(hidden)] unsafe extern $Abi fn() -> Ret, }
};

($Abi:tt, $($Arg: ident),*) => {
fnptr_impl_for_abi! { $Abi, $($Arg),* }

fnptr_impls_safety_abi! { #[doc(hidden)] extern $Abi fn($($Arg),*, ...) -> Ret, $($Arg),* }
fnptr_impls_safety_abi! { #[doc(hidden)] unsafe extern $Abi fn($($Arg),*, ...) -> Ret, $($Arg),* }
}
}

macro_rules! fnptr_impls_args {
($($Arg: ident),*) => {
fnptr_impl_for_abi_with_docs! { "Rust", $($Arg),* }

fnptr_impl_for_abi! { "C-cmse-nonsecure-call", $($Arg),* }
fnptr_impl_for_abi! { "C-unwind", $($Arg),* }
fnptr_impl_for_abi! { "aapcs", $($Arg),* }
fnptr_impl_for_abi! { "amdgpu-kernel", $($Arg),* }
fnptr_impl_for_abi! { "avr-interrupt", $($Arg),* }
fnptr_impl_for_abi! { "avr-non-blocking-interrupt", $($Arg),* }
fnptr_impl_for_abi! { "efiapi", $($Arg),* }
fnptr_impl_for_abi! { "fastcall", $($Arg),* }
fnptr_impl_for_abi! { "msp430-interrupt", $($Arg),* }
fnptr_impl_for_abi! { "platform-intrinsic", $($Arg),* }
fnptr_impl_for_abi! { "ptx-kernel", $($Arg),* }
fnptr_impl_for_abi! { "rust-call", $($Arg),* }
fnptr_impl_for_abi! { "rust-intrinsic", $($Arg),* }
fnptr_impl_for_abi! { "stdcall", $($Arg),* }
fnptr_impl_for_abi! { "stdcall-unwind", $($Arg),* }
fnptr_impl_for_abi! { "system", $($Arg),* }
fnptr_impl_for_abi! { "system-unwind", $($Arg),* }
Kampfkarren marked this conversation as resolved.
Show resolved Hide resolved
fnptr_impl_for_abi! { "sysv64", $($Arg),* }
fnptr_impl_for_abi! { "thiscall", $($Arg),* }
fnptr_impl_for_abi! { "thiscall-unwind", $($Arg),* }
fnptr_impl_for_abi! { "unadjusted", $($Arg),* }
fnptr_impl_for_abi! { "vectorcall", $($Arg),* }
fnptr_impl_for_abi! { "wasm", $($Arg),* }
fnptr_impl_for_abi! { "win64", $($Arg),* }
fnptr_impl_for_abi! { "x86-interrupt", $($Arg),* }

fnptr_impl_for_abi_variadic_support! { "C", $($Arg),* }
fnptr_impl_for_abi_variadic_support! { "cdecl", $($Arg),* }
};
}

Expand Down
5 changes: 3 additions & 2 deletions library/std/src/primitive_docs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,8 +1394,9 @@ mod prim_ref {}
/// [`Pointer`]: fmt::Pointer
///
/// Due to a temporary restriction in Rust's type system, these traits are only implemented on
/// functions that take 12 arguments or less, with the `"Rust"` and `"C"` ABIs. In the future, this
/// may change.
/// functions that take 12 arguments or less. In the future, this may change.
///
/// These traits are implemented on all available ABIs, though the documentation hides them.
///
/// In addition, function pointers of *any* signature, ABI, or safety are [`Copy`], and all *safe*
/// function pointers implement [`Fn`], [`FnMut`], and [`FnOnce`]. This works because these traits
Expand Down
11 changes: 11 additions & 0 deletions src/test/ui/function-pointer/function-pointer-impls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// check-pass
fn assert_debug<T: std::fmt::Debug>() {}

fn main() {
assert_debug::<extern "C" fn()>();
assert_debug::<extern "C" fn(argument: u32)>();
assert_debug::<unsafe extern "C" fn(argument: u32)>();
assert_debug::<unsafe extern "C" fn(argument: u32, ...)>();
assert_debug::<fn(argument: u32)>();
assert_debug::<extern "fastcall" fn(argument: u32)>();
}
2 changes: 1 addition & 1 deletion src/test/ui/issues/issue-59488.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ LL | assert_eq!(Foo::Bar, i);
extern "C" fn(A, B, C) -> Ret
extern "C" fn(A, B, C, ...) -> Ret
extern "C" fn(A, B, C, D) -> Ret
and 68 others
and 768 others
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 9 previous errors
Expand Down