rust-lang / rust

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

Weird HRTB behavior with associated types #99548

Open ArtBlnd opened 2 years ago

ArtBlnd commented 2 years ago

I've trying compile this code.

// This does not compiles
fn create_baa_in_the_foo1() {
    create_baa(Foo(()));
}

// This compiles
fn create_baa_in_the_foo2() {
    Baa(Foo(()));
}

struct Baa<A>(A);
fn create_baa<A, B>(foo: A) -> Baa<A>
where
    A: for<'a> FooTrait<'a, Output = B>,
{
    Baa(foo)
}

trait FooTrait<'a> {
    type Output;
    fn output(&'a self) -> Self::Output;
}

struct Foo(());
impl<'a> FooTrait<'a> for Foo {
    type Output = &'a ();

    fn output(&'a self) -> Self::Output {
        &self.0
    }
}

Everyone knows the lifetime of the Foo(()) is general enough but it emits error.

error: implementation of `FooTrait` is not general enough
  |
2 |     create_baa(Foo(()));
  |     ^^^^^^^^^ implementation of `FooTrait` is not general enough
  |
  = note: `Foo` must implement `FooTrait<'0>`, for any lifetime `'0`...
  = note: ...but it actually implements `FooTrait<'1>`, for some specific lifetime `'1`

If we remove Output = B and its generic type B it works fine.

struct Baa<A>(A);
fn create_baa<A>(foo: A) -> Baa<A>
where
    A: for<'a> FooTrait<'a>,
{
    Baa(foo)
}

or in other way, moving references associate type to method signature. it also works.

trait FooTrait<'a> {
    type Output;
    fn output(&'a self) -> &'a Self::Output;
}

struct Foo(());
impl<'a> FooTrait<'a> for Foo {
    type Output = ();

    fn output(&'a self) -> &'a Self::Output {
        &self.0
    }
}

I guess at least this code should have same lifetime behavior as first one. Am I doing wrong with something or this is something the bug related to https://github.com/rust-lang/rust/issues/70263?

ArtBlnd commented 2 years ago

I think its because there is no way to proof (or very hard way using dyn and HRTB) generic type B has HRTB lifetime 'a current rust implementation.