# Give capturing closures transparent types

**URL:** <https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545>\
**Category:** language design\
**Created:** [March 2, 2019, 5:47am UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545 "2019-03-02T05:47:30Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Avi-D-coder](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/avi-d-coder/32/5252_2.png) [@Avi-D-coder](https://internals.rust-lang.org/u/Avi-D-coder)\
**Post date:** [March 2, 2019, 5:47am UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/1 "2019-03-02T05:47:30Z")

</div>

Why can’t the type of capturing closures be named? What is the reason for opaque types like `closure@main.rs:10:65: 10:78 x:_, y:_]`?

Couldn’t capturing closures be implemented with types like:

```rust
struct Capturing<E, F> {
    environment: E,
    fn_ptr: F,
}

```

```rust
let x = 1;
let y = 2;
let lambda: Capturing<(&isize, &isize), fn(&isize, &isize, &isize) -> &isize> = |n| x + y + n;

```

```rust
let mut foo = "foo";
let mut make_bar: Capturing<(&mut usize), fn(&mut str)> = || foo = "bar";

```

```rust
let foo = "foo".to_owned();
let foo_with: Capturing<(String), fn(String, String)> = move |suffix: String| println!("{}{}", foo, suffix);
// Relevant impls would be generated; E.g:
impl FnOnce(String) for Capturing<(String), fn(String, String)> {}

```

Currying could be implemented by generating implementations of `Fn*` traits for each case/arity of partial application.

Am I missing something that requires capturing closures be opaque?

---

<div class="post-metadata">

**Author:** ![sfackler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sfackler/32/9_2.png) [@sfackler](https://internals.rust-lang.org/u/sfackler)\
**Post date:** [March 2, 2019, 6:39am UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/2 "2019-03-02T06:39:49Z")

</div>

Closures don’t contain a function pointer, their Fn trait implementation directly contains the code.

---

<div class="post-metadata">

**Author:** ![Avi-D-coder](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/avi-d-coder/32/5252_2.png) [@Avi-D-coder](https://internals.rust-lang.org/u/Avi-D-coder)\
**Post date:** [March 2, 2019, 7:17am UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/3 "2019-03-02T07:17:18Z")

</div>

`fn_ptr` could be named `func` and be marked `?Sized` to support inline fully applied functions.

---

<div class="post-metadata">

**Author:** ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)\
**Post date:** [March 2, 2019, 11:55am UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/4 "2019-03-02T11:55:02Z")

</div>

I would recommend reading my blog to see how closures are desugared before making changes to it. My blog gives a detailed account of how closures are desugared, including little bits sich as mhow the move keyword interacts with closures.

> **[Closures: Magic Functions](https://rustyyato.github.io/rust/syntactic/sugar/2019/01/17/Closures-Magic-Functions.html)**
>
> If you want to respond to this post, please respond via Rust users or Reddit.

Basically closures have a hidden enviornment parameter which is made explicit by the `Fn*` traits, so the struct containing the captured enviornment only needs to contain the enviornment, no need to store a function pointer.

---

<div class="post-metadata">

**Author:** ![dhm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dhm/32/4879_2.png) [@dhm](https://internals.rust-lang.org/u/dhm)\
**Post date:** [March 2, 2019, 2:21pm UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/5 "2019-03-02T14:21:19Z")

</div>

> [@Avi-D-coder](#):
>
> Why can’t the type of capturing closures be named? What is the reason for opaque types like `closure@main.rs:10:65: 10:78 x:_, y:_]` ?

Because for each closure, the compiler creates a new environment struct;

> [@Avi-D-coder](#):
>
> Am I missing something that requires capturing closures be opaque?

If you **really** need explicit types for your closures, then you have to do the unsugaring yourself instead of letting the compiler do it.

What currently prevents us from doing it in stable is the fact that `Fn` traits are unstable: it is still unclear whether their current design is good enough to become future-proof; it may thus change in the future, which would be a breaking change if it were stable.

Obviously stable `Fn` traits would be a very sweet thing to have, indeed.

> [@Avi-D-coder](#):
>
> Couldn’t capturing closures be implemented with types like:
> 
> ```rust
> struct Capturing<E, F> {
> environment: E,
> fn_ptr: F,
> }
> 
> ```

This may be surprising, but **monomorphisation is that powerful of a tool that you don't require function pointers around, it's all done statically** (this is one of the places where Rust just blatantly outperforms C).

Since @RustyYato's blog post already covers closures, I will give an example of monomorphisation vs parameter that does not involve closures, since they are not needed to show the example:

### Example ([playground](https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=9ceaf6a448b0b186e143dcf88a88710e))

1. **Dynamic argument**

2. **Static (type-level) argument**

That is, even though we call it with a `One` argument (_c.f._ `repeat_hi_static(One);` ), the "number `1`" **information of `One` is not within its struct but within its type** (in a similar vein as to why a `&[u8; 4]` contains just an address whilst a `&[u8]` [contains _both an address and a size_](https://doc.rust-lang.org/reference/dynamically-sized-types.html)).

In a similar fashion, a closure's "`call` function" is relative to the type of the closure.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [May 31, 2019, 2:21pm UTC](https://internals.rust-lang.org/t/give-capturing-closures-transparent-types/9545/6 "2019-05-31T14:21:19Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
