The following code can't compile. If replace ss.bar()
to ss.foo()
then it works as intended.
foo
and bar
only differs in receiver signature: &self
and &'a self
, which I initially supposed to be the same, as they are both in block of impl<'a> StrangeSplitter<'a>
.
Here comes my suppose:
- My guess is the explicit version of
ss.foo()
would be the following.
fn foo<'b>(&'b self) -> &'a [u8] where 'a:'b
- The "lifetime" of
ss
infn split
is also required to be shorter than (fully spanned by) lifetime of bothss.raw
and return value ofss.foo()
.
Are 1. and 2. right?
The origin goal was to create a struct that accepts AsRef<[u8]>+'a
and provides several slices valid even after the splitter gets dropped. In another word, a struct that owns, process and return references with lifetime beyond (lives longer than) the struct itself.
Any suggestion on better practice would be appreciated.
Test code: (Playground link here)
struct StrangeSplitter<'a> {
raw: &'a [u8],
}
impl<'a> StrangeSplitter<'a> {
fn foo(&self) -> &'a [u8] {
&self.raw[0..1]
}
fn bar(&'a self) -> &'a [u8] {
&self.raw[0..1]
}
}
fn split<'a>(raw: &'a [u8]) -> &'a [u8] {
let ss: StrangeSplitter<'a> = StrangeSplitter { raw };
// let a: &'a [u8] = ss.foo(); //This is okay
let a: &'a [u8] = ss.bar();
return a;
}
fn main() {
let raw: Vec<u8> = (0..8).collect();
let _ = split(&raw);
}
Compiler output:
error[E0597]: `ss` does not live long enough
--> src/main.rs:17:23
|
14 | fn split<'a>(raw: &'a [u8]) -> &'a [u8] {
| -- lifetime `'a` defined here
15 | let ss: StrangeSplitter<'a> = StrangeSplitter { raw };
| -- binding `ss` declared here
16 | // let a: &'a [u8] = ss.foo(); //This is okay
17 | let a: &'a [u8] = ss.bar();
| -------- ^^ borrowed value does not live long enough
| |
| type annotation requires that `ss` is borrowed for `'a`
18 | return a;
19 | }
| - `ss` dropped here while still borrowed