Skip to content

Regression: "cycle detected when computing when T needs async drop" for mutually recursive types held across .await (no feature(async_drop)) #165263

Closed

Description

@LinZhihao-723

Code

This needs no feature gates and no AsyncDrop impl: two types that are mutually recursive through a Box, with a value of one of them alive across an .await.

pub enum A {
    X(Box<B>),
}

pub enum B {
    Y(A),
}

pub async fn run(a: Option<A>) {
    async {}.await;
    drop(a);
}

cargo check on a library crate (edition 2024) containing only the code above.

Current output

error[E0391]: cycle detected when computing when `A` needs async drop
 --> src/lib.rs:1:1
  |
1 | pub enum A {
  | ^^^^^^^^^^
  |
  = note: ...which immediately requires computing when `A` needs async drop again
note: cycle used when computing whether `core::option::Option<A>` needs async drop
 --> /rustc/f9ceb4a4d45a471eed7bd8c40dddb7c38e749e21/library/core/src/option.rs:598:0
  = note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>

Expected

It compiles, as it does on nightly-2026-10-31 (rustc 1.101.0-nightly (92b5b8c87 2026-10-29)) and on stable.

Real-world impact

sqlx-core 0.8.6 no longer compiles on the latest nightly: its Error contains Migrate(Box<MigrateError>), and MigrateError contains Error, so Result<(), Error> held across an .await hits the same cycle:

error[E0391]: cycle detected when computing when `error::Error` needs async drop
  --> .../sqlx-core-0.8.6/src/error.rs:32:1
   |
32 | pub enum Error {
   | ^^^^^^^^^^^^^^
   |
   = note: ...which immediately requires computing when `error::Error` needs async drop again
note: cycle used when computing whether `core::result::Result<(), error::Error>` needs async drop

Any crate depending on sqlx (with the migrate feature) fails to build on nightly, e.g. our CI: https://github.com/y-scope/clp/actions/runs/41262307638/job/124717885872

Bisection

cargo bisect-rustc --start 92b5b8c87c61b20adc9001b41baf587634a74734 --end f9ceb4a4d45a471eed7bd8c40dddb7c38e749e21 --access github --regress error -- check reports:

Regression in https://github.com/rust-lang/rust/commit/8465957442411717fd22366e6d219c2961e92dd4

That's the merge of rollup #165234. The only PR in it touching async-drop analysis is #164987 ("use adt_async_drop_tys for nested ADTs in needs_async_drop"), so I suspect it, though I haven't bisected inside the rollup. Possibly related: #164977 (a similar cycle for recursive types, but only with feature(async_drop)).

Version

rustc 1.101.0-nightly (f9ceb4a4d 2026-10-31)
binary: rustc
commit-hash: f9ceb4a4d45a471eed7bd8c40dddb7c38e749e21
commit-date: 2026-10-31
host: x86_64-unknown-linux-gnu
release: 1.101.0-nightly
LLVM version: 23.1.4

@rustbot label +regression-from-stable-to-nightly

Activity

  1. added
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    I-prioritizeIssue needs a team member to assess the impact. Will be replaced by P-{low,medium,high,critical}
    on Nov 1, 2026
  2. added
    A-destructorsArea: Destructors (`Drop`, …)
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    I-cycleIssue: A query cycle occurred while none was expected
    and removed
    needs-triageThis issue may need triage. Remove when done. See docs forge.rust-lang.org/release/issue-triaging
    on Nov 1, 2026
  3. theemathas commented on Nov 1, 2026

    @theemathas
    Contributor

    cc @Web4everyone32 (author of #164987), @oli-obk (reviewer)

  4. added
    A-boxArea: Our favorite opsem complication
    on Nov 1, 2026
  5. cyx2015s commented on Nov 1, 2026

    @cyx2015s

    No need to .await.

    Minimal reproduce:

    // test.rs
    pub struct A(Box<B>);
    pub struct B(A);
    pub async fn run(_: A) {}
    $ rustup run nightly rustc --edition=2024 --crate-type=lib test.rs
    error[E0391]: cycle detected when computing when `A` needs async drop
     --> test.rs:1:1
      |
    1 | pub struct A(Box<B>);
      | ^^^^^^^^^^^^
      |
      = note: ...which immediately requires computing when `A` needs async drop again
      = note: cycle used when computing whether `A` needs async drop
      = note: for more information, see <https://rustc-dev-guide.rust-lang.org/overview.html#queries> and <https://rustc-dev-guide.rust-lang.org/query.html>
    
    error: aborting due to 1 previous error

    Environment:

    rustup run nightly rustc --version
    rustc 1.101.0-nightly (f9ceb4a4d 2026-10-31)
  6. self-assigned this
    on Nov 1, 2026
  7. added
    S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issue
    S-has-bisectionStatus: A bisection has been found for this issue
    on Nov 1, 2026
  8. 16 remaining items

  9. added a commit that references this issue on Nov 1, 2026
    79a4455
  10. added a commit that references this issue on Nov 1, 2026
    1dc02d6
  11. added a commit that references this issue on Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-async-awaitArea: Async & AwaitA-boxArea: Our favorite opsem complicationA-destructorsArea: Destructors (`Drop`, …)C-bugCategory: This is a bug.I-cycleIssue: A query cycle occurred while none was expectedP-criticalCritical priorityS-has-bisectionStatus: A bisection has been found for this issueS-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions