rust-lang / rust-lang/rust

GAT implementation requires bounds inconsistently

Open
#150,417 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

A-GATs A-trait-system C-bug needs-triage T-types
Dominant language
Rust
Stars
119k
Forks
16.1k
PR merge metrics
PR metrics pending

Description

See #150418 for a version of this issue using RPITIT instead of GATs.

I tried this code:

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

pub trait NotAnRpitit<Arg> {
    type Assoc;
    type Gat<'a>: Exists<&'a Self::Assoc>
    where
        Self::Assoc: 'a;
    fn method<'a>(&'a self) -> Self::Gat<'a>;
    // (Disables issue 87479 *requirement* to have `Self: 'a` on Gat.)
    fn _shush(_: Self::Gat<'_>) {}
}

impl<Arg> NotAnRpitit<Arg> for Option<Arg> {
    type Assoc = Option<Arg>;
    type Gat<'a> = [&'a Self::Assoc; 0]
    where
        Self::Assoc: 'a;
    fn method<'a>(&'a self) -> Self::Gat<'a>
    {
        []
    }
}

I expected to see this happen: compiles, or is at least consistent with the first diff below.

Instead, this happened:

error[E0276]: impl has stricter requirements than trait
  --> src/lib.rs:24:22
   |
 6 |     type Gat<'a>: Exists<&'a Self::Assoc>
   |     ------------------------------------- definition of `Gat` from trait
...
24 |         Self::Assoc: 'a,
   |                      ^^ impl has extra requirement `Arg: 'a`

error[E0309]: the parameter type `Arg` may not live long enough
  --> src/lib.rs:22:5
   |
22 |     type Gat<'a> = [&'a Self::Assoc; 0]
   |     ^^^^^^^^^--^
   |     |        |
   |     |        the parameter type `Arg` must be valid for the lifetime `'a` as defined here...
   |     ...so that the reference type `&'a Option<Arg>` does not outlive the data it points at
   |
help: consider adding an explicit lifetime bound
   |
24 |         Self::Assoc: 'a, Arg: 'a
   |                          +++++++

The error seems bad and inconsistent for a couple reasons.

  1. The bounds on the implementation match the trait definition. Ideally it should not be possible for that to fail.
  2. The following changes do compile.
 impl<Arg> NotAnRpitit<Arg> for Option<Arg> {
-    type Assoc = Option<Arg>;
+    type Assoc = Arg;
     type Gat<'a> = [&'a Self::Assoc; 0]
     where
         Self::Assoc: 'a;
     fn method<'a>(&'a self) -> Self::Gat<'a>
     {
         []
     }
 }
pub trait NotAnRpitit<Arg> {
    type Assoc;
    type Gat<'a>: Exists<&'a Self::Assoc>
    where
+        Self: 'a,
         Self::Assoc: 'a;
     fn method<'a>(&'a self) -> Self::Gat<'a>;
     // (Disables issue 87479 *requirement* to have `Self: 'a` on Gat.)
     fn _shush(_: Self::Gat<'_>) {}
 }

 impl<Arg> NotAnRpitit<Arg> for Option<Arg> {
     type Gat<'a> = [&'a Self::Assoc; 0]
     where
+        Self: 'a,
         Self::Assoc: 'a;

The next solver has the same behavior.

I've wrestled with GATs enough that the second diff working doesn't surprise me (and the current #87479 requirements mean it's less likely for this issue to be encountered in practice). But I have no clue why type = Arg compiles while type = Option<Arg> does not.

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

Reproduce the example in src/lib.rs using the linked Rust Playground, then compare the reported behavior with the two compiling variants and the next-solver result. Read the related discussions in #150418 and #87479. Done means the inconsistent bound behavior is explained and the compiler diagnostics or implementation are corrected accordingly.

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.