Typecheck error when using a equality-constrained GAT in a trait. · Issue #91762 · rust-lang/rust (original) (raw)

In this code:

pub trait Functor { type With;

fn fmap<T, U>(this: Self::With<T>) -> Self::With<U>;

}

pub trait FunctorExt: Sized { type Base: Functor<With = Self>;

fn fmap<U>(self) {
    let arg: <Self::Base as Functor>::With<T>;
    let ret: <Self::Base as Functor>::With<U>;

    arg = self;
    ret = <Self::Base as Functor>::fmap(arg);
}

}

I would expect the code in FunctorExt to compile, as I'm constraining Self::Base::With<T> = Self, while Self::Base::With<U> should just be whatever With<T> is without any extra constraints.

But I'm getting this compiler error:

error[E0308]: mismatched types
  --> src/case3.rs:15:15
   |
7  | / pub trait FunctorExt<T>: Sized {
8  | |     type Base: Functor<With<T> = Self>;
9  | |
10 | |     fn fmap<U>(self) {
...  |
15 | |         ret = <Self::Base as Functor>::fmap(arg);
   | |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected associated type, found type parameter `Self`
16 | |     }
17 | | }
   | |_- this type parameter
   |
   = note: expected associated type `<<Self as FunctorExt<T>>::Base as Functor>::With<U>`
               found type parameter `Self`
   = note: you might be missing a type parameter or trait bound

For more information about this error, try `rustc --explain E0308`.
error: could not compile `hkt` due to previous error

It seems to me as if the Base: Functor<With<T> = Self>; constraint causes rustc to think that any With<X> should be the same type as Self, rather than just the one With<T> for the specific T in scope.

Meta

rustc --version --verbose:

rustc 1.58.0-nightly (495322d77 2021-11-08)
binary: rustc
commit-hash: 495322d776fd6f679cd8cd4ca02b8fa834da654b
commit-date: 2021-11-08
host: x86_64-unknown-linux-gnu
release: 1.58.0-nightly
LLVM version: 13.0.0