# Naming the return type of an async function

**URL:** <https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085>\
**Category:** Uncategorized\
**Created:** [May 9, 2019, 10:02pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085 "2019-05-09T22:02:56Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [May 9, 2019, 10:02pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/1 "2019-05-09T22:02:56Z")

</div>

With async functions coming closer to stabilization I think this is an important to discuss. Under the current proposal if you have an `async fn foo() -> usize` it gets desugared to an `fn foo() -> impl Future<Output = usize>`. This has the problem that all `-> impl Trait` functions have of having an innameable return type. The solution for normal functions comes in the form of existencial type. Writen using the syntax [proposed here](https://github.com/rust-lang/rfcs/pull/2515#issuecomment-491063765) we can write

```rust
type FooReturn = impl Trait;
fn foo -> FooReturn { /**/ }

```

instead of

```rust
fn foo() -> impl Trait { /**/ }

```

as the author of the function to name the return type `FooReturn`. Because we don’t write `-> impl Future<Output = usize>` but `-> usize` in the current proposal this solution does not work for async functions and we will later have to create some special syntax for naming the return type in this way.

I feel like this is an important questing [discussed here](https://internals.rust-lang.org/t/pre-pre-rfc-async-methods-bounding-async-fns/7656) and that we should think of a solution for this before we stabalize `async foo() -> usize`. To avoid blocking in this we could initially only allow async blocks. Those have the same power as async function because the async function

```rust
async fn foo() -> usize { /**/ }

```

is just sugar for

```rust
fn foo() -> impl Future<Output = usize> { async { /**/ } }

```

which is a normal function with its body wrapped in an async block.

Personally I feel like stabilizing `-> T` at this time without looking at things like this would be a mistake. I feel like using `-> T` for a function that does not return `T` is confusing and that the unnameable return type is a symptom of a larger issue. This issue is that we are special casing these functions in a way where we will keep having to come up with workarounds for things that already work for normal functions. An other example of this is specifying additional trait bounds. @withoutboats [proposed a while back](https://internals.rust-lang.org/t/pre-pre-rfc-async-methods-bounding-async-fns/7656/51) to use

```rust
async(Sync) fn foo() -> usize

```

for an async function that returns `impl -> Future<Output = usize> + Send`. With the outer return type this does not have to be a special case at all as we can just write

```rust
async fn foo() -> impl Future<Output = usize> + Send { /**/ }
// or even to make the return type nameable
type FooReturn = impl Future<Output = usize> + Send; 
async fn foo() -> FooReturn { /**/ }

```

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [May 9, 2019, 10:09pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/2 "2019-05-09T22:09:24Z")

</div>

Discussion about this from the RFC itself:

> <https://github.com/rust-lang/rfcs/blob/master/text/2394-async_await.md#the-return-type-t-instead-of-impl-futureoutput--t>

And the conversation also talked about it, such as

> <https://github.com/rust-lang/rfcs/pull/2394#issuecomment-379363838>

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [May 9, 2019, 10:42pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/3 "2019-05-09T22:42:29Z")

</div>

I don’t actually see any text in that section of the RFC mentioning the naming problem.

On the discussion thread, the one comment I see addressing it head-on is [https://github.com/rust-lang/rfcs/pull/2394#issuecomment-379704976](https://github.com/rust-lang/rfcs/pull/2394#issuecomment-379704976), and no one seems to have objected to it. So it sounds like the position is that the nameability problem is not a blocking issue for regular `async fn`s since it’s no different from regular `impl Trait`, and it only becomes a blocking issue for `async fn` in traits just as it’s blocking for `impl Trait` in traits. Does that sound right?

---

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [May 9, 2019, 10:54pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/4 "2019-05-09T22:54:46Z")

</div>

The problem is that the solution for naming for normal functions using existensial types is

```rust
type FooReturn = impl Trait;
fn foo() -> FooReturn { /**/ }

```

which does not work for async functions as

```rust
type FooReturn = impl Future<Output = usize>;
async fn foo() -> FooReturn { /**/ }
// desugars to
type FooReturn = impl Future<Output = usize>;
fn foo() -> impl Future<Output = FooReturn> { async { /**/ } }

```

and

```rust
type FooReturn = usize;
async fn foo() -> FooReturn { /**/ }
// desugars to
type FooReturn = usize;
fn foo() -> impl Future<Output = FooReturn> { async { /**/ } }

```

both of which still do not give the return type of the function.

---

<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:** [May 9, 2019, 10:54pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/5 "2019-05-09T22:54:59Z")

</div>

Existential types have already been proposed and accepted

> <https://github.com/rust-lang/rust/issues/44685>
>
> This is the tracking issue for existential types, a part of rust-lang/rfcs#2071
> …
> 
> Blocking stabilization:
> 
> \- \[\] Implement
> \- \[\] Document
> \- \[\] Decide final syntax

> <https://github.com/rust-lang/rust/issues/34511>
>
> \## NEW TRACKING ISSUE = https://github.com/rust-lang/rust/issues/63066
> 
> \## Imp…lementation status
> 
> The basic feature as specified in \[RFC 1522\](https://github.com/rust-lang/rfcs/pull/1522) is implemented, however there have been revisions that are still in need of work:
> 
> \- \[x\] \[impl Trait in argument position\](https://github.com/rust-lang/rust/issues/44721)
> - \[x\] extend to cover traits
> - \[\] support elision https://github.com/rust-lang/rust/issues/49287
> \- \[x\] impl Trait in return position is basically implemented, but:
> - \[x\] \[filter lifetimes\](https://github.com/rust-lang/rust/issues/44725)
> - \[x\] code accepts types with out-of-scope lifetimes https://github.com/rust-lang/rust/issues/46541
> - \[x\] ICEs when interacting with elision https://github.com/rust-lang/rust/issues/43396
> - \[x\] ICE combining universal and existential https://github.com/rust-lang/rust/issues/46685
> - \[x\] ICE with nested lifetimes https://github.com/rust-lang/rust/issues/46464
> - \[x\] Infinitely recursive types not detected https://github.com/rust-lang/rust/issues/38064
> - \[x\] Better error message for infinitely recursive types https://github.com/rust-lang/rust/issues/47659 (fixed in #56074)
> - \[x\] do not accept \[nested impl trait described here\](https://github.com/rust-lang/rust/issues/34511#issuecomment-359950524) (fixed in #48072)
> \- \[x\] \`let x: impl Trait\`
> \- \[x\] \`static\` and \`const T: impl Trait\`
> \- \[\] \`abstract type\` 
> - \[x\] \[preliminary refactoring possibility\](https://github.com/rust-lang/rust/issues/44727)
> - \[x\] in modules
> - \[x\] in traits
> 
> \### RFCs
> 
> There have been a number of RFCs regarding impl trait, all of which are tracked by this central tracking issue.
> 
> \- https://github.com/rust-lang/rfcs/pull/1522
> - the original, which covered only impl Trait in return position for inherent functions
> \- https://github.com/rust-lang/rfcs/pull/1951
> - settling on a particular syntax design, resolving questions around the some/any proposal and others.
> - resolving questions around which type and lifetime parameters are considered in scope for an impl Trait.
> - adding impl Trait to argument position.
> \- https://github.com/rust-lang/rfcs/pull/2071
> - named \`abstract type\` in modules and impls
> - \[x\] Finalize syntax (https://github.com/rust-lang/rfcs/pull/2515)
> - \[\] Update RFC https://github.com/rust-lang/rfcs/pull/2289 to match that syntax if that RFC gets merged.
> - use of impl trait in \`let\`, \`const\`, and \`static\` positions
> \- https://github.com/rust-lang/rfcs/pull/2250
> - Finalizing the syntax of \`impl Trait\` and \`dyn Trait\` with multiple bounds
> 
> \### Unresolved questions
> 
> The implementation has raised a number of interesting questions as well:
> 
> \- \[x\] What is the precedence of the \`impl\` keyword when parsing types? Discussion: \[1\](https://github.com/rust-lang/rust/pull/35091#discussion\_r73736079)
> - e.g., how to associate \`Send\` for \`where F: Fn() -\> impl Foo + Send\`?
> - Resolved by https://github.com/rust-lang/rfcs/pull/2250.
> - \[x\] Implemented (?) in https://github.com/rust-lang/rust/pull/45294
> \- \[\] Should we allow \`impl Trait\` after \`-\>\` in \`fn\` types or parentheses sugar? #45994 
> \- \[\] Do we have to impose a DAG across all functions to allow for auto-safe leakage, or can we use some kind of deferral. Discussion: \[1\](https://github.com/rust-lang/rust/pull/35091#discussion\_r73738398)
> - Present semantics: DAG.
> \- \[x\] How should we integrate impl trait into regionck? Discussion: \[1\](https://github.com/rust-lang/rust/pull/35091#discussion\_r73734987), \[2\](https://github.com/rust-lang/rust/issues/34511#issuecomment-237289787)
> - Resolved in https://github.com/rust-lang/rust/pull/45701
> \- \[\] Should we permit specifying types if some parameters are implicit and some are explicit? e.g., \`fn foo\<T\>(x: impl Iterator\<Item = T\>\>)\`?
> - Current behavior: An error to specify types
> - Other alternatives: \[treat \`impl Trait\` as arguments in the list, permitting migration\](https://github.com/rust-lang/rust/issues/44721#issuecomment-330921814)
> \- \[\] \[Some concerns about nested impl Trait usage\](https://github.com/rust-lang/rust/issues/34511#issuecomment-350715858)
> \- \[x\] Should the syntax in an impl be \`existential type Foo: Bar\` or \`type Foo = impl Bar\`? (\[see here for discussion\](https://github.com/rust-lang/rust/pull/52650#discussion\_r204893239))
> - Settled by https://github.com/rust-lang/rfcs/pull/2515.
> \- \[\] Should the set of "defining uses" for an \`existential type\` in an impl be just items of the impl, or include nested items within the impl functions etc? (\[see here for example\](https://github.com/rust-lang/rust/pull/52650#discussion\_r204893239))

The first issue was closed as a duplicate of the second, now the second tracks both `impl Trait` and existential types.

* * *

> [@DDOtten](#):
>
> which does not work for async functions as
> 
> ```rust
> type FooReturn = impl Future<Output = usize>;
> async fn foo -> FooReturn { /**/ }
> 
> ```

You shouldn't need to put `impl Future` for async functions

---

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [May 9, 2019, 11:05pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/6 "2019-05-09T23:05:04Z")

</div>

> [@RustyYato](#):
>
> You shouldn’t need to put `impl Future` for async functions

This also does not work, see my edit to my previous reply. One solution for this would be to allow a way to name functions themselves. If we can not only call `foo` but can also use ` foo` itself or something like `typeof foo` for well the type of the function `foo` (each function defines its own type that implements the `Fn` traits) we could do `foo::Output` or `(typeof foo)::Output` where `Output` is the type defined by the `Fn` traits. Being able to name functions themselves is a problem which I think we do want to solve eventually regardless.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [May 9, 2019, 11:30pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/7 "2019-05-09T23:30:37Z")

</div>

```rust
async_fn!(my_fn(args...) -> T {...})

```

can expand to

```rust
my_fn(args...) -> T { async {...} }

```

I don’t know if this is good enough though.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 10, 2019, 1:22am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/8 "2019-05-10T01:22:50Z")

</div>

You should be able to do:

```rust
type FooRet = impl Future<Output = T>;
async fn foo() -> T { .. }

fn __foo_FooRet() {
    let _: FooRet = foo();
}

```

This will assign the return of `foo` to the existential type `FooRet`.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [May 10, 2019, 2:44am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/9 "2019-05-10T02:44:26Z")

</div>

One point is that `async fn foo(...) -> T` is not semantically equivalent to `fn foo(...) -> impl Future<Output=T>`.

The former, indicates that “this function should return immediately unless within a `async` block, with maximum cost of a struct constructor over the arguments”, and the later can do what ever it wanted to do before return.

This might not be implemented as a language restriction, but as long as the `async` keyword is appearing in the API, people will use this as documentation note of different behaviour guarantee.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [May 10, 2019, 2:49am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/10 "2019-05-10T02:49:39Z")

</div>

> [@earthengine](#):
>
> The former, indicates that “this function should return immediately unless within a `async` block, with maximum cost of a struct constructor over the arguments”

This is slightly incorrect:

`async fn`'s coroutine desugaring will _always_ be exactly one struct construction and then returning that `impl Future`. It's only on the `await`ting that it does anything else; it does the same thing when called in sync and async contexts.

(Side note this made me think about: `#[inline]` on `async fn` should probably just not exist, as it doesn't and can't mean anything.)

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [May 10, 2019, 2:54am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/11 "2019-05-10T02:54:55Z")

</div>

I would very much like to have `typeof` in the language, for this and many other reasons. I’d love to have `typeof(foo)::Output` and `typeof(foo)::Output::Output` (the latter giving the output type of the Future that foo returns).

---

<div class="post-metadata">

**Author:** ![DDOtten](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ddotten/32/4334_2.png) [@DDOtten](https://internals.rust-lang.org/u/DDOtten)\
**Post date:** [May 10, 2019, 12:27pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/12 "2019-05-10T12:27:21Z")

</div>

> [@CAD97](#):
>
> You should be able to do:
> 
> ```rust
> type FooRet = impl Future<Output = T>;
> async fn foo() -> T { .. }
> 
> fn __foo_FooRet() {
> let _: FooRet = foo();
> }
> 
> ```
> 
> This will assign the return of `foo` to the existential type `FooRet` .

That is an interesting way to do it I did not think of. I think this would work so we would at least have some way to do this. In the long term however I would not like this to be the only way to do this as you have to define a dummy function and because it would not show in the documentation that this is the return type of this function. A `typeof` definitely seems like a good long term solution for this problem and others. We could even think of a postfix `foo.type` now we are discussing postfix operators to avoid having a keyword that actually consists of two words (`type` and `typeof` are both already reserved as keywords so we could do this in this edition).

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [May 10, 2019, 3:55pm UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/13 "2019-05-10T15:55:26Z")

</div>

I think this is the right solution. Mind, I’m strongly in favor of being able to name the types of free functions without going through a `decltype` mechanism, which I’ve found is a pretty kludgey solution to the equivalent problems in C++. I think `typeof` is a good idea for other contexts (like macros or as a stopgap for naming some unpronounceable type until we get around to it).

---

<div class="post-metadata">

**Author:** ![abonander](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/abonander/32/1284_2.png) [@abonander](https://internals.rust-lang.org/u/abonander)\
**Post date:** [May 11, 2019, 8:25am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/14 "2019-05-11T08:25:42Z")

</div>

I’m surprised no one has suggested the simplest solution:

```rust
type FooRet = impl Future<Item = usize>;

#[verbatim_return]
async fn foo() -> FooRet {}

```

Where `#[verbatim_return]` applied to any `async fn` just says “don’t change the return type in the desugaring”. (Bikeshedding needed; e.g. `#[actual_return]`.)

Alternately you could wrap the return type in a generic lang-item that gets erased/unwrapped by the desugaring:

```rust
type FooRet = impl Future<Item = usize>;

// written
async fn foo () -> Verbatim<FooRet> {}

// rendered in docs, and the actual semantics
async fn foo() -> FooRet {}

```

Where when the `async fn` desugar sees `Verbatim<_>` as a return type it replaces it with the type parameter. Or, it could be an actual type in the `stdlib` that forwards the trait impl and the compiler copies it unchanged (less surprising but limited to traits implemented for the type).

Either of these could be applied to generators as well.

It also wouldn’t be too difficult to add nice diagnostics on return type mismatches, like "oh did you mean to use the return type verbatim? Use `#[verbatim_return]`"

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [May 11, 2019, 9:30am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/15 "2019-05-11T09:30:47Z")

</div>

An even simpler solution already exists, do the `async fn` to `async` block desugaring manually. It’s not just the return type that needs to be verbatim, it’s the whole function signature:

```rust
async fn foo<T: Into<String>>(bar: &usize, baz: T) -> Path {
    unimplemented!()
}

type FooRet<'a, 'b, T: 'b> = impl Future<Output = Path> + 'a + 'b;
fn foo<'a, 'b, T: Into<String> + 'b>(
    bar: &'a usize,
    baz: T,
) -> FooRet<'a, 'b, T> {
    async { unimplemented!() }
}

```

---

<div class="post-metadata">

**Author:** ![abonander](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/abonander/32/1284_2.png) [@abonander](https://internals.rust-lang.org/u/abonander)\
**Post date:** [May 11, 2019, 9:42am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/16 "2019-05-11T09:42:19Z")

</div>

That’s definitely an option but it’s not exactly the cleanest.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [May 11, 2019, 9:48am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/17 "2019-05-11T09:48:33Z")

</div>

It’s about as clean as it can be without introducing a specific feature for naming the return type after the async transform has modified it. With the verbatim return types you propose how would you connect the lifetimes up?

```rust
type FooRet<'a, 'b, T: 'b> = impl Future<Item = usize> + 'a + 'b;

#[verbatim_return]
async fn foo<T: Into<String>>(bar: &usize, baz: T) -> FooRet<T>

async fn foo<T: Into<String>>(bar: &usize, baz: T) -> Verbatim<FooRet<T>>

```

---

<div class="post-metadata">

**Author:** ![abonander](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/abonander/32/1284_2.png) [@abonander](https://internals.rust-lang.org/u/abonander)\
**Post date:** [May 11, 2019, 10:01am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/18 "2019-05-11T10:01:47Z")

</div>

It’s about the same amount of work to just have the attribute preserve the whole signature, I’m leaning much more toward that than the lang-item return type anyway.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [May 13, 2019, 5:28am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/19 "2019-05-13T05:28:22Z")

</div>

Instead of using attributes, would it be better to extend the language a bit to allow

```rust
type FooRet = MyFutureType; //My brilliant future type! Item=usize
fn foo() -> FooRet as async usize {}

```

---

<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:** [August 11, 2019, 5:28am UTC](https://internals.rust-lang.org/t/naming-the-return-type-of-an-async-function/10085/20 "2019-08-11T05:28:24Z")

</div>

Closed on August 11, 2019, 5:28am UTC

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