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.