about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-03-06 16:48:22 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2023-03-27 12:19:52 +0000
commit5ae6caa0f04c686f0cc8a330f54390131148f899 (patch)
tree91f0a70a67df8a2a0cd4381d124d447a5bdbbdb9
parent9e27c6c133b6710510f1a2ff94a943cb61efbc52 (diff)
downloadrust-5ae6caa0f04c686f0cc8a330f54390131148f899.tar.gz
rust-5ae6caa0f04c686f0cc8a330f54390131148f899.zip
Use the FnPtr trait to avoid implementing common traits via macros
-rw-r--r--library/core/src/marker.rs2
-rw-r--r--library/core/src/ptr/mod.rs267
-rw-r--r--tests/ui/issues/issue-59488.stderr20
3 files changed, 162 insertions, 127 deletions
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index c0cb12df5b0..74e9c55396d 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -932,7 +932,7 @@ mod copy_impls {
 #[lang = "fn_ptr_trait"]
 #[cfg(not(bootstrap))]
 #[rustc_deny_explicit_impl]
-pub trait FnPtr {
+pub trait FnPtr: Copy + Clone {
     /// Returns the address of the function pointer.
     #[lang = "fn_ptr_addr"]
     fn addr(self) -> *const ();
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 5884a8ca308..9cdfd2c21cc 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1891,150 +1891,205 @@ pub fn hash<T: ?Sized, S: hash::Hasher>(hashee: *const T, into: &mut S) {
     hashee.hash(into);
 }
 
-// If this is a unary fn pointer, it adds a doc comment.
-// Otherwise, it hides the docs entirely.
-macro_rules! maybe_fnptr_doc {
-    (@ #[$meta:meta] $item:item) => {
-        #[doc(hidden)]
-        #[$meta]
-        $item
-    };
-    ($a:ident @ #[$meta:meta] $item:item) => {
-        #[doc(fake_variadic)]
-        #[doc = "This trait is implemented for function pointers with up to twelve arguments."]
-        #[$meta]
-        $item
-    };
-    ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
-        #[doc(hidden)]
-        #[$meta]
-        $item
-    };
-}
+#[cfg(bootstrap)]
+mod old_fn_ptr_impl {
+    use super::*;
+    // If this is a unary fn pointer, it adds a doc comment.
+    // Otherwise, it hides the docs entirely.
+    macro_rules! maybe_fnptr_doc {
+        (@ #[$meta:meta] $item:item) => {
+            #[doc(hidden)]
+            #[$meta]
+            $item
+        };
+        ($a:ident @ #[$meta:meta] $item:item) => {
+            #[doc(fake_variadic)]
+            #[doc = "This trait is implemented for function pointers with up to twelve arguments."]
+            #[$meta]
+            $item
+        };
+        ($a:ident $($rest_a:ident)+ @ #[$meta:meta] $item:item) => {
+            #[doc(hidden)]
+            #[$meta]
+            $item
+        };
+    }
 
-// FIXME(strict_provenance_magic): function pointers have buggy codegen that
-// necessitates casting to a usize to get the backend to do the right thing.
-// for now I will break AVR to silence *a billion* lints. We should probably
-// have a proper "opaque function pointer type" to handle this kind of thing.
+    // FIXME(strict_provenance_magic): function pointers have buggy codegen that
+    // necessitates casting to a usize to get the backend to do the right thing.
+    // for now I will break AVR to silence *a billion* lints. We should probably
+    // have a proper "opaque function pointer type" to handle this kind of thing.
 
-// Impls for function pointers
-macro_rules! fnptr_impls_safety_abi {
-    ($FnTy: ty, $($Arg: ident),*) => {
+    // Impls for function pointers
+    macro_rules! fnptr_impls_safety_abi {
+        ($FnTy: ty, $($Arg: ident),*) => {
         fnptr_impls_safety_abi! { #[stable(feature = "fnptr_impls", since = "1.4.0")] $FnTy, $($Arg),* }
     };
     (@c_unwind $FnTy: ty, $($Arg: ident),*) => {
         fnptr_impls_safety_abi! { #[unstable(feature = "c_unwind", issue = "74990")] $FnTy, $($Arg),* }
     };
     (#[$meta:meta] $FnTy: ty, $($Arg: ident),*) => {
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> PartialEq for $FnTy {
-                #[inline]
-                fn eq(&self, other: &Self) -> bool {
-                    *self as usize == *other as usize
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> PartialEq for $FnTy {
+                    #[inline]
+                    fn eq(&self, other: &Self) -> bool {
+                        *self as usize == *other as usize
+                    }
                 }
             }
-        }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> Eq for $FnTy {}
-        }
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> Eq for $FnTy {}
+            }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> PartialOrd for $FnTy {
-                #[inline]
-                fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-                    (*self as usize).partial_cmp(&(*other as usize))
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> PartialOrd for $FnTy {
+                    #[inline]
+                    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+                        (*self as usize).partial_cmp(&(*other as usize))
+                    }
                 }
             }
-        }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> Ord for $FnTy {
-                #[inline]
-                fn cmp(&self, other: &Self) -> Ordering {
-                    (*self as usize).cmp(&(*other as usize))
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> Ord for $FnTy {
+                    #[inline]
+                    fn cmp(&self, other: &Self) -> Ordering {
+                        (*self as usize).cmp(&(*other as usize))
+                    }
                 }
             }
-        }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> hash::Hash for $FnTy {
-                fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
-                    state.write_usize(*self as usize)
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> hash::Hash for $FnTy {
+                    fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
+                        state.write_usize(*self as usize)
+                    }
                 }
             }
-        }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    fmt::pointer_fmt_inner(*self as usize, f)
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> fmt::Pointer for $FnTy {
+                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        fmt::pointer_fmt_inner(*self as usize, f)
+                    }
                 }
             }
-        }
 
