Background
tl;dr This started out as a resource-references-resource solution and evolved into a more general Cow
.
One of the libraries I maintain defines a hierarchy of resources; e.g., a top-level Environment
type, and a Database<'a>
type that notionally contains an &'a Environment
, etc. This works great until you want to ship the two around together in a struct
such as
struct Resources {
env: Environment,
db: Database<'?>, // Needs to reference `env`
}
Since this isn't legal, one currently has to resort to using unsafe code (by hand, or like owning_ref) or contorting the program to hold everything on the stack.
But I also didn't want to force Arc
on everyone since it makes it harder to statically reason about the actual lifetimes of values.
So I essentially started with something like
enum Reflike<'a, T> {
Owned(T),
Borrowed(&'a T),
Shared(Arc<T>),
}
and then extended it to be generic over shared reference types (eg, Arc
vs Rc
), to handle Borrow
similarly to Cow
and eventually ended up with this very general thing below.
The crate in question
Essentially, this gives you a type Supercow<'a, T>
that is mostly usable as &'a T
and has similar features as Cow<'a,T>
, plus the ability to work with Arc
and friends, and Into
conversions from bare owned/borrowed/shared values. By default it is only a pointer wider than a normal reference.
In the case of the library above, the struct
issue is solved by the client code choosing to use Arc
s instead, resulting in, e.g.,
struct Resources {
env: Arc<Enviornment>,
db: Database<'static>, // Holds its own `Arc<Environment>` in a `Supercow`
}
while reference-based client code can continue using references.
Basically I'm hoping for feedback on a couple points before actually putting this on crates.io:
-
Does this seem generally useful? I was kind of surprised to not find anything similar already existing, but maybe I didn't look for the right thing.
-
Is it worth it? The code does a lot of.. interesting things with pointers in the name of keeping the struct small and having a fast
Deref
. It also has a number of somewhat esoteric generic parameters.