RPITIT is allowed to name any in-scope lifetime parameter, unlike inherent RPIT methods · Issue #112194 · rust-lang/rust (original) (raw)

I noticed (while responding to this comment by @aliemjay) that there's an inconsistency in how we handle returning Self if it captures lifetimes. For both inherent methods and RPITIT, if you write -> impl Trait and then return self on an impl for a type that containing a lifetime, we give you an error:

struct Foo<'a>(&'a str);

// ERROR: hidden type for impl Sized captures lifetime that does not appear in bounds impl<'a> Foo<'a> { fn foo(self) -> impl Sized { self } }

trait Trait<'a> { fn bar(self) -> impl Sized; }

// ERROR: hidden type for impl Sized captures lifetime that does not appear in bounds impl<'a> Trait<'a> for &'a i32 { fn bar(self) -> impl Sized { self } }

However, if you write -> Self on an implementation of a trait method that's written with -> impl Trait, there is no error (though this would require #[refine] with RFC 3245):

// OK? impl<'a> Trait<'a> for &'a u32 { fn bar(self) -> Self { self } }

playground

First, this inconsistency is weird from a user perspective because it seems like the capture rules say what lifetimes your hidden type is allowed to reference, and such a property can only be strengthened by an implementation (by referencing fewer, or longer-lived, lifetimes than the trait allows), never weakened. But here, the implementation specifies it a concrete type which allows it to name additional lifetimes.

If we could I we would say we should probably accept all of these examples and consider Self to be a type parameter in how we interpret RFC 1951. That said, I don't think it's possible to change today given that you can depend on the return type not referencing the lifetime.

Given that, we should probably apply the same restriction to RPITIT for the sake of consistency and not allow it to name any lifetime parameters as we assume it can today (including through Self). Though this might create other issues I'm not thinking of.

cc @compiler-errors