My thinking is that the 'b lifetime needs to outlive the 'a lifetime that's exposed on the struct. So why does 'b need to be part of the struct's parameters (essentially part of its public interface). I can't use the same lifetime parameter because of Borrowing something forever - Learning Rust, not to mention they aren't the same lifetime, one just bounds the other.
These lifetimes have to exist and be tracked for correctness.
In theory, Rust could add more lifetime elision rules to the syntax to make the 'b not necessary to write out explicitly, but that could make the struct unusable wherever you actually needed to refer to that lifetime, or require more lifetime elision rules elsewhere.
Not directly. You may be able to type-erase the inner lifetime with dyn Trait if it's possible to define the necessary functionality in terms of a trait, and use &'a dyn Trait. You could use a type parameter (in place of one lifetime, or both), technically (but I'm pretty sure you wouldn't be any happier).
Note that the type system isn't just about public API, but is integral to how the compiler works (e.g. borrow-checks). It would be unsound for two different 'bs to result in the same type. Even with covariance it's unsound to extend the inner lifetime.[1] So some hypothetical OuterRefMut<'a> with a hidden 'b would still need the 'b to be part of it's type.
If consumer of your type couldn't tell or dictate that two different OuterRefMut<'a> were really the same type,[2] that would make for a horrible/unworkable coding experience.
What's your XY for wanting to get rid of the second lifetime parameter? Anything beyond aesthetics?
but due to the covariance, &'a InnerRef<'a> can often work when &'a mut InnerRefMut<'a> cannot ↩︎
But the inner abstraction removes that flexibility.
What's your XY for wanting to get rid of the second lifetime parameter? Anything beyond aesthetics?
First-order reason, I guess you could call it aesthetics, however, without getting too philosophical, aesthetics are the integration of lots of observations and experiences. They're a heuristic shortcut for what's likely to work and what probably isn't.
So yeah... Every additional lifetime parameter (especially in a trait) is a sharp edge that I'm likely to cut myself on in the future.
Every additional lifetime parameter ... is a sharp edge that I'm likely to cut myself on in the future.
In this case, the future was only a couple hours away. In this case I have a trait that does not have any lifetime parameters, but there is a method to return an OuterRefMut
The trait needs to be implemented on an InnerRefMut and the OuterRefMut can't outlive the mutable borrow of the InnerRefMut. So this would be easily done on an ordinary impl on InnerRefMut, e.g.