Skip to content

Commit 5ae6caa

Browse files
committed
Use the FnPtr trait to avoid implementing common traits via macros
1 parent 9e27c6c commit 5ae6caa

File tree

3 files changed

+162
-127
lines changed

3 files changed

+162
-127
lines changed

library/core/src/marker.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,7 @@ mod copy_impls {
932932
#[lang = "fn_ptr_trait"]
933933
#[cfg(not(bootstrap))]
934934
#[rustc_deny_explicit_impl]
935-
pub trait FnPtr {
935+
pub trait FnPtr: Copy + Clone {
936936
/// Returns the address of the function pointer.
937937
#[lang = "fn_ptr_addr"]
938938
fn addr(self) -> *const ();

library/core/src/ptr/mod.rs

+161-106
Original file line numberDiff line numberDiff line change
@@ -1891,150 +1891,205 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
18911891
hashee.hash(into);
18921892
}
18931893

1894-
// If this is a unary fn pointer, it adds a doc comment.
1895-
// Otherwise, it hides the docs entirely.
1896-
macro_rules! maybe_fnptr_doc {
1897-
(@ #[$meta:meta] $item:item) => {
1898-
#[doc(hidden)]
1899-
#[$meta]
1900-
$item
1901-
};
1902-
($a:ident @ #[$meta:meta] $item:item) => {
1903-
#[doc(fake_variadic)]
1904-
#[doc = "This trait is implemented for function pointers with up to twelve arguments."]
1905-
#[$meta]
1906-
$item
1907-
};
1908-
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
1909-
#[doc(hidden)]
1910-
#[$meta]
1911-
$item
1912-
};
1913-
}
1894+
#[cfg(bootstrap)]
1895+
mod old_fn_ptr_impl {
1896+
use super::*;
1897+
// If this is a unary fn pointer, it adds a doc comment.
1898+
// Otherwise, it hides the docs entirely.
1899+
macro_rules! maybe_fnptr_doc {
1900+
(@ #[$meta:meta] $item:item) => {
1901+
#[doc(hidden)]
1902+
#[$meta]
1903+
$item
1904+
};
1905+
($a:ident @ #[$meta:meta] $item:item) => {
1906+
#[doc(fake_variadic)]
1907+
#[doc = "This trait is implemented for function pointers with up to twelve arguments."]
1908+
#[$meta]
1909+
$item
1910+
};
1911+
($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
1912+
#[doc(hidden)]
1913+
#[$meta]
1914+
$item
1915+
};
1916+
}
19141917

1915-
// FIXME(strict_provenance_magic): function pointers have buggy codegen that
1916-
// necessitates casting to a usize to get the backend to do the right thing.
1917-
// for now I will break AVR to silence *a billion* lints. We should probably
1918-
// have a proper "opaque function pointer type" to handle this kind of thing.
1918+
// FIXME(strict_provenance_magic): function pointers have buggy codegen that
1919+
// necessitates casting to a usize to get the backend to do the right thing.
1920+
// for now I will break AVR to silence *a billion* lints. We should probably
1921+
// have a proper "opaque function pointer type" to handle this kind of thing.
19191922

1920-
// Impls for function pointers
1921-
macro_rules! fnptr_impls_safety_abi {
1922-
($FnTy: ty, $($Arg: ident),*) => {
1923+
// Impls for function pointers
1924+
macro_rules! fnptr_impls_safety_abi {
1925+
($FnTy: ty, $($Arg: ident),*) => {
19231926
fnptr_impls_safety_abi! { #[stable(feature = "fnptr_impls", since = "1.4.0")] $FnTy, $($Arg),* }
19241927
};
19251928
(@c_unwind $FnTy: ty, $($Arg: ident),*) => {
19261929
fnptr_impls_safety_abi! { #[unstable(feature = "c_unwind", issue = "74990")] $FnTy, $($Arg),* }
19271930
};
19281931
(#[$meta:meta] $FnTy: ty, $($Arg: ident),*) => {
1929-
maybe_fnptr_doc! {
1930-
$($Arg)* @
1931-
#[$meta]
1932-
impl<Ret, $($Arg),*> PartialEq for $FnTy {
1933-
#[inline]
1934-
fn eq(&self, other: &Self) -> bool {
1935-
*self as usize == *other as usize
1932+
maybe_fnptr_doc! {
1933+
$($Arg)* @
1934+
#[$meta]
1935+
impl<Ret, $($Arg),*> PartialEq for $FnTy {
1936+
#[inline]
1937+
fn eq(&self, other: &Self) -> bool {
1938+
*self as usize == *other as usize
1939+
}
19361940
}
19371941
}
1938-
}
19391942

1940-
maybe_fnptr_doc! {
1941-
$($Arg)* @
1942-
#[$meta]
1943-
impl<Ret, $($Arg),*> Eq for $FnTy {}
1944-
}
1943+
maybe_fnptr_doc! {
1944+
$($Arg)* @
1945+
#[$meta]
1946+
impl<Ret, $($Arg),*> Eq for $FnTy {}
1947+
}
19451948

1946-
maybe_fnptr_doc! {
1947-
$($Arg)* @
1948-
#[$meta]
1949-
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
1950-
#[inline]
1951-
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1952-
(*self as usize).partial_cmp(&(*other as usize))
1949+
maybe_fnptr_doc! {
1950+
$($Arg)* @
1951+
#[$meta]
1952+
impl<Ret, $($Arg),*> PartialOrd for $FnTy {
1953+
#[inline]
1954+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1955+
(*self as usize).partial_cmp(&(*other as usize))
1956+
}
19531957
}
19541958
}
1955-
}
19561959

1957-
maybe_fnptr_doc! {
1958-
$($Arg)* @
1959-
#[$meta]
1960-
impl<Ret, $($Arg),*> Ord for $FnTy {
1961-
#[inline]
1962-
fn cmp(&self, other: &Self) -> Ordering {
1963-
(*self as usize).cmp(&(*other as usize))
1960+
maybe_fnptr_doc! {
1961+
$($Arg)* @
1962+
#[$meta]
1963+
impl<Ret, $($Arg),*> Ord for $FnTy {
1964+
#[inline]
1965+
fn cmp(&self, other: &Self) -> Ordering {
1966+
(*self as usize).cmp(&(*other as usize))
1967+
}
19641968
}
19651969
}
1966-
}
19671970

1968-
maybe_fnptr_doc! {
1969-
$($Arg)* @
1970-
#[$meta]
1971-
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
1972-
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
1973-
state.write_usize(*self as usize)
1971+
maybe_fnptr_doc! {
1972+
$($Arg)* @
1973+
#[$meta]
1974+
impl<Ret, $($Arg),*> hash::Hash for $FnTy {
1975+
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
1976+
state.write_usize(*self as usize)
1977+
}
19741978
}
19751979
}
1976-
}
19771980

1978-
maybe_fnptr_doc! {
1979-
$($Arg)* @
1980-
#[$meta]
1981-
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
1982-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1983-
fmt::pointer_fmt_inner(*self as usize, f)
1981+
maybe_fnptr_doc! {
1982+
$($Arg)* @
1983+
#[$meta]
1984+
impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
1985+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1986+
fmt::pointer_fmt_inner(*self as usize, f)
1987+
}
19841988
}
19851989
}
1986-
}
19871990

1988-
maybe_fnptr_doc! {
1989-
$($Arg)* @
1990-
#[$meta]
1991-
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
1992-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1993-
fmt::pointer_fmt_inner(*self as usize, f)
1991+
maybe_fnptr_doc! {
1992+
$($Arg)* @
1993+
#[$meta]
1994+
impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
1995+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1996+
fmt::pointer_fmt_inner(*self as usize, f)
1997+
}
19941998
}
19951999
}
19962000
}
19972001
}
1998-
}
19992002

2000-
macro_rules! fnptr_impls_args {
2001-
($($Arg: ident),+) => {
2002-
fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
2003-
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
2004-
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
2003+
macro_rules! fnptr_impls_args {
2004+
($($Arg: ident),+) => {
2005+
fnptr_impls_safety_abi! { extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
2006+
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
2007+
fnptr_impls_safety_abi! { extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
20052008
fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
20062009
fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
2007-
fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
2008-
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
2009-
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
2010+
fnptr_impls_safety_abi! { unsafe extern "Rust" fn($($Arg),+) -> Ret, $($Arg),+ }
2011+
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+) -> Ret, $($Arg),+ }
2012+
fnptr_impls_safety_abi! { unsafe extern "C" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
20102013
fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
20112014
fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
2012-
};
2013-
() => {
2014-
// No variadic functions with 0 parameters
2015-
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
2016-
fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
2015+
};
2016+
() => {
2017+
// No variadic functions with 0 parameters
2018+
fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
2019+
fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
20172020
fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" fn() -> Ret, }
2018-
fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
2019-
fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
2021+
fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
2022+
fnptr_impls_safety_abi! { unsafe extern "C" fn() -> Ret, }
20202023
fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn() -> Ret, }
2021-
};
2024+
};
2025+
}
2026+
2027+
fnptr_impls_args! {}
2028+
fnptr_impls_args! { T }
2029+
fnptr_impls_args! { A, B }
2030+
fnptr_impls_args! { A, B, C }
2031+
fnptr_impls_args! { A, B, C, D }
2032+
fnptr_impls_args! { A, B, C, D, E }
2033+
fnptr_impls_args! { A, B, C, D, E, F }
2034+
fnptr_impls_args! { A, B, C, D, E, F, G }
2035+
fnptr_impls_args! { A, B, C, D, E, F, G, H }
2036+
fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
2037+
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
2038+
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
2039+
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
20222040
}
20232041

2024-
fnptr_impls_args! {}
2025-
fnptr_impls_args! { T }
2026-
fnptr_impls_args! { A, B }
2027-
fnptr_impls_args! { A, B, C }
2028-
fnptr_impls_args! { A, B, C, D }
2029-
fnptr_impls_args! { A, B, C, D, E }
2030-
fnptr_impls_args! { A, B, C, D, E, F }
2031-
fnptr_impls_args! { A, B, C, D, E, F, G }
2032-
fnptr_impls_args! { A, B, C, D, E, F, G, H }
2033-
fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
2034-
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
2035-
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
2036-
fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
2042+
#[cfg(not(bootstrap))]
2043+
mod new_fn_ptr_impl {
2044+
use super::*;
2045+
use crate::marker::FnPtr;
2046+
2047+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2048+
impl<F: FnPtr> PartialEq for F {
2049+
#[inline]
2050+
fn eq(&self, other: &Self) -> bool {
2051+
self.addr() == other.addr()
2052+
}
2053+
}
2054+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2055+
impl<F: FnPtr> Eq for F {}
2056+
2057+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2058+
impl<F: FnPtr> PartialOrd for F {
2059+
#[inline]
2060+
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
2061+
self.addr().partial_cmp(&other.addr())
2062+
}
2063+
}
2064+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2065+
impl<F: FnPtr> Ord for F {
2066+
#[inline]
2067+
fn cmp(&self, other: &Self) -> Ordering {
2068+
self.addr().cmp(&other.addr())
2069+
}
2070+
}
2071+
2072+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2073+
impl<F: FnPtr> hash::Hash for F {
2074+
fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
2075+
state.write_usize(self.addr() as _)
2076+
}
2077+
}
2078+
2079+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2080+
impl<F: FnPtr> fmt::Pointer for F {
2081+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2082+
fmt::pointer_fmt_inner(self.addr() as _, f)
2083+
}
2084+
}
20372085

2086+
#[stable(feature = "fnptr_impls", since = "1.4.0")]
2087+
impl<F: FnPtr> fmt::Debug for F {
2088+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
2089+
fmt::pointer_fmt_inner(self.addr() as _, f)
2090+
}
2091+
}
2092+
}
20382093
/// Create a `const` raw pointer to a place, without creating an intermediate reference.
20392094
///
20402095
/// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned

