[Pre-RFC?] Allowing custom owned types in Cow


#1

Currently, Cow is usable only with predefined ToOwned relationship, so you can’t put custom types or even boxed slices like Box<[T]> instead of Vec or String for the owned side of &[T].

This is possible to workaround with custom newtype wrappers for the borrowed variant or custom enum instead of Cow, but it doesn’t seem that this limitation is necessary in the first place?

So what I’m thinking is changing Cow from current

pub enum Cow<'a, B>
where
    B: 'a + ToOwned + ?Sized,
{
    Borrowed(&'a B),
    Owned(<B as ToOwned>::Owned),
}

to something like

pub enum Cow<'a, B, O = <B as ToOwned>::Owned>
where
    B: 'a + ?Sized,
    O: Borrow<B>,
{
    Borrowed(&'a B),
    Owned(O),
}

This would still preserve backwards compatibility with existing Cow definition by defaulting to ToOwned version of the owned type if it’s not explicitly provided, but allow to provide your own as long as it can be borrowed as the B type.

This wouldn’t allow doing Cow::into_owned / ::into_mut with custom type - you’ll need to convert types yourself if you do this (or maybe we can rely on From conversions?), but in my experience there is a lot of cases where Cow is still useful as purely an optimised storage and conversions to owned don’t matter that much to be a problem then.

Does this look useful? Are there any other problems that would make this infeasible?


#2

Personally, I just defined an Oob type where you specify the owned type instead. It was previously called Moo, but I couldn’t think of a plausible backronym for it.

pub enum Oob<'a, O>
where
    O: Deref,
    O::Target: 'a,
{
    Owned(O),
    Borrowed(&'a O::Target),
}

That also lets you go from borrowed to owned, provided O: From<&'a B> is satisfied. Works well enough for Oob<'static, Box<str>> (we hates the useless capacity field, my precious).


#3

Yes, as I mentioned in the topic, defining own enum is an option, but it did make me wonder whenever I had to use it, whether allowing two different types could be just part of standard Cow interface given how similar and common this is.