about summary refs log tree commit diff
path: root/library
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-03-28 12:50:01 +0000
committerbors <bors@rust-lang.org>2023-03-28 12:50:01 +0000
commitbf57e8ada6dc62369d1cee7ab055fb4074bd2d10 (patch)
tree21cb8bce941e422c139fe496537d8ab823fadccc /library
parent60660371efe59dfc99644e9d709a1b71e25ae2ac (diff)
parent5ae6caa0f04c686f0cc8a330f54390131148f899 (diff)
downloadrust-bf57e8ada6dc62369d1cee7ab055fb4074bd2d10.tar.gz
rust-bf57e8ada6dc62369d1cee7ab055fb4074bd2d10.zip
Auto merge of #108080 - oli-obk:FnPtr-trait, r=lcnr
Add a builtin `FnPtr` trait that is implemented for all function pointers

r? `@ghost`

Rebased version of https://github.com/rust-lang/rust/pull/99531 (plus adjustments mentioned in the PR).

If perf is happy with this version, I would like to land it, even if the diagnostics fix in 9df8e1befb5031a5bf9d8dfe25170620642d3c59 only works for `FnPtr` specifically, and does not generally improve blanket impls.
Diffstat (limited to 'library')
-rw-r--r--library/core/src/marker.rs15
-rw-r--r--library/core/src/ptr/mod.rs267
2 files changed, 176 insertions, 106 deletions
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 9a0fd1f5f51..74e9c55396d 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -922,3 +922,18 @@ mod copy_impls {
     #[stable(feature = "rust1", since = "1.0.0")]
     impl<T: ?Sized> Copy for &T {}
 }
+
+/// A common trait implemented by all function pointers.
+#[unstable(
+    feature = "fn_ptr_trait",
+    issue = "none",
+    reason = "internal trait for implementing various traits for all function pointers"
+)]
+#[lang = "fn_ptr_trait"]
+#[cfg(not(bootstrap))]
+#[rustc_deny_explicit_impl]
+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