Skip to content

Rust does not correctly handle async recursion with nice errors in certain cases #144344

@cheesycod

Description

@cheesycod

I tried this code (its too big for a example and I don't have a MVP as it relies on a slew of things going wrong): https://github.com/Anti-Raid/khronos/blob/c67dbc8c1f3e4eb3bbfdd103d6ddb3fc3a877da0/crates/runtime/src/plugins/antiraid/discord/mod.rs#L194

I expected to see this happen: A error telling me to use async recursion/infinitely sized future error

Instead, this happened:

error[E0391]: cycle detected when computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider>::check_channel_permissions()}>`
    |
    = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider>::check_channel_permissions()}>`...
note: ...which requires computing layout of `{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider>::check_channel_permissions()}`...
   --> /home/antiraid/.cargo/git/checkouts/khronos-a39d166da77a1483/c67dbc8/crates/runtime/src/plugins/antiraid/discord/mod.rs:242:63
    |
242 | ...d(gt) => return self.check_channel_permissions(gt.owner_id, gt.parent_id.widen(), needed_permissions).await,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider>::check_channel_permissions()}>`, completing the cycle
note: cycle used when computing layout of `{async closure body@<khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider> as mluau::userdata::UserData>::add_methods<mluau::userdata::registry::UserDataRegistry<khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::dummyctx::DummyProvider>>>::{closure#6}::{closure#0}<templatingrt::primitives::dummyctx::DummyProvider>}`
   --> /home/antiraid/.cargo/git/checkouts/khronos-a39d166da77a1483/c67dbc8/crates/runtime/src/plugins/antiraid/discord/mod.rs:379:65
    |
379 |   ...   let (partial_guild, member, channel, permissions) = this.check_channel_permissions(data.user_id, data.channel_id, data...
    |  ___________________________________________________________^
380 | | ...       .await
    | |________________^
    = 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

error[E0391]: cycle detected when computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider>::check_channel_permissions()}>`
    |
    = note: ...which requires computing layout of `core::mem::manually_drop::ManuallyDrop<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider>::check_channel_permissions()}>`...
note: ...which requires computing layout of `{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider>::check_channel_permissions()}`...
   --> /home/antiraid/.cargo/git/checkouts/khronos-a39d166da77a1483/c67dbc8/crates/runtime/src/plugins/antiraid/discord/mod.rs:242:63
    |
242 | ...d(gt) => return self.check_channel_permissions(gt.owner_id, gt.parent_id.widen(), needed_permissions).await,
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires computing layout of `core::mem::maybe_uninit::MaybeUninit<{async fn body of khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider>::check_channel_permissions()}>`, completing the cycle
note: cycle used when computing layout of `{async closure body@<khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider> as mluau::userdata::UserData>::add_methods<mluau::userdata::registry::UserDataRegistry<khronos_runtime::plugins::antiraid::discord::DiscordActionExecutor<templatingrt::primitives::ctxprovider::TemplateContextProvider>>>::{closure#6}::{closure#0}<templatingrt::primitives::ctxprovider::TemplateContextProvider>}`
   --> /home/antiraid/.cargo/git/checkouts/khronos-a39d166da77a1483/c67dbc8/crates/runtime/src/plugins/antiraid/discord/mod.rs:379:65
    |
379 |   ...   let (partial_guild, member, channel, permissions) = this.check_channel_permissions(data.user_id, data.channel_id, data...
    |  ___________________________________________________________^
380 | | ...       .await
    | |________________^
    = 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

For more information about this error, try `rustc --explain E0391`.
error: could not compile `template-worker` (bin "template-worker") due to 2 previous errors

The error points to rustc-dev-guide and doesn't mention the recursion whatsoever.

While I'm not sure what the error is, it seems to be related to using a trait that contains a async function that recurses

Meta

rustc --version --verbose:

rustc 1.89.0-nightly (1677d46cb 2025-06-10)
binary: rustc
commit-hash: 1677d46cb128cc8f285dbd32b0dc4d7a46437050
commit-date: 2025-06-10
host: x86_64-unknown-linux-gnu
release: 1.89.0-nightly
LLVM version: 20.1.5

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-async-awaitArea: Async & AwaitC-bugCategory: This is a bug.E-needs-mcveCall for participation: This issue has a repro, but needs a Minimal Complete and Verifiable Exampleneeds-triageThis issue may need triage. Remove it if it has been sufficiently triaged.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions