You context is unclear to me. You can't safely go from a Bar<'a> to a &'a Foo though; it could be pointing to different Foo fields or things that are part of no Foo. You can go the other way.
You generally can't because A and Foo-when-variant-A may have different layouts; if you used explicit representations so you know the layouts, then &A would still be missing the discriminant as all explicit enum layouts don't use implicit discriminants.
In a generic context, it wouldn't need the layout to be the same.
I think the Borrow trait is flawed. HashSet<String> can use Borrow to look up by &str, but HashSet<(String, String)> can't be looked up by (&str, &str).
trait BetterBorrowConstructor {
type Bbc<'a, T: ?Sized> where T: 'a;
}
trait BetterBorrow<T: ?Sized, B: BetterBorrowConstructor> {
fn better_borrow(&self) -> B::Bbc<'_, T>;
}
struct Reference;
impl BetterBorrowConstructor for Reference {
type Bbc<'a, T: ?Sized> = &'a T where T: 'a;
}
impl<T: ?Sized, U: ?Sized> BetterBorrow<T, Reference> for U where U: Borrow<T> {
fn better_borrow(&self) -> &T { self.borrow() }
}
But this clearly isn't a drop-in replacement, and there are some rough edges around where GAT is at (probably some HRTB restrictions, isn't trait object safe, etc). Maybe also because Bbc can't name a restriction based on the implementor of BetterBorrow without even more hoops (where Self: 'a is the wrong bound for the example).
(Might also be the wrong shape for other reasons like variadic generics? Haven't spent a ton of time thinking about it.)
For the associated type flavor, there's either a long way to go to support some ?GAT thing that's also trait object safe somehow, or you define a different trait.
trait CanonicalBorrow {
type Canon;
fn c_borrow(&self) -> &Self::Canon;
}
trait BetterCanonicalBorrow {
type Canon<'a> where Self: 'a;
fn c_borrow(&self) -> Self::Canon<'_>;
}
// Depending on the use case, this might not be desired...
// (Breaking change for existing CanonicalBorrow implementors
// to migrate to something better)
impl<T: CanonicalBorrow> BetterCanonicalBorrow for T {
type Canon<'a> = &'a <Self as CanonicalBorrow>::Canon where Self: 'a;
fn c_borrow(&self) -> Self::Canon<'_> {
<Self as CanonicalBorrow>::c_borrow(self)
}
}
It’s a bit like String vs &str / &Vec<T> vs &[T]. And it’s a bit like &Option<T> vs Option<&T>.
I think, having a type like Bar<'_> can be a good idea; I don’t know of a name for this concept. Maybe call Bar<'_> something like FooRef<'_>, and give Foo an as_ref(&self) -> FooRef<'_> method (method name inspired by Option’s method.