I am trying to create an alternative version of the Borrow
trait that could be used to obtain a smart reference concrete type. Something like the following:
pub trait Borrow<Borrowed>
where
Borrowed: ?Sized,
{
fn borrow(&self) -> Borrowed;
}
However, this code has a huge downside: the generic Borrowed
object is not bound to the lifetime of Self
. I tried different approaches, trying to have a lifetime in the trait definition, as a HRTB and as a function generic parameter, but I did not success to express my intent. To be honest, given that most of the time people ask for help because code does not compile, it is pretty strange to ask how can I make it not compile
In any case: here a playground with a not working code and two helpful doctests to check if the goal is reached.
EDIT: updated playground, mis-copy-pasted.
If you are asking "why????", my idea is pretty simple and practical: it happens to use serde in order to deserialize data using borrowing structs, something like this:
#[derive(Deserialize, Serialize)]
struct A<'a> {
param1: &'a str,
param2: &'a str,
#[serde(borrowed)]
child: B<'a>,
}
#[derive(Deserialize, Serialize)]
struct B<'a> {
param1: &'a str,
param2: &'a str,
}
If you need a JSON response just to save some data to a DB, for instance, allocating Strings
all around is just a waste of resources.
However, you often reach the point you need the owning version of your structures. AFAIK, at today you need to copy-paste everything and replace all the references with owning version of your data. I think it would be great to create a derive-macro to automatize this boilerplate process, but a trait is necessary in order to allow the parent struct to get the owned version of the child one, and ToOwned
cannot be used.
If I am correct, the Borrow
trait I am trying to implement should be 100% compatible with the one in std::borrow
, because a reference to a generic type is a subset of a generic type, if this obviously has a correct lifetime bound.