1
votes

According to the docs on task::spawn (note I'm using tokio::spawn which seems similar but lacks the description)

The 'static constraint means that the closure and its return value must have a lifetime of the whole program execution. The reason for this is that threads can detach and outlive the lifetime they have been created in. Indeed if the thread, and by extension its return value, can outlive their caller, we need to make sure that they will be valid afterwards, and since we can't know when it will return we need to have them valid as long as possible, that is until the end of the program, hence the 'static lifetime.

I'm trying to pass a Url into a thread, like this,

do_update(confg.to_feed_url()).await;

Where I do this in do_update,

  async fn do_update(url: Url) {
    let task = task::spawn(async {
      let duration = Duration::from_millis(5_000);
      let mut stream = time::interval(duration);
      stream.tick().await;
      loop {
        feeds::MyFeed::from_url(url.clone(), true);

This doesn't work and generates these errors,

error[E0373]: async block may outlive the current function, but it borrows url, which is owned by the current function

I've read the docs, but this doesn't much make sense to me because I'm cloning in the block. How can I resolve this error?

1
The 'static constraint means that the closure and its return value must have a lifetime of the whole program execution. - This is slightly misleading. The closure must either own the values it uses (in which case it can prolong their lifetimes arbitrarily) or, if it refers to non-owned values, those must be valid until the end of the program. Non-static data can be made owned just by moving it to the closure. If you need to keep referring to the data, you can wrap it in an Arc and move its clone into the closure.user4815162342
See this excellent guide for details.user4815162342

1 Answers

4
votes

In this case, if you don't need the URL elsewhere, you can write async move for your block instead of async, which will move the URL (and anything else the block captures, which it looks like is nothing) into the block.

If you do need it elsewhere, then you can clone the url variable outside of the block and then do the same thing (async move) to move just that particular variable into the block and not url itself. The clone call will probably not be necessary in such a case.

This occurs because url lives outside the block and calling url.clone borrows it (probably immutably, but it depends on the implementation). Since its scope is this function and not the life of the program, it won't live for the 'static lifetime and hence you need to move it into the block instead of borrowing.