rust-lang / rust-lang/rust

Compiler hang on resursive trait bound when async fn in trait

Open
#117,999 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-trait-system C-bug fixed-by-next-solver I-compilemem I-hang T-compiler
Dominant language
Rust
Stars
119k
Forks
16.2k
PR merge metrics
PR metrics pending

Description

Code
pub trait HasError {
    type Error;
}

pub trait Foo: HasError {
    // removing `async` emits E0275 instead of hanging until OOM
    async fn foo() -> Result<(), Self::Error>;
}

pub struct MyStruct<'a> {
    _inner: &'a (),
}

impl<'a> HasError for MyStruct<'a>
where
    Self: HasError<Error = ()>,
{
    type Error = ();
}

impl<'a> Foo for MyStruct<'a> {
    async fn foo() -> Result<(), ()> {
        loop {}
    }
}

Playground, with more comments

Meta

rustc --version --verbose:

rustc 1.76.0-nightly (6b771f6b5 2023-11-15)
binary: rustc
commit-hash: 6b771f6b5a6c8b03b6322a9c77ac77cb346148f0
commit-date: 2023-11-15
host: x86_64-unknown-linux-gnu
release: 1.76.0-nightly
LLVM version: 17.0.5

FWIW, also fails on stable 1.70 and 1.60, sometimes with error output about the recursion limit, but always hangs in the versions I tried.

Error output
<no output given by cargo, hangs until OOM killed>
Using -Ztrait-solver=next

Fixed when using -Ztrait-solver=next on nightly (2023-11-15 shown above), as it reports an error correctly.
Posting this issue because I'm not sure how soon that "next" trait solver will become the default (e.g. for stable).

$ RUSTFLAGS="-Ztrait-solver=next" cargo c
+ command cargo c
    Checking ice_117999 v0.1.0 (/home/user/ice_117999)
error[E0275]: overflow evaluating the requirement `<impl Future<Output = Result<(), ()>> as Future>::Output == Result<(), <MyStruct<'a> as HasError>::Error>`
  --> src/lib.rs:38:5
   |
38 |     async fn foo() -> Result<(), ()> {
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`ice_117999`)
note: required by a bound in `Foo::{opaque#0}`
  --> src/lib.rs:18:5
   |
18 |     async fn foo() -> Result<(), Self::Error>;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`

For more information about this error, try `rustc --explain E0275`.
error: could not compile `ice_117999` (lib) due to previous error

Backtrace - not available, since rustc hangs until OOM killed

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the issue from the code in src/lib.rs with cargo check, comparing the default trait solver with -Ztrait-solver=next. Trace the rustc handling of the recursive trait-bound requirement and async trait method, then ensure the default solver reports E0275 instead of hanging until OOM.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.