Skip to content

RPITIT implementation requires bounds inconsistently #150418

@QuineDot

Description

@QuineDot

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 e17ea4b)
  • Nightly channel: 1.94.0-nightly (2025-12-25 fabece9)

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-impl-traitArea: `impl Trait`. Universally / existentially quantified anonymous types with static dispatch.A-trait-systemArea: Trait systemC-bugCategory: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.needs-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