Unboxed closures

A relatively complete description of by reference closures that aims to encompass entirety of current thinking, except for bound lifetimes.

cc @pcwalton
On Wed, Jun 11, 2014 at 08:57:28PM -0700, Eric Reed wrote:
> If we don't have a subtyping relationship on the closure traits,
> then we'll just end up with a needless variants of higher-order
> functions.

I agree this situation is to be avoided. Subtrait relationships are
not necessarily the only way to do that, however (though they may be a
good way).

My biggest concern is ergonomic and points at a general weak point in
our trait system as compared to a traditional OO setup. Basically,
although we use OO terminology like "supertrait", we don't in fact
offer an OO system where subtraits can override supertrait methods and
so on. This basically means that people who manually implement the
close traits will have to implement more than one trait in many
(most?) cases.

In other words, if we had a closure hierarchy like:

    trait FnOnce<A,R> {
        fn call_once(self, arg: A) -> R;
    }

    trait Fn<A,R> : FnOnce<A, R> {
        fn call(&mut self, arg: A) -> R;
    }

    trait FnShare<A,R> : Fn<A, R> {
        fn call_share(&self, arg: A) -> R;
    }

And now I have some type that implements `FnShare`:

    struct Foo;

    impl FnShare<(),()> for Foo {
        fn call_share(&self, arg: ()) -> () { ... }
    }

This will yield an error because there is no impl `FnOnce`
nor `Fn`. I'd have to write those manually:

    impl Fn<(),()> for Foo {
        fn call(&mut self, arg: ()) -> () {
            self.call_share(arg)
        }
    }

    impl FnOnce<(),()> for Foo {
        fn call_once(&mut self, arg: ()) -> () {
            self.call_share(arg)
        }
    }

Maybe this doesn't matter, since it will be uncommon to implement
these traits manually, and perhaps we will at some point grow the
ability for a "subtrait" to specify default impls for
supertraits. This would take some careful design to get right though.

If we did instead have an impl like:

    impl<A,R,T:FnShare<A,R>> Fn<A,R> for T { ... }

then there'd be no such issue. Still, that'd require some other
extensions to permit.