Reputation: 1318
I have a struct that wraps some functionality around a slice:
use std::fmt::Debug;
struct SliceWrapper<'a, T: Debug + Copy + 'a> {
slice: &'a [T],
pos: usize,
}
I want to implement the From
trait for each element that supports AsRef<T: Debug + Copy + 'a>
like this:
impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
fn from(slice: R) -> Self {
Self {
slice: slice.as_ref(),
pos: 0,
}
}
}
I get the error:
error[E0597]: `slice` does not live long enough
--> src/lib.rs:11:20
|
11 | slice: slice.as_ref(),
| ^^^^^ borrowed value does not live long enough
...
14 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 8:6...
--> src/lib.rs:8:6
|
8 | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
| ^^
I don't understand this because I say that R
(slice
) must live as long as my SliceWrapper
– and as far as I understand it, AsRef<_>
inherits the lifetime from it's self
(slice
)...
Upvotes: 2
Views: 670
Reputation: 13772
You can restrict the conversion to reference arguments, and then you have a nice way to express the borrowing you need — lifetime is taken from the input reference:
impl<'a, T, R> From<&'a R> for SliceWrapper<'a, T>
where
T: Debug + Copy + 'a,
R: AsRef<[T]>
{
fn from(slice: &'a R) -> Self {
Self {
slice: slice.as_ref(),
pos: 0,
}
}
}
Now you can follow your original reasoning.
You have AsRef giving you: &'x self -> &'x [T]
for any 'x
and you input a &'a R
into that, so you get a&'a [T]
out.
Reference taking From
sometimes exist, I think it's especially appropriate in reference-to-reference-like conversions. An example in std is impl<'a> From<&'a str> for Cow<'a, str>
Upvotes: 2
Reputation: 602115
The full error message on nightly states quite clearly what's happening here. You move slice
into the function from()
, then borrow it using as_ref()
, and then it gets dropped at the end of the scope:
8 | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
| -- lifetime `'a` defined here
9 | fn from(slice: R) -> Self {
10 | Self{ slice: slice.as_ref(), pos: 0 }
| ^^^^^---------
| |
| borrowed value does not live long enough
| argument requires that `slice` is borrowed for `'a`
11 | }
| - `slice` dropped here while still borrowed
You are trying to create a borrow that lives for the lifetime 'a
, but the owner you are borrowing from, slice
, does not live long enough.
The From
trait does not seem to be a good fit for this use case. The idea of that trait is to move ownership of some data to a new type, but your SliceWrapper
does not take ownership. I suggest writing a custom constructor instead that takes R
by reference.
Upvotes: 3