-        maybe_fnptr_doc! {
-            $($Arg)* @
-            #[$meta]
-            impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
-                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-                    fmt::pointer_fmt_inner(*self as usize, f)
+            maybe_fnptr_doc! {
+                $($Arg)* @
+                #[$meta]
+                impl<Ret, $($Arg),*> fmt::Debug for $FnTy {
+                    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+                        fmt::pointer_fmt_inner(*self as usize, f)
+                    }
                 }
             }
         }
     }
-}
 
-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),+ }
+    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! { @c_unwind extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
         fnptr_impls_safety_abi! { @c_unwind extern "C-unwind" 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),+ }
+            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),+ }
         fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+) -> Ret, $($Arg),+ }
         fnptr_impls_safety_abi! { @c_unwind unsafe extern "C-unwind" fn($($Arg),+ , ...) -> Ret, $($Arg),+ }
-    };
-    () => {
-        // No variadic functions with 0 parameters
-        fnptr_impls_safety_abi! { extern "Rust" fn() -> Ret, }
-        fnptr_impls_safety_abi! { extern "C" fn() -> Ret, }
+        };
+        () => {
+            // 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! { @c_unwind extern "C-unwind" fn() -> Ret, }
-        fnptr_impls_safety_abi! { unsafe extern "Rust" fn() -> Ret, }
-        fnptr_impls_safety_abi! { unsafe 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! { @c_unwind unsafe extern "C-unwind" fn() -> Ret, }
-    };
+        };
+    }
+
+    fnptr_impls_args! {}
+    fnptr_impls_args! { T }
+    fnptr_impls_args! { A, B }
+    fnptr_impls_args! { A, B, C }
+    fnptr_impls_args! { A, B, C, D }
+    fnptr_impls_args! { A, B, C, D, E }
+    fnptr_impls_args! { A, B, C, D, E, F }
+    fnptr_impls_args! { A, B, C, D, E, F, G }
+    fnptr_impls_args! { A, B, C, D, E, F, G, H }
+    fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
+    fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
+    fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
+    fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
 }
 
-fnptr_impls_args! {}
-fnptr_impls_args! { T }
-fnptr_impls_args! { A, B }
-fnptr_impls_args! { A, B, C }
-fnptr_impls_args! { A, B, C, D }
-fnptr_impls_args! { A, B, C, D, E }
-fnptr_impls_args! { A, B, C, D, E, F }
-fnptr_impls_args! { A, B, C, D, E, F, G }
-fnptr_impls_args! { A, B, C, D, E, F, G, H }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K }
-fnptr_impls_args! { A, B, C, D, E, F, G, H, I, J, K, L }
+#[cfg(not(bootstrap))]
+mod new_fn_ptr_impl {
+    use super::*;
+    use crate::marker::FnPtr;
+
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> PartialEq for F {
+        #[inline]
+        fn eq(&self, other: &Self) -> bool {
+            self.addr() == other.addr()
+        }
+    }
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> Eq for F {}
+
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> PartialOrd for F {
+        #[inline]
+        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+            self.addr().partial_cmp(&other.addr())
+        }
+    }
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> Ord for F {
+        #[inline]
+        fn cmp(&self, other: &Self) -> Ordering {
+            self.addr().cmp(&other.addr())
+        }
+    }
+
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> hash::Hash for F {
+        fn hash<HH: hash::Hasher>(&self, state: &mut HH) {
+            state.write_usize(self.addr() as _)
+        }
+    }
+
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> fmt::Pointer for F {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            fmt::pointer_fmt_inner(self.addr() as _, f)
+        }
+    }
 
+    #[stable(feature = "fnptr_impls", since = "1.4.0")]
+    impl<F: FnPtr> fmt::Debug for F {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            fmt::pointer_fmt_inner(self.addr() as _, f)
+        }
+    }
+}
 /// Create a `const` raw pointer to a place, without creating an intermediate reference.
 ///
 /// Creating a reference with `&`/`&mut` is only allowed if the pointer is properly aligned
diff --git a/tests/ui/issues/issue-59488.stderr b/tests/ui/issues/issue-59488.stderr
index d45beefa420..ac8862716c0 100644
--- a/tests/ui/issues/issue-59488.stderr
+++ b/tests/ui/issues/issue-59488.stderr
@@ -90,16 +90,6 @@ LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
-   = help: the following other types implement trait `Debug`:
-             extern "C" fn() -> Ret
-             extern "C" fn(A, B) -> Ret
-             extern "C" fn(A, B, ...) -> Ret
-             extern "C" fn(A, B, C) -> Ret
-             extern "C" fn(A, B, C, ...) -> Ret
-             extern "C" fn(A, B, C, D) -> Ret
-             extern "C" fn(A, B, C, D, ...) -> Ret
-             extern "C" fn(A, B, C, D, E) -> Ret
-           and 118 others
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
@@ -109,16 +99,6 @@ LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
    = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
-   = help: the following other types implement trait `Debug`:
-             extern "C" fn() -> Ret
-             extern "C" fn(A, B) -> Ret
-             extern "C" fn(A, B, ...) -> Ret
-             extern "C" fn(A, B, C) -> Ret
-             extern "C" fn(A, B, C, ...) -> Ret
-             extern "C" fn(A, B, C, D) -> Ret
-             extern "C" fn(A, B, C, D, ...) -> Ret
-             extern "C" fn(A, B, C, D, E) -> Ret
-           and 118 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 10 previous errors