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/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.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 { 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); +}