Cycle detected when borrow-checking a main function relying on static_cell nightly feature
Hi,
In the process of updating my project to rely on https://github.com/esp-rs/esp-hal/releases/tag/esp-hal-v1.0.0, I came across the following error.
error[E0391]: cycle detected when borrow-checking `__main::____embassy_main_task::____embassy_main_task_inner_function`
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of opaque `__main::____embassy_main_task::____embassy_main_task_inner_function::{closure#0}::T::{opaque#0}` via HIR typeck...
--> src/bin/main.rs:58:32
|
58 | let _x: &'static mut u32 = static_cell::make_static!(0u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires computing the opaque types defined by `__main::__embassy_main::POOL`...
--> src/bin/main.rs:29:1
Full compiler output
error[E0391]: cycle detected when borrow-checking `__main::____embassy_main_task::____embassy_main_task_inner_function`
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
|
note: ...which requires computing type of opaque `__main::____embassy_main_task::____embassy_main_task_inner_function::{closure#0}::T::{opaque#0}` via HIR typeck...
--> src/bin/main.rs:58:32
|
58 | let _x: &'static mut u32 = static_cell::make_static!(0u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...which requires computing the opaque types defined by `__main::__embassy_main::POOL`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires computing type of `__main::__embassy_main::POOL`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires evaluating type-level constant...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires const-evaluating + checking `__main::__embassy_main::POOL::{constant#0}`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires caching mir of `__main::__embassy_main::POOL::{constant#0}` for CTFE...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires elaborating drops for `__main::__embassy_main::POOL::{constant#0}`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
= note: ...which requires normalizing `embassy_executor::_export::task_pool_size<__main::____embassy_main_task, (embassy_executor::spawner::Spawner,), __main::____embassy_main_task::{opaque#0}, ValTree(Leaf(0x00000001): usize)>`...
note: ...which requires computing type of `__main::____embassy_main_task::____embassy_main_task_inner_function::{opaque#0}`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
note: ...which requires computing type of opaque `__main::____embassy_main_task::____embassy_main_task_inner_function::{opaque#0}`...
--> src/bin/main.rs:29:1
|
29 | #[esp_rtos::main]
| ^^^^^^^^^^^^^^^^^
= note: ...which again requires borrow-checking `__main::____embassy_main_task::____embassy_main_task_inner_function`, completing the cycle
note: cycle used when computing type of opaque `__main::____embassy_main_task::____embassy_main_task_inner_function::{closure#0}::T::{opaque#0}`
--> src/bin/main.rs:58:32
|
58 | let _x: &'static mut u32 = static_cell::make_static!(0u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
= note: this error originates in the attribute macro `esp_rtos::main` which comes from the expansion of the macro `static_cell::make_static` (in Nightly builds, run with -Z macro-backtrace for more info)
For more information about this error, try `rustc --explain E0391`.
error: could not compile `my-esp-project` (bin "my-esp-project") due to 1 previous error
Steps to reproduce
A standard cargo-based Rust project is provided at https://github.com/renkenono/embassy-static-cell-poc. The most important bits to note are the following dependencies and the relevant snippet of code.
Dependencies
esp-hal = { version = "1.0.0", features = ["defmt", "esp32c6", "unstable"] }
esp-rtos = { version = "0.2.0", features = [
"defmt",
"embassy",
"esp-alloc",
"esp-radio",
"esp32c6",
] }
# $ cargo tree
# │ ├── embassy-executor v0.9.1 (*)
# │ ├── embassy-sync v0.7.2 (*)
# │ ├── embassy-time-driver v0.2.1 (*)
# │ ├── embassy-time-queue-utils v0.3.0
# │ │ ├── embassy-executor-timer-queue v0.1.0
static_cell = { version = "2.1.1", features = ["nightly"] }
Simplified example
#[esp_rtos::main]
async fn main(_: Spawner) -> ! {
// [...]
let _x: &'static mut u32 = static_cell::make_static!(0u32);
// [...]
}
Potential lead
I think the problem might stem from the fact that static_cell relies on impl Trait syntax to avoid requiring the user from specifying the underlying type as part of the make_static macro as seen at https://github.com/embassy-rs/static-cell/blob/v2.1.1/src/lib.rs#L241. This however appears to break the logic used underneath by embassy to calculate the number of tasks at compile-time (I assume?).
The reason why I create the issue here and not on static-cell is because I want to understand what embassy's main macro is doing underneath which requires all types to be computed prior to its execution.
Current workaround
- Using the non-nightly explicit way of defining
StaticCellobjects.
static SC: StaticCell<u32> = StaticCell::new();
let _x: &'static mut u32 = SC.init(0u32);
- Relying on a macro requiring the type to be passed as an argument as well to avoid opaque type computation such as the one used by esp-hal in their test framework.
// When you are okay with using a nightly compiler it's better to use https://docs.rs/static_cell/2.1.0/static_cell/macro.make_static.html
macro_rules! mk_static {
($t:ty,$val:expr) => {{
static STATIC_CELL: static_cell::StaticCell<$t> = static_cell::StaticCell::new();
#[deny(unused_attributes)]
let x = STATIC_CELL.uninit().write(($val));
x
}};
}
What should be the next step to fix this issue for the next release of embassy/static_cell? I'd like to contribute a fix if possible.
Thank you for your work on embassy!