From 3e5a8f3bd43c420ef923e975b4afb80f6d6f120f Mon Sep 17 00:00:00 2001
From: Michael de Silva <michael@mwdesilva.com>
Date: Mon, 11 Oct 2021 13:40:37 +0530
Subject: [PATCH 1/5] WIP adding Fn* impls to Arc; FIXME cannot move out of Arc
 as Fn does not Copy

---
 library/alloc/src/sync.rs | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 6e8da849e64cd..1fbcd4af1c3c1 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1663,6 +1663,26 @@ impl Arc<dyn Any + Send + Sync> {
     }
 }
 
+impl<Args, F: FnOnce<Args> + ?Sized> FnOnce<Args> for Arc<F> {
+    type Output = <F as FnOnce<Args>>::Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
+        <F as FnOnce<Args>>::call_once(*self, args)
+    }
+}
+
+impl<Args, F: FnMut<Args> + ?Sized> FnMut<Args> for Arc<F> {
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
+        <F as FnMut<Args>>::call_mut(self, args)
+    }
+}
+
+impl<Args, F: Fn<Args> + ?Sized> Fn<Args> for Arc<F> {
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output {
+        <F as Fn<Args>>::call(self, args)
+    }
+}
+
 impl<T> Weak<T> {
     /// Constructs a new `Weak<T>`, without allocating any memory.
     /// Calling [`upgrade`] on the return value always gives [`None`].

From ad0b709fb3b3e7567aeb721512223d338c0766a2 Mon Sep 17 00:00:00 2001
From: Michael de Silva <michael@mwdesilva.com>
Date: Mon, 11 Oct 2021 16:36:24 +0530
Subject: [PATCH 2/5] Allow Copy for closure

---
 library/alloc/src/sync.rs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 1fbcd4af1c3c1..a7cb74fcb6799 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1663,7 +1663,7 @@ impl Arc<dyn Any + Send + Sync> {
     }
 }
 
-impl<Args, F: FnOnce<Args> + ?Sized> FnOnce<Args> for Arc<F> {
+impl<Args, F: FnOnce<Args> + ?Sized + Copy> FnOnce<Args> for Arc<F> {
     type Output = <F as FnOnce<Args>>::Output;
 
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
@@ -1671,13 +1671,13 @@ impl<Args, F: FnOnce<Args> + ?Sized> FnOnce<Args> for Arc<F> {
     }
 }
 
-impl<Args, F: FnMut<Args> + ?Sized> FnMut<Args> for Arc<F> {
+impl<Args, F: FnMut<Args> + ?Sized + Copy> FnMut<Args> for Arc<F> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
         <F as FnMut<Args>>::call_mut(self, args)
     }
 }
 
-impl<Args, F: Fn<Args> + ?Sized> Fn<Args> for Arc<F> {
+impl<Args, F: Fn<Args> + ?Sized + Copy> Fn<Args> for Arc<F> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output {
         <F as Fn<Args>>::call(self, args)
     }

From e0cffea7b63c3f276c222f7945d0a9c5e351f915 Mon Sep 17 00:00:00 2001
From: Michael de Silva <michael@mwdesilva.com>
Date: Mon, 11 Oct 2021 18:52:53 +0530
Subject: [PATCH 3/5] Remove Copy and add impls for Fn only, due to Arc

---
 library/alloc/src/sync.rs | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index a7cb74fcb6799..cb0b0ad2adcb9 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1663,21 +1663,24 @@ impl Arc<dyn Any + Send + Sync> {
     }
 }
 
-impl<Args, F: FnOnce<Args> + ?Sized + Copy> FnOnce<Args> for Arc<F> {
+#[stable(feature = "arc_fn_impls", since = "1.57.0")]
+impl<Args, F: Fn<Args> + ?Sized> FnOnce<Args> for Arc<F> {
     type Output = <F as FnOnce<Args>>::Output;
 
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output {
-        <F as FnOnce<Args>>::call_once(*self, args)
+        <F as Fn<Args>>::call(&self, args)
     }
 }
 
-impl<Args, F: FnMut<Args> + ?Sized + Copy> FnMut<Args> for Arc<F> {
+#[stable(feature = "arc_fn_impls", since = "1.57.0")]
+impl<Args, F: Fn<Args> + ?Sized> FnMut<Args> for Arc<F> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output {
-        <F as FnMut<Args>>::call_mut(self, args)
+        <F as Fn<Args>>::call(self, args)
     }
 }
 
-impl<Args, F: Fn<Args> + ?Sized + Copy> Fn<Args> for Arc<F> {
+#[stable(feature = "arc_fn_impls", since = "1.57.0")]
+impl<Args, F: Fn<Args> + ?Sized> Fn<Args> for Arc<F> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output {
         <F as Fn<Args>>::call(self, args)
     }

From 655aa927cef59c060856c037578033dbfccdba33 Mon Sep 17 00:00:00 2001
From: Michael de Silva <michael@mwdesilva.com>
Date: Mon, 11 Oct 2021 20:04:59 +0530
Subject: [PATCH 4/5] Add tests for adding Fn impl to Arc

---
 library/alloc/src/sync/tests.rs | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 4ccb32fbbf63d..a62b86adf890e 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -618,3 +618,18 @@ fn test_arc_cyclic_two_refs() {
     assert_eq!(Arc::strong_count(&two_refs), 3);
     assert_eq!(Arc::weak_count(&two_refs), 2);
 }
+
+#[test]
+fn test_arc_fn() {
+    let f = || String::from("hello");
+    let f: Arc<dyn Fn() -> String> = Arc::new(f);
+
+    assert_eq!(quox(&f), "hello");
+}
+
+fn quox<F>(f: &F) -> String
+where
+    F: Fn() -> String,
+{
+    f()
+}

From 1f60e2f032bea49521b23377552ca8e07d6378d9 Mon Sep 17 00:00:00 2001
From: Michael de Silva <michael@mwdesilva.com>
Date: Tue, 12 Oct 2021 19:21:28 +0530
Subject: [PATCH 5/5] Improve test, using test in #71570

---
 library/alloc/src/sync/tests.rs | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index a62b86adf890e..3b7620f23e5f2 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -633,3 +633,25 @@ where
 {
     f()
 }
+
+#[test]
+fn test_arc_fn2() {
+    fn apply_fn_once<T>(v: T, f: impl FnOnce(T)) {
+        f(v)
+    }
+    fn apply_fn_mut<T>(v: T, mut f: impl FnMut(T)) {
+        f(v)
+    }
+    fn apply_fn<T>(v: T, f: impl Fn(T)) {
+        f(v)
+    }
+
+    let x = Mutex::new(0);
+    let f = Arc::new(|v: i32| *x.lock().unwrap() += v);
+
+    apply_fn_once(1, f.clone());
+    apply_fn_mut(2, f.clone());
+    apply_fn(4, f.clone());
+
+    assert_eq!(*x.lock().unwrap(), 7);
+}