Recently I’ve been working on a library where user code gets called with borrowed references to underlying buffers. Avoiding memcpy is important in the common case, but sometimes the user will want to spawn off a thread to process the request async. The definition of Clone makes that challenging because the lifetimes are part of the cloned type, so there’s no way to define fn clone(Self<'a>) -> Self<'static>.
fn handler<'a>(req: Cow<'a, [u8]>) {
let req = req.clone();
thread::spawn(move || { /* fails, `req` still in 'a */ });
}
It seems like having a CloneTo capable of cloning to a different type (and thus different lifetime) would be useful here. There’s precedent in std::borrow::ToOwned, which exists for cross-type borrowing. The definition is straightforward:
// std::clone::CloneTo
trait CloneTo<Target> {
fn clone_to(&self) -> Target;
}
With this, I can freely clone Cow and other existentially quantified types to other lifetimes (including 'static):
impl <'from, 'to, B> CloneTo<Cow<'to, B>> for Cow<'from, B>
where B: ToOwned + ?Sized + 'to
{
fn clone_to(&self) -> Cow<'to, B> {
match *self {
Cow::Borrowed(b) => Cow::Owned(b.to_owned()),
Cow::Owned(ref o) => {
let b: &B = o.borrow();
Cow::Owned(b.to_owned())
},
}
}
}
#[derive(Debug)]
struct Foo<'a> {
s: Cow<'a, str>,
}
impl<'from, 'to> CloneTo<Foo<'to>> for Foo<'from> {
fn clone_to(&self) -> Foo<'to> {
Foo { s: self.s.clone_to() }
}
}
Does this seem useful enough to justify an RFC?