[rust-dev] RFC: Future-proof for unboxed closures

Niko Matsakis niko at alum.mit.edu
Fri Jan 24 21:31:00 PST 2014


This is good to think about, though I think writing `&mut || foo`
feels like a nonstarter to me.

I still feel that `&my` -- meaning, a pointer that gives ownership of
the referent but not the memory where the referent lives -- is the
right approach here. Basically, the type of `|| ...` would be `&my T`
where `T` is some fresh type that implements `Fn<U,R>`.

Now, the consumer of the closure could be any of:

- `fn foo(x: |U| -> R)`: In this case, the type `|U| -> R`
  is equivalent to `&mut Fn<U,R>`. This is an automatic
  object coercion and also an automatic reborrow. That is,
  written out very explicitly, `foo(|u| r)` would be
  equivalen to `foo((&mut *(&my T { ... })) as &mut Fn<U,R>)`,
  where again `T` is the anonymous closure type.

- `fn foo<T:Fn<U,R>>(x: &my T) -> T`: Now `foo` takes ownership of the
  value `T`. Because it's an `&my` pointer, `foo()` can move the
  referent around.

- `fn foo<T:Fn<U,R>>(x: &mut T) -> T`: `foo` does not take ownership
  of the closure, but does avoid virtual dispatch.

This can be extended to "once closures" in a pretty straightforward
way:

- `fn foo(x: once |U| -> R)`
- `fn foo<T:OnceFn<U,R>>(x: &my T)`

As a bonus, `&my` is perfect for the `drop` trait. And (I think)
fairly straightforwad to implement.

(The semantics of `&my`: when an `&my` value is dropped, it would
 cause the referent to be dropped as well)


Niko

On Mon, Dec 30, 2013 at 07:31:45PM -0800, Patrick Walton wrote:
> Yes, it would need to be &mut, you're right.
> 
> I think the underlying type syntax would be something like `Fn<int,&int>` for the unboxed version, and `&mut Fn<int,&int>` for the boxed version. The type syntax with the bars is just syntactic sugar for the latter (and, in trait bound position, for the former).
> 
> It's somewhat unfortunate but I don't see a particularly good alternative if we want boxed and unboxed closures alike to have nice-looking APIs. The alternative, I guess, is to block 1.0 on unboxed closures, convert all our APIs to unboxed closures where possible, and just say that if you want a boxed closure you have to write `&mut |x| x + 1` at each closure construction site...
> 
> Patrick
> 
> "Gábor Lehel" <glaebhoerl at gmail.com> wrote:
> >Wouldn't it have to be `&mut` rather than `&` to fit the semantics of |
> >|,
> >which is affine and can mutate its environment?
> >
> >And wouldn't this lead to divergence between the type- and value
> >syntax,
> >with | | as a type being a boxed closure (`&mut FnMut`), and an unboxed
> >closure as a value? This was one of the nicer points of the recent
> >closure
> >overhaul, and it would be a shame to lose it so soon.
> >
> >
> >On Mon, Dec 30, 2013 at 10:11 PM, Patrick Walton
> ><pcwalton at mozilla.com>wrote:
> >
> >> I've been thinking that to future-proof unboxed closures in the
> >future we
> >> should maybe limit `|x| x+1` lambda syntax to either (a) require `&`
> >in
> >> front or (b) in function position.
> >>
> >> So today you would write:
> >>
> >>     let f = |x| x+1;
> >>
> >> But tomorrow you would write:
> >>
> >>     let f = &|x| x+1;
> >>
> >> But it would always work here:
> >>
> >>     v.map(|&x| x+1);
> >>
> >> The reason is simply that we'd like `|x| x+1` to become an unboxed
> >closure
> >> in the future and it's easier in the language semantics to
> >future-proof for
> >> it this way: we simply special-case the function argument position.
> >>
> >> Alternatively we can do it with assignability: say that `|x| x+1` is
> >an
> >> anonymous type (an error today) that is assignable to the type
> >> `|int|->int`. That might be cleaner than special-casing the function
> >> argument position.
> >>
> >> Patrick
> >> _______________________________________________
> >> Rust-dev mailing list
> >> Rust-dev at mozilla.org
> >> https://mail.mozilla.org/listinfo/rust-dev
> >>
> 
> -- 
> Sent from my Android phone with K-9 Mail. Please excuse my brevity.

> _______________________________________________
> Rust-dev mailing list
> Rust-dev at mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev



More information about the Rust-dev mailing list