rust-lang / rust-lang/rust

RPITIT implementation requires bounds inconsistently

Open
#150,418 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

I tried this code:

pub trait Exists<T: ?Sized> {}
impl<T: ?Sized, U: ?Sized> Exists<T> for U {}

pub trait Rpitit<Arg> {
    type Assoc;
    fn method<'a>(&'a self) -> impl Exists<&'a Self::Assoc>
    where
        Self::Assoc: 'a;
}

impl<Arg> Rpitit<Arg> for Option<Arg> {
    type Assoc = Option<Arg>;
    fn method<'a>(&'a self) -> impl Exists<&'a Self::Assoc>
    where
        Self::Assoc: 'a,
    {
    }
}

I expected to see this happen: Compiles successfully.

Instead, this happened:

error[E0276]: impl has stricter requirements than trait
 --> src/lib.rs:8:22
  |
8 |         Self::Assoc: 'a;
  |                      ^^ impl has extra requirement `Arg: 'a`

(Incidentally, this error is too terse and does not even point at the error site (it points at the trait definition, not the implementation). Let me know if you want a separate diagnostic issue.)

The error seems bad and inconsistent for a few reasons.

  1. The bounds on the implementation match the trait definition. Ideally it should not be possible for that to fail.
  2. self: &'a Self, so there is an implicit Option<Arg>: 'a bound, and thus an implicit Arg: 'a bound.
  3. The following changes do compile.
 impl<Arg> Rpitit<Arg> for Option<Arg> {
-    type Assoc = Option<Arg>;
+    type Assoc = Arg;
     fn method<'a>(&'a self) -> impl Exists<&'a Self::Assoc>
     where
         Self::Assoc: 'a,
     {
     }
 }
 pub trait Rpitit<Arg> {
     type Assoc;
     fn method<'a>(&'a self) -> impl Exists<&'a Self::Assoc>
     where
+        Self: 'a,
         Self::Assoc: 'a;
 }
+// (Implementation does *not* need to add `where Self: 'a`)

The next solver has the same behavior. (The error is a bit less terse, but still only points at the trait definition.)

#150417 demonstrates similar behavior with GATs instead of RPITITs. Based on that issue, it looks like the RPITIT doesn't inherit the implicit Self: 'a bound. It seems to me that RPITIT should be able to do so independently of #87479, as the opaque is unique to the single method.

I don't have an explanation of how Type = Arg can work without the Self: 'a bound when Type = Option<Arg> does not.

This issue is inspired by this URLO thread.

Meta

Playground:

  • Stable channel: 1.92.0
  • Beta channel: 1.93.0-beta.4 (2025-12-18 e17ea4bf4e2f2094ad56)
  • Nightly channel: 1.94.0-nightly (2025-12-25 fabece9e9491d0a3c365)

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 running the stable, beta, and nightly reproducer linked in the issue and compare it with the next-solver result. Use the example at src/lib.rs:8 and issue #150417 to investigate the differing implicit lifetime-bound behavior; done means the valid implementation is accepted consistently and the regression is covered by a compiler test.

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.