rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.35k stars 12.59k forks source link

Weird error messages using GATs: cannot satisfy `<Self as Trait<'b>>::Assoc<'a> == '_`? #89635

Open timothee-haudebourg opened 2 years ago

timothee-haudebourg commented 2 years ago

Sorry for the title, I don't really know how to describe this issue otherwise. I've been playing with GATs and trying to define a trait that would allow me to encode covariance. I came up with the following erroneous code. I know why it cannot work, but I am surprised by the error messages I got:

/// Type that is covariant over `'a`.
pub trait Covariant<'a>: 'a {
    type Target<'b> where Self: 'b;

    fn shorter<'b>(self) -> Self::Target<'b> where 'a: 'b;

    fn unwrap<'c>(target: <Self as Covariant<'c>>::Target<'a>) -> Self where Self: Covariant<'c>;
}

impl<'a, T> Covariant<'a> for &'a T {
    type Target<'b> where Self: 'b = &'b T;

    fn shorter<'b>(self) -> &'b T where 'a: 'b {
        self
    }

    fn unwrap<'c>(target: &'a T) -> Self where Self: Covariant<'c> {
        target
    }
}

Everything works well without the unwrap function. But with it, I get some weird error messages:

error[E0284]: type annotations needed: cannot satisfy `<Self as Covariant<'c>>::Target<'a> == _`
 --> src/lib.rs:8:5
  |
8 |     fn unwrap<'c>(target: <Self as Covariant<'c>>::Target<'a>) -> Self where Self: Covariant<'c>;
  |        ^^^^^^ cannot satisfy `<Self as Covariant<'c>>::Target<'a> == _`

The compiler is unable to prove the equality of <Self as Covariant<'c>>::Target<'a> with... '_? How is that possible? What does it mean? Fine. Then I tried to help it a little by replacing this complicated type with a type parameter, who knows:

fn unwrap<'c, T>(target: T) -> Self where Self: Covariant<'c, Target<'a>=T>;

I get something even weirder in return:

error[E0283]: type annotations needed
 --> src/lib.rs:3:1
  |
3 | pub trait Covariant<'a>: 'a {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for type parameter `Self`
  |
  = note: cannot satisfy `Self: Covariant<'a>`
note: required by a bound in `Covariant`
 --> src/lib.rs:3:1
  |
3 | pub trait Covariant<'a>: 'a {
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Covariant`
help: consider specifying the type arguments in the function call
  |
3 | pub trait Covariant<'a>: 'a::<Self, 'a> {
  |                            ++++++++++++

How can Self be a type parameter? What does 'a::<Self, 'a> even mean?

jackh726 commented 2 years ago

Not a GATs issue:

pub trait Covariant<'a> {
    type Target;
    fn unwrap<'c>(target: <Self as Covariant<'c>>::Target) -> Self where Self: Covariant<'c>;
}
error[E0284]: type annotations needed: cannot satisfy `<Self as Covariant<'c>>::Target == _`
 --> src/lib.rs:3:5
  |
3 |     fn unwrap<'c>(target: <Self as Covariant<'c>>::Target) -> Self where Self: Covariant<'c>;
  |        ^^^^^^ cannot satisfy `<Self as Covariant<'c>>::Target == _`