Tokio Recursion Error

Hi all,

I try to use reccursion with tokio::spawn function and got the following strange error:

<MyPath>/.cargo/bin/cargo.exe build --color=always --all --all-targets
warning: unused import: `tokio::prelude::*`
 --> src\main.rs:1:5
  |
1 | use tokio::prelude::*;
  |     ^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `BoxFuture`
 --> src\main.rs:5:23
  |
5 | use futures::future::{BoxFuture, FutureExt};
  |                       ^^^^^^^^^

warning: unused import: `tokio::prelude::*`
 --> src\main.rs:1:5
  |
1 | use tokio::prelude::*;
  |     ^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

warning: unused import: `BoxFuture`
 --> src\main.rs:5:23
  |
5 | use futures::future::{BoxFuture, FutureExt};
  |                       ^^^^^^^^^

error[E0391]: cycle detected when processing `handle_url::{{opaque}}#0`
  --> src\main.rs:7:35
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...which requires borrow-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires unsafety-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...which requires evaluating trait selection obligation `for<'r, 's> {std::future::ResumeTy, url::Url, &'r url::Url, impl core::future::future::Future, ()}: std::marker::Send`...
   = note: ...which again requires processing `handle_url::{{opaque}}#0`, completing the cycle
note: cycle used when checking item types in top-level module
  --> src\main.rs:1:1
   |
1  | / use tokio::prelude::*;
2  | | use scraper::{Html, Selector};
3  | | use reqwest::Url;
4  | | use url::ParseError;
...  |
42 | |     Ok(())
43 | | }
   | |_^

error[E0391]: cycle detected when processing `handle_url::{{opaque}}#0`
  --> src\main.rs:7:35
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...which requires borrow-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires processing `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires unsafety-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...which again requires processing `handle_url::{{opaque}}#0`, completing the cycle
note: cycle used when checking item types in top-level module
  --> src\main.rs:1:1
   |
1  | / use tokio::prelude::*;
2  | | use scraper::{Html, Selector};
3  | | use reqwest::Url;
4  | | use url::ParseError;
...  |
42 | |     Ok(())
43 | | }
   | |_^

error: aborting due to 2 previous errors; 2 warnings emitted

For more information about this error, try `rustc --explain E0391`.
error[E0391]: cycle detected when processing `handle_url::{{opaque}}#0`
  --> src\main.rs:7:35
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...which requires borrow-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...which requires evaluating trait selection obligation `for<'r, 's> {std::future::ResumeTy, url::Url, &'r url::Url, impl core::future::future::Future, ()}: std::marker::Send`...
   = note: ...which again requires processing `handle_url::{{opaque}}#0`, completing the cycle
note: cycle used when checking item types in top-level module
  --> src\main.rs:1:1
   |
1  | / use tokio::prelude::*;
2  | | use scraper::{Html, Selector};
3  | | use reqwest::Url;
4  | | use url::ParseError;
...  |
42 | |     Ok(())
43 | | }
   | |_^

error[E0391]: cycle detected when processing `handle_url::{{opaque}}#0`
  --> src\main.rs:7:35
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
note: ...which requires borrow-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `handle_url`...
  --> src\main.rs:7:1
   |
7  | async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   = note: ...which again requires processing `handle_url::{{opaque}}#0`, completing the cycle
note: cycle used when checking item types in top-level module
  --> src\main.rs:1:1
   |
1  | / use tokio::prelude::*;
2  | | use scraper::{Html, Selector};
3  | | use reqwest::Url;
4  | | use url::ParseError;
...  |
42 | |     Ok(())
43 | | }
   | |_^

error: could not compile `SearchEngine`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: aborting due to 2 previous errors; 2 warnings emitted

For more information about this error, try `rustc --explain E0391`.
error: could not compile `SearchEngine`.

To learn more, run the command again with --verbose.

Process finished with exit code 101

I use the following code:

async fn handle_url(url: &Url) -> Result<(), Box<dyn std::error::Error>> {
        // Some code
        tokio::spawn(async {
            handle_url(&child_url).await;
        }.boxed());
        // Some code
}

