Skip to content

Instantly share code, notes, and snippets.

@yescallop
Last active February 4, 2024 06:30
Show Gist options
  • Save yescallop/981915bc4b5694b110c4799e45fa5061 to your computer and use it in GitHub Desktop.
Save yescallop/981915bc4b5694b110c4799e45fa5061 to your computer and use it in GitHub Desktop.
Generic Associated Lifetime
use core::fmt;
pub trait Str {
fn concretize<'a>(self) -> &'a str
where
Self: 'a;
}
impl Str for &str {
fn concretize<'a>(self) -> &'a str
where
Self: 'a,
{
self
}
}
pub trait Storage {
type Str<'a>: Str
where
Self: 'a;
fn as_str_opaque(&self) -> Self::Str<'_>;
}
impl<'o> Storage for &'o str {
type Str<'i> = &'o str where Self: 'i;
fn as_str_opaque(&self) -> Self::Str<'_> {
self
}
}
impl Storage for String {
type Str<'a> = &'a str where Self: 'a;
fn as_str_opaque(&self) -> Self::Str<'_> {
self
}
}
pub trait StorageHelper<'i, 'o>: Storage {
fn as_str(&'i self) -> &'o str;
}
impl<'i, 'o, T: Storage + 'i> StorageHelper<'i, 'o> for T
where
T::Str<'i>: 'o,
{
fn as_str(&'i self) -> &'o str {
let s: T::Str<'i> = self.as_str_opaque();
s.concretize()
}
}
struct Container<T>(T);
impl<'i, 'o, T: StorageHelper<'i, 'o>> Container<T> {
fn as_str(&'i self) -> &'o str {
self.0.as_str()
}
}
#[allow(unused)]
fn ref_outlives_borrowed_container(s: &str) -> &str {
Container(s).as_str()
}
// fn ref_does_not_outlive_owned_container() -> &'static str {
// // error: cannot return value referencing temporary value
// Container(String::new()).as_str();
// }
// fn ref_does_not_outlive_borrowed_data() -> &'static str {
// let s = String::new();
// // error: cannot return value referencing local variable `s`
// Container(&s[..]).as_str()
// }
// `as_str` is callable on `Container<T>` where `T: Storage`.
impl<T: Storage> fmt::Display for Container<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.as_str(), f)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment