Difference between `&self` and `&'a self` in `impl<'a>`

⚓ Rust    📅 2025-04-30    👤 surdeus    👁️ 5      

surdeus

Warning

This post was published 113 days ago. The information described in this article may have changed.

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:

  1. My guess is the explicit version of ss.foo() would be the following.
    fn foo<'b>(&'b self) -> &'a [u8] where 'a:'b
  1. The "lifetime" of ss in fn split is also required to be shorter than (fully spanned by) lifetime of both ss.raw and return value of ss.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

3 posts - 2 participants

Read full topic

🏷️ rust_feed