Unclear error message when using recursive future with tokio::spawn #112175
Open
Description
opened on Jun 1, 2023
Code
async fn tokio_fact(n: u32) -> u32 {
if n <= 1 {
return n;
} else {
let jh = tokio::spawn(tokio_fact(n-1));
jh.await.unwrap() * n
}
}
Current output
error[E0391]: cycle detected when computing type of `tokio_fact::{opaque#0}`
--> a/src/main.rs:99:33
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^
|
note: ...which requires borrow-checking `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires promoting constants in MIR for `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires preparing `tokio_fact` for borrow checking...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires unsafety-checking `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building MIR for `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires match-checking `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires building THIR for `tokio_fact`...
--> a/src/main.rs:99:1
|
99 | async fn tokio_fact(n: u32) -> u32 {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires type-checking `tokio_fact`...
--> a/src/main.rs:103:18
|
103 | let jh = tokio::spawn(tokio_fact(n-1));
| ^^^^^^^^^^^^
= note: ...which requires evaluating trait selection obligation `tokio_fact::{opaque#0}: core::marker::Send`...
= note: ...which again requires computing type of `tokio_fact::{opaque#0}`, completing the cycle
Desired output
I'm not sure what should be the proper error message. Because of the tokio::spawn
this is not the same problem as in E0733.
The workaround often proposed by @Darksonn on various forums is to use a wrapping non-async function:
async fn tokio_fact_bis(n: u32) -> u32 {
if n <= 1 {
return n;
} else {
fn tokio_fact_wrap(n : u32) -> JoinHandle<u32> {
tokio::spawn(tokio_fact_bis(n))
}
let jh = tokio_fact_wrap(n-1);
jh.await.unwrap() * n
}
}
Rationale and extra context
No response
Other cases
No response
Anything else?
No response
Activity