Without .boxed() it also complained !!

Have anyone idea what is it ?

What happens with this?

tokio::spawn(handle_url(child_url));

Alternatively you can define:

fn spawn_handle_url(url: String) {
    tokio::spawn(handle_url(url));
}

@alice

tokio::spawn(handle_url(child_url));

This code has the same error !!
Some recursion occurs !!

Then use the other approach I mentioned.

You can also try putting the spawn in its own block:

{
    tokio::spawn(handle_url(child_url));
}

Edit; This doesn't work. Define an ordinary function.

futures are like enums/structs, you can't them recursively without some kind of pointer.
try using ordinary futures (without the async keyword) with a Box:

Edit: See corrected example in post #14.

fn handle_url(url: &Url) -> Box<impl Future<Output=Result<(), Box<dyn std::io::Error>>>> {
    // some code
    tokio::spawn(async {
        handle_url(&child_url).await;
    });
    // some code.
}

Again some error occured:

error[E0277]: `(dyn std::error::Error + 'static)` cannot be sent between threads safely
   --> src\main.rs:8:5
    |
8   |     tokio::spawn(handle_url(url));
    |     ^^^^^^^^^^^^ `(dyn std::error::Error + 'static)` cannot be sent between threads safely

This is because your handle_url takes the url as a &str or similar type. You must take ownership with String to spawn the task.

Edit: I read the error message a bit too fast. This is because you are using Box<dyn Error> which cannot be sent across threads. You want Box<dyn Error + Send + Sync>.

Additionally spawning it like that would ignore any errors.

@alice

Thank you !!
It helped me !!

But why there was a recursion with tokio::spawn(handle_url(url)); ???

@alice
It helps, but another error occur at runtime !!

