Skip to content

Commit f131001

Browse files
committed
Auto merge of #49224 - Centril:feature/shared-fn, r=<try>
impl Fn/FnMut/FnOnce for Arc/Rc This PR introduces the ability to have `Rc/Arc<F>: Fn(A) -> B where F: Fn(A) -> B` and `Rc/Arc<Fn(A) -> B`. This was previously tried (and failed) in #34118 (comment) due to breakage with crater. But now that the new edition is approaching we might want to try this in edition 2018. We should probably do a new crater run to see how much the breakage has changed since the previous attempt. cc @aturon
2 parents 17fea66 + 51b2ca5 commit f131001

File tree

3 files changed

+134
-1
lines changed

3 files changed

+134
-1
lines changed

src/liballoc/arc.rs

+66
Original file line numberDiff line numberDiff line change
@@ -1414,6 +1414,72 @@ impl<T> From<Vec<T>> for Arc<[T]> {
14141414
}
14151415
}
14161416

1417+
mod fn_impls {
1418+
use super::Arc;
1419+
1420+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1421+
impl<A, F: ?Sized + Fn<A>> Fn<A> for Arc<F> {
1422+
extern "rust-call" fn call(&self, args: A) -> F::Output {
1423+
(**self).call(args)
1424+
}
1425+
}
1426+
1427+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1428+
impl<A, F: ?Sized + Fn<A>> FnMut<A> for Arc<F> {
1429+
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
1430+
(**self).call(args)
1431+
}
1432+
}
1433+
1434+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1435+
impl<A, F: ?Sized + Fn<A>> FnOnce<A> for Arc<F> {
1436+
type Output = F::Output;
1437+
1438+
extern "rust-call" fn call_once(self, args: A) -> F::Output {
1439+
(&*self).call(args)
1440+
}
1441+
}
1442+
1443+
#[cfg(test)]
1444+
mod tests {
1445+
use super::Arc;
1446+
1447+
#[test]
1448+
fn is_fn() {
1449+
use_fn(Arc::new(|x| x + 1));
1450+
}
1451+
1452+
#[test]
1453+
fn is_fn_mut() {
1454+
use_fn_mut(Arc::new(|x| x + 1));
1455+
}
1456+
1457+
#[test]
1458+
fn is_fn_once() {
1459+
use_fn_once(Arc::new(|x| x + 1));
1460+
}
1461+
1462+
#[test]
1463+
fn can_dyn_dispatch() {
1464+
let dyn_dispatch: Arc<Fn(u8) -> u8> = Arc::new(|x| x + 1);
1465+
use_fn(dyn_dispatch);
1466+
}
1467+
1468+
fn use_fn_once<F: FnOnce(u8) -> u8>(fun: F) {
1469+
assert_eq!(2, fun(1));
1470+
}
1471+
1472+
fn use_fn_mut<F: FnMut(u8) -> u8>(mut fun: F) {
1473+
assert_eq!(2, fun(1));
1474+
assert_eq!(3, fun(2));
1475+
}
1476+
1477+
fn use_fn<F: Fn(u8) -> u8>(fun: F) {
1478+
assert_eq!(2, fun(1));
1479+
}
1480+
}
1481+
}
1482+
14171483
#[cfg(test)]
14181484
mod tests {
14191485
use std::boxed::Box;

src/liballoc/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,9 @@
124124
#![feature(exact_chunks)]
125125
#![feature(pointer_methods)]
126126
#![feature(inclusive_range_fields)]
127+
#![feature(fn_traits)]
127128

128-
#![cfg_attr(not(test), feature(fn_traits, swap_with_slice, i128))]
129+
#![cfg_attr(not(test), feature(swap_with_slice, i128))]
129130
#![cfg_attr(test, feature(test))]
130131

131132
// Allow testing this library

src/liballoc/rc.rs

+66
Original file line numberDiff line numberDiff line change
@@ -1389,6 +1389,72 @@ impl<T: ?Sized> RcBoxPtr<T> for Weak<T> {
13891389
}
13901390
}
13911391

1392+
mod fn_impls {
1393+
use super::Rc;
1394+
1395+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1396+
impl<A, F: ?Sized + Fn<A>> Fn<A> for Rc<F> {
1397+
extern "rust-call" fn call(&self, args: A) -> F::Output {
1398+
(**self).call(args)
1399+
}
1400+
}
1401+
1402+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1403+
impl<A, F: ?Sized + Fn<A>> FnMut<A> for Rc<F> {
1404+
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
1405+
(**self).call(args)
1406+
}
1407+
}
1408+
1409+
#[stable(feature = "shared_fn_impls", since = "1.26.0")]
1410+
impl<A, F: ?Sized + Fn<A>> FnOnce<A> for Rc<F> {
1411+
type Output = F::Output;
1412+
1413+
extern "rust-call" fn call_once(self, args: A) -> F::Output {
1414+
(&*self).call(args)
1415+
}
1416+
}
1417+
1418+
#[cfg(test)]
1419+
mod tests {
1420+
use super::Rc;
1421+
1422+
#[test]
1423+
fn is_fn() {
1424+
use_fn(Rc::new(|x| x + 1));
1425+
}
1426+
1427+
#[test]
1428+
fn is_fn_mut() {
1429+
use_fn_mut(Rc::new(|x| x + 1));
1430+
}
1431+
1432+
#[test]
1433+
fn is_fn_once() {
1434+
use_fn_once(Rc::new(|x| x + 1));
1435+
}
1436+
1437+
#[test]
1438+
fn can_dyn_dispatch() {
1439+
let dyn_dispatch: Rc<Fn(u8) -> u8> = Rc::new(|x| x + 1);
1440+
use_fn(dyn_dispatch);
1441+
}
1442+
1443+
fn use_fn_once<F: FnOnce(u8) -> u8>(fun: F) {
1444+
assert_eq!(2, fun(1));
1445+
}
1446+
1447+
fn use_fn_mut<F: FnMut(u8) -> u8>(mut fun: F) {
1448+
assert_eq!(2, fun(1));
1449+
assert_eq!(3, fun(2));
1450+
}
1451+
1452+
fn use_fn<F: Fn(u8) -> u8>(fun: F) {
1453+
assert_eq!(2, fun(1));
1454+
}
1455+
}
1456+
}
1457+
13921458
#[cfg(test)]
13931459
mod tests {
13941460
use super::{Rc, Weak};

0 commit comments

Comments
 (0)