tests/ui/issues/issue-59488.stderr

-20
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,6 @@ LL | assert_eq!(Foo::Bar, i);
9090
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
9191
|
9292
= help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
93-
= help: the following other types implement trait `Debug`:
94-
extern "C" fn() -> Ret
95-
extern "C" fn(A, B) -> Ret
96-
extern "C" fn(A, B, ...) -> Ret
97-
extern "C" fn(A, B, C) -> Ret
98-
extern "C" fn(A, B, C, ...) -> Ret
99-
extern "C" fn(A, B, C, D) -> Ret
100-
extern "C" fn(A, B, C, D, ...) -> Ret
101-
extern "C" fn(A, B, C, D, E) -> Ret
102-
and 118 others
10393
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
10494

10595
error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
@@ -109,16 +99,6 @@ LL | assert_eq!(Foo::Bar, i);
10999
| ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
110100
|
111101
= help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
112-
= help: the following other types implement trait `Debug`:
113-
extern "C" fn() -> Ret
114-
extern "C" fn(A, B) -> Ret
115-
extern "C" fn(A, B, ...) -> Ret
116-
extern "C" fn(A, B, C) -> Ret
117-
extern "C" fn(A, B, C, ...) -> Ret
118-
extern "C" fn(A, B, C, D) -> Ret
119-
extern "C" fn(A, B, C, D, ...) -> Ret
120-
extern "C" fn(A, B, C, D, E) -> Ret
121-
and 118 others
122102
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
123103

124104
error: aborting due to 10 previous errors

0 commit comments

Comments
 (0)