Url path is https://docs.rs/tokio/0.2.19/tokio/signal/index.html
thread 'tokio-runtime-worker' panicked at 'gai background task failed: JoinError::Cancelled', {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\dns.rs:144:30
stack backtrace:
   0: backtrace::backtrace::trace_unsynchronized
             at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.46\src\backtrace\mod.rs:66
   1: std::sys_common::backtrace::_print_fmt
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\sys_common\backtrace.rs:78
   2: std::sys_common::backtrace::_print::{{impl}}::fmt
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\sys_common\backtrace.rs:59
   3: core::fmt::write
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libcore\fmt\mod.rs:1069
   4: std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\io\mod.rs:1504
   5: std::sys_common::backtrace::_print
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\sys_common\backtrace.rs:62
   6: std::sys_common::backtrace::print
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\sys_common\backtrace.rs:49
   7: std::panicking::default_hook::{{closure}}
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\panicking.rs:198
   8: std::panicking::default_hook
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\panicking.rs:218
   9: std::panicking::rust_panic_with_hook
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\panicking.rs:511
  10: std::panicking::begin_panic_handler
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\panicking.rs:419
  11: std::panicking::begin_panic_fmt
             at /rustc/edc02580e4e80476ac1ded2cc1008eaf8b8400e6\/src\libstd\panicking.rs:373
  12: hyper::client::connect::dns::{{impl}}::poll::{{closure}}
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\dns.rs:144
  13: core::task::poll::Poll<core::result::Result<core::result::Result<hyper::client::connect::dns::IpAddrs, std::io::error::Error>, tokio::runtime::task::error::JoinError>>::map<core::result::Result<core::result::Result<hyper::client::connect::dns::IpAddrs, st
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\task\poll.rs:33
  14: hyper::client::connect::dns::{{impl}}::poll
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\dns.rs:141
  15: core::future::poll_with_context<hyper::client::connect::dns::GaiFuture>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  16: hyper::client::connect::dns::resolve::{{closure}}<hyper::client::connect::dns::GaiResolver>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\dns.rs:342
  17: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  18: core::future::poll_with_context<core::future::from_generator::GenFuture<generator-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  19: hyper::client::connect::http::{{impl}}::call_async::{{closure}}<hyper::client::connect::dns::GaiResolver>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\http.rs:307
  20: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  21: core::future::poll_with_context<core::future::from_generator::GenFuture<generator-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  22: hyper::client::connect::http::{{impl}}::call::{{closure}}<hyper::client::connect::dns::GaiResolver>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\http.rs:248
  23: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  24: core::future::future::{{impl}}::poll<alloc::boxed::Box<Future>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\future.rs:118
  25: hyper::client::connect::http::{{impl}}::poll<hyper::client::connect::dns::GaiResolver>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\connect\http.rs:388
  26: futures_util::future::either::{{impl}}::poll<hyper::client::connect::http::HttpConnecting<hyper::client::connect::dns::GaiResolver>,hyper::client::connect::http::HttpConnecting<hyper::client::connect::dns::GaiResolver>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\either.rs:62
  27: core::future::poll_with_context<futures_util::future::either::Either<hyper::client::connect::http::HttpConnecting<hyper::client::connect::dns::GaiResolver>, hyper::client::connect::http::HttpConnecting<hyper::client::connect::dns::GaiResolver>>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  28: hyper_tls::client::{{impl}}::call::{{closure}}<reqwest::connect::HttpConnector>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-tls-0.4.1\src\client.rs:115
  29: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  30: core::future::future::{{impl}}::poll<alloc::boxed::Box<Future>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\future.rs:118
  31: hyper_tls::client::{{impl}}::poll<tokio::net::tcp::stream::TcpStream>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-tls-0.4.1\src\client.rs:144
  32: core::future::poll_with_context<hyper_tls::client::HttpsConnecting<tokio::net::tcp::stream::TcpStream>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  33: reqwest::connect::{{impl}}::connect_with_maybe_proxy::{{closure}}
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.4\src\connect.rs:346
  34: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  35: core::future::poll_with_context<core::future::from_generator::GenFuture<generator-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  36: reqwest::connect::with_timeout::{{closure}}<reqwest::connect::Conn,core::future::from_generator::GenFuture<generator-0>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.4\src\connect.rs:500
  37: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  38: core::future::future::{{impl}}::poll<alloc::boxed::Box<Future>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\future.rs:118
  39: hyper::service::oneshot::{{impl}}::poll<reqwest::connect::Connector,http::uri::Uri>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\service\oneshot.rs:58
  40: futures_core::future::{{impl}}::try_poll<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>,reqwest::connect::Conn,alloc::boxed::Box<Error>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-core-0.3.4\src\future.rs:83
  41: futures_util::future::try_future::map_err::{{impl}}::poll<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>,fn(alloc::boxed::Box<Error>) -> hyper::error::Error,hyper::error::Error>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\try_future\map_err.rs:43
  42: futures_core::future::{{impl}}::try_poll<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>, fn(alloc::boxed::Box<Error>) -> hyper::error::Error>,reqwest::connect::Conn,hyper::er
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-core-0.3.4\src\future.rs:83
  43: futures_util::future::try_future::try_chain::TryChain<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>, fn(alloc::boxed::Box<Error>) -> hyper::error::Error>, futures_util::futu
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\try_future\try_chain.rs:53
  44: futures_util::future::try_future::and_then::{{impl}}::poll<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>, fn(alloc::boxed::Box<Error>) -> hyper::error::Error>,futures_util::
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\try_future\and_then.rs:46
  45: futures_util::future::either::{{impl}}::poll<futures_util::future::try_future::and_then::AndThen<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::uri::Uri>, fn(alloc::boxed::Box<Error>) 
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\either.rs:62
  46: hyper::common::lazy::{{impl}}::poll<closure-0,futures_util::future::either::Either<futures_util::future::try_future::and_then::AndThen<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::Oneshot<reqwest::connect::Connector, http::ur
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\common\lazy.rs:59
  47: futures_util::future::future::FutureExt::poll_unpin<hyper::common::lazy::Lazy<closure-0, futures_util::future::either::Either<futures_util::future::try_future::and_then::AndThen<futures_util::future::try_future::map_err::MapErr<hyper::service::oneshot::On
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\future\mod.rs:507
  48: futures_util::future::select::{{impl}}::poll<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>,hyper::common::lazy::Lazy<closure-0, futures_util::future::either::Either<futures_util::future::try_future::and_th
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\select.rs:64
  49: futures_util::future::future::chain::Chain<futures_util::future::select::Select<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>, hyper::common::lazy::Lazy<closure-0, futures_util::future::either::Either<futu
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\future\chain.rs:44
  50: futures_util::future::future::then::{{impl}}::poll<futures_util::future::select::Select<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>, hyper::common::lazy::Lazy<closure-0, futures_util::future::either::Eit
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\future\then.rs:44
  51: futures_core::future::{{impl}}::try_poll<futures_util::future::future::then::Then<futures_util::future::select::Select<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>, hyper::common::lazy::Lazy<closure-0, fu
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-core-0.3.4\src\future.rs:83
  52: futures_util::future::try_future::try_chain::TryChain<futures_util::future::future::then::Then<futures_util::future::select::Select<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>, hyper::common::lazy::Lazy<
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\try_future\try_chain.rs:53
  53: futures_util::future::try_future::and_then::{{impl}}::poll<futures_util::future::future::then::Then<futures_util::future::select::Select<hyper::client::pool::Checkout<hyper::client::PoolClient<reqwest::async_impl::body::ImplStream>>, hyper::common::lazy::
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\try_future\and_then.rs:46
  54: hyper::client::{{impl}}::retryably_send_request::{{closure}}<reqwest::connect::Connector,reqwest::async_impl::body::ImplStream>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\mod.rs:253
  55: futures_util::future::poll_fn::{{impl}}::poll<core::result::Result<http::response::Response<hyper::body::body::Body>, hyper::error::Error>,closure-0>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\futures-util-0.3.4\src\future\poll_fn.rs:54
  56: core::future::future::{{impl}}::poll<alloc::boxed::Box<Future>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\future.rs:118
  57: hyper::client::{{impl}}::poll
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\hyper-0.13.5\src\client\mod.rs:604
  58: reqwest::async_impl::client::{{impl}}::poll
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.4\src\async_impl\client.rs:1276
  59: reqwest::async_impl::client::{{impl}}::poll
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.4\src\async_impl\client.rs:1255
  60: core::future::poll_with_context<reqwest::async_impl::client::Pending>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  61: reqwest::get::{{closure}}<url::Url>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\reqwest-0.10.4\src\lib.rs:249
  62: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  63: core::future::poll_with_context<core::future::from_generator::GenFuture<generator-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:84
  64: SearchEngine::handle_url::{{closure}}
             at .\src\main.rs:21
  65: core::future::from_generator::{{impl}}::poll<generator-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\future\mod.rs:66
  66: tokio::runtime::task::core::{{impl}}::poll::{{closure}}<core::future::from_generator::GenFuture<generator-0>,alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\core.rs:163
  67: tokio::loom::std::unsafe_cell::UnsafeCell<tokio::runtime::task::core::Stage<core::future::from_generator::GenFuture<generator-0>>>::with_mut<tokio::runtime::task::core::Stage<core::future::from_generator::GenFuture<generator-0>>,core::task::poll::Poll<cor
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\loom\std\unsafe_cell.rs:14
  68: tokio::runtime::task::core::Core<core::future::from_generator::GenFuture<generator-0>, alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>::poll<core::future::from_generator::GenFuture<generator-0>,alloc::sync::Arc<tokio::runtime::thread_pool::
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\core.rs:148
  69: tokio::runtime::task::harness::{{impl}}::poll::{{closure}}<core::future::from_generator::GenFuture<generator-0>,alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\harness.rs:108
  70: core::ops::function::FnOnce::call_once<closure-0,()>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\ops\function.rs:232
  71: std::panic::{{impl}}::call_once<core::task::poll::Poll<core::result::Result<core::result::Result<(), alloc::boxed::Box<Error>>, tokio::runtime::task::error::JoinError>>,closure-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panic.rs:318
  72: std::panicking::try::do_call<std::panic::AssertUnwindSafe<closure-0>,core::task::poll::Poll<core::result::Result<core::result::Result<(), alloc::boxed::Box<Error>>, tokio::runtime::task::error::JoinError>>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panicking.rs:331
  73: std::panicking::try::do_catch<std::panic::AssertUnwindSafe<closure-0>,core::task::poll::Poll<core::result::Result<core::result::Result<(), alloc::boxed::Box<Error>>, tokio::runtime::task::error::JoinError>>>
  74: std::panicking::try<core::task::poll::Poll<core::result::Result<core::result::Result<(), alloc::boxed::Box<Error>>, tokio::runtime::task::error::JoinError>>,std::panic::AssertUnwindSafe<closure-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panicking.rs:274
  75: std::panic::catch_unwind<std::panic::AssertUnwindSafe<closure-0>,core::task::poll::Poll<core::result::Result<core::result::Result<(), alloc::boxed::Box<Error>>, tokio::runtime::task::error::JoinError>>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panic.rs:394
  76: tokio::runtime::task::harness::Harness<core::future::from_generator::GenFuture<generator-0>, alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>::poll<core::future::from_generator::GenFuture<generator-0>,alloc::sync::Arc<tokio::runtime::thread_
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\harness.rs:84
  77: tokio::runtime::task::raw::poll<core::future::from_generator::GenFuture<generator-0>,alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\raw.rs:104
  78: tokio::runtime::task::raw::RawTask::poll
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\raw.rs:66
  79: tokio::runtime::task::Notified<alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>::run<alloc::sync::Arc<tokio::runtime::thread_pool::worker::Worker>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\mod.rs:169
  80: tokio::runtime::thread_pool::worker::{{impl}}::run_task::{{closure}}
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:353
  81: tokio::coop::budget::{{closure}}<closure-0,core::result::Result<alloc::boxed::Box<tokio::runtime::thread_pool::worker::Core>, ()>>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\coop.rs:97
  82: std::thread::local::LocalKey<core::cell::Cell<usize>>::try_with<core::cell::Cell<usize>,closure-0,core::result::Result<alloc::boxed::Box<tokio::runtime::thread_pool::worker::Core>, ()>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\thread\local.rs:263
  83: std::thread::local::LocalKey<core::cell::Cell<usize>>::with<core::cell::Cell<usize>,closure-0,core::result::Result<alloc::boxed::Box<tokio::runtime::thread_pool::worker::Core>, ()>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\thread\local.rs:239
  84: tokio::coop::budget
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\coop.rs:79
  85: tokio::runtime::thread_pool::worker::Context::run_task
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:352
  86: tokio::runtime::thread_pool::worker::Context::run
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:324
  87: tokio::runtime::thread_pool::worker::run::{{closure}}
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:309
  88: tokio::macros::scoped_tls::ScopedKey<tokio::runtime::thread_pool::worker::Context>::set<tokio::runtime::thread_pool::worker::Context,closure-0,()>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\macros\scoped_tls.rs:64
  89: tokio::runtime::thread_pool::worker::run
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:306
  90: tokio::runtime::thread_pool::worker::{{impl}}::launch::{{closure}}
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\thread_pool\worker.rs:285
  91: tokio::runtime::blocking::task::{{impl}}::poll<closure-0,()>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\blocking\task.rs:38
  92: tokio::runtime::task::core::{{impl}}::poll::{{closure}}<tokio::runtime::blocking::task::BlockingTask<closure-0>,tokio::runtime::blocking::schedule::NoopSchedule>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\core.rs:163
  93: tokio::loom::std::unsafe_cell::UnsafeCell<tokio::runtime::task::core::Stage<tokio::runtime::blocking::task::BlockingTask<closure-0>>>::with_mut<tokio::runtime::task::core::Stage<tokio::runtime::blocking::task::BlockingTask<closure-0>>,core::task::poll::Po
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\loom\std\unsafe_cell.rs:14
  94: tokio::runtime::task::core::Core<tokio::runtime::blocking::task::BlockingTask<closure-0>, tokio::runtime::blocking::schedule::NoopSchedule>::poll<tokio::runtime::blocking::task::BlockingTask<closure-0>,tokio::runtime::blocking::schedule::NoopSchedule>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\core.rs:148
  95: tokio::runtime::task::harness::{{impl}}::poll::{{closure}}<tokio::runtime::blocking::task::BlockingTask<closure-0>,tokio::runtime::blocking::schedule::NoopSchedule>
             at {MyPath}\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.19\src\runtime\task\harness.rs:108
  96: core::ops::function::FnOnce::call_once<closure-0,()>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libcore\ops\function.rs:232
  97: std::panic::{{impl}}::call_once<core::task::poll::Poll<core::result::Result<(), tokio::runtime::task::error::JoinError>>,closure-0>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panic.rs:318
  98: std::panicking::try::do_call<std::panic::AssertUnwindSafe<closure-0>,core::task::poll::Poll<core::result::Result<(), tokio::runtime::task::error::JoinError>>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panicking.rs:331
  99: core::result::{{impl}}::into_result<std::sync::mutex::MutexGuard<()>,std::sys_common::poison::PoisonError<std::sync::mutex::MutexGuard<()>>>
 100: std::panicking::try<core::task::poll::Poll<core::result::Result<(), tokio::runtime::task::error::JoinError>>,std::panic::AssertUnwindSafe<closure-0>>
             at {MyPath}\.rustup\toolchains\nightly-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\panicking.rs:274
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

Consider the following code:

tokio::spawn(handle_url(url)); // Crashed
handle_url(url).await; // Ok

I have no idea why in tokio::spawn it crashed !!

When rustc compiles an async function it essentially generates a big enum with variants for each await point holding things like local variables and the future that is being awaited.

If you try to use recursion without an extra level of indirection then trying to await on handle_url(&child_url) means one of the enum variants would contain the future for handle_url... which means handle_url's enum would contain an instance of itself (which would contain an instance of itself, which would ...).

It's not possible to know the layout of such a recursive type, so the compiler will give up and tells you to use some indirection which has a known size (e.g. a Box).

@Michael-F-Bryan
Okay, but how can I .await on recursive call in the same function ?

Does something like handle_url(&child_url).boxed().await work?

Yes, except the function itself returns a Boxed & Pinned future...

fn handle_url(url: String) -> Pin<Box<dyn Future<Output=Result<(), ()>> + Send>> {
    Box::pin(async move {
        if url.len() <= 1 {
            return Ok(());
        }
        
        let child_url = (&url[1..]).to_string();
        
        tokio::spawn(handle_url(child_url));
        
        Ok(())
    })
}

Playground: https://play.rust-lang.org/?version=stable&mode=release&edition=2018&gist=f142c2b075bfa825351ca71100b06ab0

I just googled "rust async await recursion" and the first result it showed me was the Recursion chapter from The Async Book and they propose the same workaround:

In order to allow this, we have to introduce an indirection using Box . Unfortunately, compiler limitations mean that just wrapping the calls to recursive() in Box::pin isn't enough. To make this work, we have to make recursive into a non- async function which returns a .boxed() async block:

use futures::future::{BoxFuture, FutureExt};

fn recursive() -> BoxFuture<'static, ()> {
    async move {
        recursive().await;
        recursive().await;
    }.boxed()
}

You mean something like the following code:

enum FutureResult {
    HandleUrl2,
    HandleUrl,
}

fn do_some_stuff(url: &str) -> FutureResult {
    return FutureResult::HandleUrl2;
}

fn handle_url(url: &str) -> FutureResult {
    do_some_stuff(url);
    if url == "Some url" {
        return FutureResult::HandleUrl;
    }
    let child_url = "Some url";
    return handle_url(child_url);
}

But I do not see any issues with such approach !?

Right, the async keyword is just syntactic sugar that turns the call into an impl Future

The example you've shown isn't correct. Each async function is compiled into its own type.

// This function:
async fn foo() {
    step_one().await;
    step_two().await;
}
// generates a type like this:
enum Foo {
    First(StepOne),
    Second(StepTwo),
}

// So this function:
async fn recursive() {
    recursive().await;
    recursive().await;
}

// generates a type like this:
enum Recursive {
    First(Recursive),
    Second(Recursive),
}

(quoting the first section in the Async Book's Recursion chapter)

No it does not work (:

It's not only boxing the future, it must be pinned too... I've corrected my example in post #14.