Possible compiler bug with Lifetimes and Traits

The code is this:

fn main() {
    <S as From<&i32>>::from(&5);
}

struct S;

impl<'a, T> From<&'a T> for S
where
    for<'b> &'b T: IntoRef,
    for<'b> Self: From<<&'b T as IntoRef>::Ref>,
{
    fn from(value: &'a T) -> Self {
        <Self as From<<&T as IntoRef>::Ref>>::from(value.into_ref())
    }
}

impl<'a> From<<&'a i32 as IntoRef>::Ref> for S {
    fn from(value: <&'a i32 as IntoRef>::Ref) -> Self {
        todo!()
    }
}

trait IntoRef {
    type Ref;
    fn into_ref(self) -> Self::Ref;
}

impl<'a> IntoRef for &'a i32 {
    type Ref = IRef<'a>;
    fn into_ref(self) -> Self::Ref {
        IRef(self)
    }
}

struct IRef<'a>(&'a i32)

Playground.

Maybe I completely misunderstand HRTBs, but I am pretty sure that this code is valid and should compile, correct me if I'm wrong.

Obligatory note: In this case you don't need HRTB, you can just use the same 'a throughout.

impl<'a, T> From<&'a T> for S
where
    &'a T: IntoRef,
    Self: From<<&'a T as IntoRef>::Ref>,
{
    fn from(value: &'a T) -> Self {
        <Self as From<<&T as IntoRef>::Ref>>::from(value.into_ref())
    }
}

But that still leaves the question on why the original code didn't compile: I think this may just be a limitation of the trait system.

1 Like

The compiler sometimes can't prove a universal proposition ("for all 'a, P<'a>") even when it could prove any specific instance of the proposition (e.g. P<'static>). I think this is one of those times.

It's not exactly a bug per se, because there will always be things the compiler cannot prove, but it is a current limitation and it could be fixed in theory. Maybe with Chalk?

2 Likes