From 0caccdf9f79d39d6b0a1d385aec995b75c3cb9ba Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Sun, 26 Apr 2020 16:08:42 +1000 Subject: [PATCH 1/2] Implement Fn traits for Rc and Arc --- src/liballoc/rc.rs | 23 +++++++++++++++++++++++ src/liballoc/sync.rs | 23 +++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 2f9505ec79ffa..dc8801fe8b461 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1436,6 +1436,29 @@ impl fmt::Pointer for Rc { } } +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> FnOnce for Rc { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call(&*self, args) + } +} + +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> FnMut for Rc { + extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { + >::call(self, args) + } +} + +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> Fn for Rc { + extern "rust-call" fn call(&self, args: A) -> Self::Output { + >::call(self, args) + } +} + #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Rc { fn from(t: T) -> Self { diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 19d289c87fd9f..c88b8865e650c 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -2066,6 +2066,29 @@ impl Hash for Arc { } } +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> FnOnce for Arc { + type Output = >::Output; + + extern "rust-call" fn call_once(self, args: A) -> Self::Output { + >::call(&*self, args) + } +} + +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> FnMut for Arc { + extern "rust-call" fn call_mut(&mut self, args: A) -> Self::Output { + >::call(self, args) + } +} + +#[stable(feature = "rc_fn", since = "1.45.0")] +impl + ?Sized> Fn for Arc { + extern "rust-call" fn call(&self, args: A) -> Self::Output { + >::call(self, args) + } +} + #[stable(feature = "from_for_ptrs", since = "1.6.0")] impl From for Arc { fn from(t: T) -> Self { From 0cb80ab265f389f054f1f3ee08026596cfd9e6c4 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Sun, 10 May 2020 10:18:32 +1000 Subject: [PATCH 2/2] Add tests for Fn impl of Rc and Arc --- src/liballoc/rc/tests.rs | 20 ++++++++++++++++++++ src/liballoc/sync/tests.rs | 20 ++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/liballoc/rc/tests.rs b/src/liballoc/rc/tests.rs index 56788bb56d550..d847948559082 100644 --- a/src/liballoc/rc/tests.rs +++ b/src/liballoc/rc/tests.rs @@ -434,3 +434,23 @@ fn test_array_from_slice() { let a: Result, _> = r.clone().try_into(); assert!(a.is_err()); } + +#[test] +fn test_fn() { + fn apply_fn_once(v: T, f: impl FnOnce(T)) { + f(v) + } + fn apply_fn_mut(v: T, mut f: impl FnMut(T)) { + f(v) + } + fn apply_fn(v: T, f: impl Fn(T)) { + f(v) + } + + let x = RefCell::new(0); + let f = Rc::new(|v: i32| *x.borrow_mut() += v); + apply_fn_once(1, f.clone()); + apply_fn_mut(2, f.clone()); + apply_fn(4, f.clone()); + assert_eq!(*x.borrow(), 7); +} diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index edc2820ee22f1..f4319dabf7ef5 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -490,3 +490,23 @@ fn test_array_from_slice() { let a: Result, _> = r.clone().try_into(); assert!(a.is_err()); } + +#[test] +fn test_fn() { + fn apply_fn_once(v: T, f: impl FnOnce(T)) { + f(v) + } + fn apply_fn_mut(v: T, mut f: impl FnMut(T)) { + f(v) + } + fn apply_fn(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); +}