about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-07-29 14:01:24 -0700
committerbors <bors@rust-lang.org>2013-07-29 14:01:24 -0700
commitd34016d1098bbd5e74fe18b99c4222b4fe709087 (patch)
treedbd2700988d03b0781e3f381a4c5a98c9eac78fd /src/libstd
parent2830d7d0135f188260f1762e6a47c347e9a603e2 (diff)
parent11aad20cf879f508a339c2af2bad901446f4fb3a (diff)
downloadrust-d34016d1098bbd5e74fe18b99c4222b4fe709087.tar.gz
rust-d34016d1098bbd5e74fe18b99c4222b4fe709087.zip
auto merge of #8109 : blake2-ppc/rust/extern-fn-clone, r=thestinger
Implement Clone and DeepClone for functions with 0 to 8 arguments.  `extern fn()` is implicitly copyable so it's simple, except there is no way to implement it generically over #n function arguments.

Allows deriving of Clone on structs containing `extern "Rust" fn`.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/clone.rs58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/libstd/clone.rs b/src/libstd/clone.rs
index d7220fdeb60..bd5bfb197b2 100644
--- a/src/libstd/clone.rs
+++ b/src/libstd/clone.rs
@@ -97,6 +97,26 @@ clone_impl!(())
 clone_impl!(bool)
 clone_impl!(char)
 
+macro_rules! extern_fn_clone(
+    ($($A:ident),*) => (
+        impl<$($A,)* ReturnType> Clone for extern "Rust" fn($($A),*) -> ReturnType {
+            /// Return a copy of a function pointer
+            #[inline]
+            fn clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
+        }
+    )
+)
+
+extern_fn_clone!()
+extern_fn_clone!(A)
+extern_fn_clone!(A, B)
+extern_fn_clone!(A, B, C)
+extern_fn_clone!(A, B, C, D)
+extern_fn_clone!(A, B, C, D, E)
+extern_fn_clone!(A, B, C, D, E, F)
+extern_fn_clone!(A, B, C, D, E, F, G)
+extern_fn_clone!(A, B, C, D, E, F, G, H)
+
 /// A trait distinct from `Clone` which represents "deep copies" of things like
 /// managed boxes which would otherwise not be copied.
 pub trait DeepClone {
@@ -157,6 +177,26 @@ deep_clone_impl!(())
 deep_clone_impl!(bool)
 deep_clone_impl!(char)
 
+macro_rules! extern_fn_deep_clone(
+    ($($A:ident),*) => (
+        impl<$($A,)* ReturnType> DeepClone for extern "Rust" fn($($A),*) -> ReturnType {
+            /// Return a copy of a function pointer
+            #[inline]
+            fn deep_clone(&self) -> extern "Rust" fn($($A),*) -> ReturnType { *self }
+        }
+    )
+)
+
+extern_fn_deep_clone!()
+extern_fn_deep_clone!(A)
+extern_fn_deep_clone!(A, B)
+extern_fn_deep_clone!(A, B, C)
+extern_fn_deep_clone!(A, B, C, D)
+extern_fn_deep_clone!(A, B, C, D, E)
+extern_fn_deep_clone!(A, B, C, D, E, F)
+extern_fn_deep_clone!(A, B, C, D, E, F, G)
+extern_fn_deep_clone!(A, B, C, D, E, F, G, H)
+
 #[test]
 fn test_owned_clone() {
     let a = ~5i;
@@ -195,3 +235,21 @@ fn test_borrowed_clone() {
     let z: &int = (&y).clone();
     assert_eq!(*z, 5);
 }
+
+#[test]
+fn test_extern_fn_clone() {
+    trait Empty {}
+    impl Empty for int {}
+
+    fn test_fn_a() -> float { 1.0 }
+    fn test_fn_b<T: Empty>(x: T) -> T { x }
+    fn test_fn_c(_: int, _: float, _: ~[int], _: int, _: int, _: int) {}
+
+    let _ = test_fn_a.clone();
+    let _ = test_fn_b::<int>.clone();
+    let _ = test_fn_c.clone();
+
+    let _ = test_fn_a.deep_clone();
+    let _ = test_fn_b::<int>.deep_clone();
+    let _ = test_fn_c.deep_clone();
+}