I hit this problem a few years ago and was able to workaround it (as shown below) but was never satisfied with the approach. I'd like to know if this can be achieved without a custom ToStatic
trait?
The general idea is a tree of nested structs which typically borrow data but with the ability to ToOwned
the entire tree when required. Minimal example below, hopefully I haven't over simplified it.
Given:
#[derive(Debug)]
pub struct Foo<'a> {
name: Cow<'a, str>,
}
// We need a `T: 'static` here
fn bar<T: Debug + 'static>(foo: T) {
dbg!(foo);
}
How can we create a Foo
which we can move into bar()
?
fn main() {
let name = String::from("inner");
let foo = Foo { name: Cow::from(&name) };
// TODO invoke bar(..)
}
Attempting to use ToOwned
:
impl ToOwned for Foo<'static> {
type Owned = Foo<'static>;
fn to_owned(&self) -> Self::Owned {
Foo { name: Cow::Owned(self.name.clone().into_owned()) }
}
}
fn main() {
let name = String::from("inner");
let foo = Foo { name: Cow::from(&name) };
bar(foo.to_owned());
}
Fails (Rust Playground) with:
error[E0597]: `name` does not live long enough
--> src/main.rs:39:37
|
39 | let foo = Foo { name: Cow::from(&name) };
| ----------^^^^^-
| | |
| | borrowed value does not live long enough
| argument requires that `name` is borrowed for `'static`
40 | bar(foo.to_owned());
41 | }
| - `name` dropped here while still borrowed
However, it can be made to work (Rust Playground) if we use a custom trait where the associated type is Static: 'static
and a blanket impl for Cow
:
pub trait ToStatic {
type Static: 'static;
fn to_static(&self) -> Self::Static;
}
impl<T> ToStatic for Cow<'_, T>
where
T: 'static + ToOwned + ?Sized,
{
type Static = Cow<'static, T>;
fn to_static(&self) -> Self::Static {
Cow::Owned(self.clone().into_owned())
}
}
impl ToStatic for Foo<'_> {
type Static = Foo<'static>;
fn to_static(&self) -> Self::Static {
Foo { name: self.name.to_static() }
}
}
fn main() {
let name = String::from("inner");
let foo = Foo { name: Cow::from(&name) };
bar(foo.to_static());
}
Can this be achieved with ToOwned
? Can we express the : 'static
bound when declaring the the Owned = Foo<'static>
associated type in the ToOwned
impl?