# How to define async methods without capturing lifetime of self

**URL:** <https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708>\
**Category:** Uncategorized\
**Created:** [August 14, 2019, 6:35am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708 "2019-08-14T06:35:17Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 6:35am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/1 "2019-08-14T06:35:18Z")

</div>

I have some code I wanted to move to async-await. Here the `NamedFuture` struct doesn't capture any lifetime.

```rust
impl Struct {
    fn foo(&self) -> NamedFuture {
        // do stuff
        self.bar()
    }

    fn bar(&self) -> NamedFuture {
         NamedFuture::new()
    }
}

```

But changing this to use async-await:

```rust
impl Struct {
    async fn foo(&self) {
        // do stuff
        self.bar().await
    }

    async fn bar(&self) {
         NamedFuture::new().await
    }
}

```

The async-version captures the lifetime of `self` which breaks lots of existing uses such as:

```rust
let fut = {
    let s = Struct::new();
    s.foo();
}

```

or:

```rust
let s = Struct::new();
let fut = s.foo();
tokio::spawn(fut);

```

Can we somehow indicates or the compiler can infer that the returned future doesn't need to capture self and bind to its lifetime?

_Real world use case_: Hyper's `Client::get` currently returns `ResponseFuture` which doesnt capture self.

---

<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:** [August 14, 2019, 8:02am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/2 "2019-08-14T08:02:43Z")

</div>

There is no way to annotate an `async fn` to not capture a lifetime in it, and inferring that would go against Rust's current philosophy that function signature's should be able to be relied on independently of the body (other than auto-trait leakage in RPIT).

You can instead make `bar` a normal `fn` returning an `impl Future` and use an async block to define it:

```rust
impl Struct {
    fn bar(&self) -> impl Future<Output = ()> {
        async move {
            NamedFuture::new().await
        }
    }
}

```

You then have all the normal capabilities of RPIT to accurately define which lifetimes the return type captures.

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 8:14am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/3 "2019-08-14T08:14:42Z")

</div>

Yes that's a possible solution but it turns ugly when you have branching code. It's a bunch of nested `Either`s.

> <https://github.com/hyperium/hyper/blob/master/src/client/mod.rs#L450>

I had a relief when I changed method to async. The code became very clean, but it doesnt work as expected.

---

<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:** [August 14, 2019, 8:16am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/4 "2019-08-14T08:16:21Z")

</div>

The body of an async block is basically identical to the body of an `async fn` (and you can see the latter as a desugaring to the former), you should be able to write it exactly the same as you would an `async fn` and just move the code inside the block.

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 8:19am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/5 "2019-08-14T08:19:24Z")

</div>

At some places, the branch conditions are `self`'s fields. If I move that condition inside `async` block, self is captured. If I keep it out of it, I can't write the code without `Either`.

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 8:28am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/6 "2019-08-14T08:28:16Z")

</div>

I guess we could move the "async" part of the code into free functions/async blocks and pass "copied or cloned state" to the them.

free functions will be better because of the better error handling support.

Will the situation be better with async closures? They produce future on executing them right?

---

<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:** [August 14, 2019, 8:34am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/7 "2019-08-14T08:34:21Z")

</div>

Async non-move closures are intended to have the same signature lifetime handling of async fn, so are unlikely to help. Current `async move |_| { ... }` closures are (as far as I'm aware) identical to closures returning async blocks (`|_| async move { ... }`).

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 9:53am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/8 "2019-08-14T09:53:57Z")

</div>

Thanks @Nemo157. I think I can use RPIT.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 14, 2019, 11:41am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/9 "2019-08-14T11:41:39Z")

</div>

> [@vehls](#):
>
> At some places, the branch conditions are `self` 's fields. If I move that condition inside `async` block, self is captured. If I keep it out of it, I can't write the code without `Either` .

The easiest way to do this is to compute the branch conditions before the block, assign them to `bool` variables, and then have the async block capture those variables and not `self`.

---

<div class="post-metadata">

**Author:** ![bill\_myers](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bill_myers/32/4085_2.png) [@bill\_myers](https://internals.rust-lang.org/u/bill_myers)\
**Post date:** [August 14, 2019, 11:58am UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/10 "2019-08-14T11:58:58Z")

</div>

Might be too late, but could this be an argument for not stabilizing async functions and instead relying only on async blocks, plus maybe a syntax to capture all lifetimes in the return type, so that the user has to explicitly make this choice? (e.g. fn foo([...]) -\> impl Future\<[...]\> + '\* )

---

<div class="post-metadata">

**Author:** ![najamelan](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/najamelan/32/3162_2.png) [@najamelan](https://internals.rust-lang.org/u/najamelan)\
**Post date:** [August 14, 2019, 12:06pm UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/11 "2019-08-14T12:06:26Z")

</div>

Async fn are useful in plenty of situations. I don't see why they should not be stabelized. Note that capturing the lifetime of self is problematic if you want to directly spawn the future on an executor (which usually requires a `'static` future.

If you have an async context that owns an object, it can perfectly `await` methods on that object. Your outer async context will still be `'static` and can be spawned.

The future has to capture lifetimes, since it's not run immediately, and the objects need to be around when it does. No different than any other struct that owns references to things.

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 12:42pm UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/12 "2019-08-14T12:42:54Z")

</div>

@withoutboatsYes thats the approach I am taking now. But it doesnt always feel as natural as writing an regular async fn.

@najamelanThing about letting self captured is that some of the code store the future. I ll be propagating lifetime to very large scope.

@bill_myersI dont think this is reason enough to block stablization of async fns. This problem can probablt solved better with a different design. My question is if something can be done for now. Most codebases doing these things will probably have to redesign around this or use RPIT or custom futures. Tokio already removed some of the poll\_\* functions in favour of async ones. So users will have to do the same.

---

<div class="post-metadata">

**Author:** ![withoutboats](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/withoutboats/32/4560_2.png) [@withoutboats](https://internals.rust-lang.org/u/withoutboats)\
**Post date:** [August 14, 2019, 4:44pm UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/13 "2019-08-14T16:44:24Z")

</div>

> [@vehls](#):
>
> @withoutboats Yes thats the approach I am taking now. But it doesnt always feel as natural as writing an regular async fn.

Obviously but there's no way around this. You can't use `self` within the async scope without capturing it, if you don't want to capture it you have to precompute whatever values you need before the async context is constructed. What you are writing is exactly what you want the program to do.

---

<div class="post-metadata">

**Author:** ![vehls](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vehls/32/5745_2.png) [@vehls](https://internals.rust-lang.org/u/vehls)\
**Post date:** [August 14, 2019, 5:33pm UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/14 "2019-08-14T17:33:25Z")

</div>

Thanks @withoutboats, I think I understand it now. Thanks all for your help.

---

<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:** [November 12, 2019, 5:40pm UTC](https://internals.rust-lang.org/t/how-to-define-async-methods-without-capturing-lifetime-of-self/10708/15 "2019-11-12T17:40:31Z")

</div>

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