Skip to content

Instantly share code, notes, and snippets.

@mildsunrise
Last active June 3, 2025 00:32
Show Gist options
  • Save mildsunrise/0119bce13e54021a0935d06d0884124e to your computer and use it in GitHub Desktop.
Save mildsunrise/0119bce13e54021a0935d06d0884124e to your computer and use it in GitHub Desktop.
thoughts on generalizing Borrow to types (both borroweds and borrowees) that aren't fully references (https://tech.lgbt/@mildsunrise/114616125118623443)
// old trait definition:
trait OldBorrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
// new trait definition:
trait Borrow<Borrowed> {
fn borrow(self) -> Borrowed;
}
// any implementation of the old trait can be used to implement the new trait:
impl<'a, T: OldBorrow<Q>, Q: ?Sized> Borrow<&'a Q> for &'a T {
fn borrow(self) -> &'a Q {
OldBorrow::borrow(self)
}
}
// blanket impls manually adapted:
impl<'a, T: ?Sized> Borrow<&'a T> for &'a T {
fn borrow(self) -> &'a T {
self
}
}
impl<'b, 'a, T: ?Sized> Borrow<&'a T> for &'b &'a T {
fn borrow(self) -> &'a T {
self
}
}
impl<'b, 'a, T: ?Sized> Borrow<&'a T> for &'b mut &'a T {
fn borrow(self) -> &'a T {
self
}
}
// sample impl manually adapted:
impl<'a> Borrow<&'a str> for &'a String {
fn borrow(self) -> &'a str {
self.as_ref()
}
}
// new impls become possible for e.g. Option<T>:
// one where we're just borrowing the contents, and another where
// we're borrowing the option itself (and optionally the contents too,
// but the blanket impl above lets us make Q=&T)
impl<T: Borrow<Q>, Q> Borrow<Option<Q>> for Option<T> {
fn borrow(self) -> Option<Q> {
self.map(Borrow::borrow)
}
}
impl<'a, T, Q> Borrow<Option<Q>> for &'a Option<T>
where &'a T: Borrow<Q> {
fn borrow(self) -> Option<Q> {
self.as_ref().map(Borrow::borrow)
}
}
// hooray!
fn borrow(x: &Option<String>) -> Option<&str> {
x.borrow()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment