pub trait Borrow {
type Target<'a>
where Self: 'a;
// Required method
fn borrow(&self) -> Self::Target<'_>;
}
Expand description
Borrow from self.
This works similarly to Borrow
but allows
borrowing compoundly from &self
by defining a generic Target
. This
means it’s not just limited to returning an immediate reference to the
borrowed value but can return something which receives lifetime parameters
that borrows from self. This is called “compound borrowing” because it lets
you return types which contains compound references.
It is recommended that you use borrow
instead of
importing this trait.
What about std::borrow::Borrow
?
The Borrow
trait as defined can’t perform
compound borrows from &self
. Because the borrow
method immediately
returns a reference to the borrowed type.
trait Borrow<Borrowed: ?Sized> {
fn borrow(&self) -> &Borrowed;
}
This means that there is no way to implement something like
Borrow<Word<'a>>
because it’s required that we return a reference which
doesn’t outlive 'a
, something that can’t be satisfied from the call to
&self
.
struct Word<'a>(&'a str);
struct OwnedWord(String);
impl<'a> Borrow<Word<'a>> for OwnedWord {
fn borrow(&self) -> &Word<'a> {
&Word(self.0.as_str())
}
}
error[E0515]: cannot return reference to temporary value
--> src/borrow.rs:37:9
|
9 | &Word(self.0.as_str())
| ^---------------------
| ||
| |temporary value created here
| returns a reference to data owned by the current function
The solution implemented in this crate is to use a generic Target
, with
which we can implement borrow
like this:
use borrowme::Borrow;
impl Borrow for OwnedWord {
type Target<'a> = Word<'a>;
fn borrow(&self) -> Self::Target<'_> {
Word(self.0.as_str())
}
}
A catch here is that Borrow
can only be implemented once for each time,
compared to Borrow<T>
. But for our purposes this
is fine. This crate is primarily intended to work with two symmetrical types
and any deviation from that pattern can be handled by customizing the
behavior of the #[borrowme]
attribute.