rust-lang / rust-lang/rust

`Send` bound not inferred on RPIT due to nonsensical unsatisfied higher ranked bound

Open
#159,708 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-associated-items A-auto-traits A-higher-ranked A-impl-trait A-trait-system C-bug needs-triage T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

Extracted from #159575

trait SomeTrait {} // doesnt matter which trait we use for this

trait Trait {
    type Assoc;
}

// error goes away when implementing for `dyn SomeTrait + '_`
impl Trait for dyn SomeTrait {
    type Assoc = ();
}

// The future returned here is obviously `Send`.
// Adding an explicit `+ Send` bound demonstrates this and makes the error go away.
fn future<T: Trait + ?Sized>() -> impl Future<Output = T::Assoc> {
    async { todo!() }
}

fn use_send(_: impl Send) {} // to assert the `Send` bound

fn main() {
    use_send(async { future::<dyn SomeTrait>().await }); // error
}

Compiler output

error: implementation of `Trait` is not general enough
  --> src/main.rs:21:5
   |
21 |     use_send(async { future::<dyn SomeTrait>().await }); // error
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Trait` is not general enough
   |
   = note: `(dyn SomeTrait + '0)` must implement `Trait`, for any lifetime `'0`...
   = note: ...but `Trait` is actually implemented for the type `(dyn SomeTrait + 'static)`

With -Znext-solver:

error: higher-ranked subtype error
  --> src/main.rs:21:5
   |
21 |     use_send(async { future::<dyn SomeTrait>().await }); // error
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

There should not be any higher ranked logic involved here, since dyn SomeTrait in both cases is just the fixed type dyn SomeTrait + 'static (error still happens if written as such). Replacing both occurrences with a type like () makes the error go away. The error also happens if dyn SomeTrait is wrapped in Box or similar.

Adding an explicit + Send bound to the RPIT makes the error go away but can "cause" (unknown if this is the cause) an ICE on the old solver later on (see #159575).

Removing the seemingly redundant async { (...).await } also causes the error to go away.

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 compiling the reduced example in src/main.rs and compare the default solver with -Znext-solver, focusing on the RPIT, dyn SomeTrait, and async-await interactions described here. Done means the example no longer reports an erroneous higher-ranked bound for dyn SomeTrait without requiring an explicit + Send; also check the related behavior noted in #159575.

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
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.