Implement FnMut, Fn for Box<FnMut>, Box<Fn>


#1

I think we should add these impls. They compile and coherence check (in liballoc/boxed.rs).

They add some extra flexibility, for example you should be permitted to use (and return) std::iter::Map<I, Box<FnMut<I::Iter, Output=R>> if the boxed closure implements the trait itself.

impl<A, R> FnOnce<A> for Box<FnMut<A, Output=R>> {
    type Output = R;

    extern "rust-call" fn call_once(mut self, args: A) -> R {
        (*self).call_mut(args)
    }
}

impl<A, R> FnMut<A> for Box<FnMut<A, Output=R>> {
    extern "rust-call" fn call_mut(&mut self, args: A) -> R {
        (**self).call_mut(args)
    }
}

impl<A, R> FnOnce<A> for Box<Fn<A, Output=R>> {
    type Output = R;

    extern "rust-call" fn call_once(self, args: A) -> R {
        (*self).call(args)
    }
}

impl<A, R> FnMut<A> for Box<Fn<A, Output=R>> {
    extern "rust-call" fn call_mut(&mut self, args: A) -> R {
        (**self).call(args)
    }
}

impl<A, R> Fn<A> for Box<Fn<A, Output=R>> {
    extern "rust-call" fn call(&self, args: A) -> R {
        (**self).call(args)
    }
}

#2

:+1: This makes it easier to write functors.


#3

There is precedent for other trait objects such as Iterator.

Out of curiosity, why not something like:

impl<F, A, R> FnOnce<A> for Box<F> where F: FnMut<A, Output=R> {
    // ...
}

#4

(Presumably you’d need F: ?Sized too.)

I’m in favour if coherence works.


#5

That was the first I tried, and it failed coherence. If I missed something, it’s still preferable, but I’m proposing something I know compiles.

It conflicted directly with the FnBox stuff I think, but maybe it can be fixed by adapting those impls too? I’m not very hopeful.


#6

Has anything changed here? This still seems like a good idea.