0

I want to keep binary data in Struct(e.g., aout) and refer it partially using Slice(e.g., data)

In the followings, I created a slice in test2 method and it might be succeeded. However, as show in the next block, I cannot invoke t.test3()

I don't understand what it happens and how to realize my purpose (I am not sure it can be or not). The one thing that I know this reason is lifetime parameter('a). But I think it is necessary because I have a slice inside a structure (e.g., Test)

struct Test<'a> {
    test: String,
    aout: Vec<u8>,
    data: &'a [u8],
}

impl<'a> Test<'a> {

    fn test2(&'a mut self) {
        self.data = &self.aout[0..3]; // make a slice there
        println!("test2");        
    }

    fn test3(&self) {
        println!("test3");
    }

}


fn main() {
    println!("hoge123");

    let mut t = Test{
        test: String::from("abc"),
        aout: vec![1,2,3,4,5],
        data: &[],
    };    
    t.test2();
    t.test3(); // **--> compile error**
}
error[E0502]: cannot borrow `t` as immutable because it is also borrowed as mutable
  --> examples/1.rs:31:5
   |
30 |     t.test2();
   |     --------- mutable borrow occurs here
31 |     t.test3();
   |     ^^^^^^^^^
   |     |
   |     immutable borrow occurs here
   |     mutable borrow later used here

For more information about this error, try `rustc --explain E0502`.

When I remove lifetime parameter and slice, we can invoke:

t.test2();
t.test3();

So, the reason is lifetime but I don't know why.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Hiro
  • 1
  • 1
  • 1
    `&'a mut self` (when `'a` is a lifetime of the struct) is (almost?) always wrong. You cannot use the struct more than once. – Chayim Friedman Aug 23 '23 at 12:32
  • ...and a sign of a self-referential struct. – Chayim Friedman Aug 23 '23 at 12:33
  • @ChayimFriedman Thanks for your comments. Now I may understand why `&a mut self` can be invoked only once. Because `'a` can be applied to `'static`, meaning that once we invoke this method, the instance keep existing until the application ends. Is it what you want to say? – Hiro Aug 24 '23 at 06:42
  • No, this is not the reason. The reason is that since `'a` is the lifetime in the struct, it is equivalent to the whole lifetime of the struct. So when you take `&'a mut self` you're saying "I'm borrow this value for the rest of its life". But practically, all you need to know is that `&'a mut self` is wrong, and if you've found yourself using it, you need to reconsider your stance. Also, that self-referential structs are wrong. – Chayim Friedman Aug 24 '23 at 07:36
  • @ChayimFriedman thanks again. Practically, I understand "&'a mut self" is wrong. Now my curious is WHY? IMHO, what you say "I'm borrow this value for the rest of its life" represents `&'a mut self` because &'a might be `&'static mut self` -> meaning that we may borrow this value until the application ends. Therefore lifetime checker needs to check this possibility, generating above errors. Am I wrong? – Hiro Aug 24 '23 at 08:09
  • Yes, you are wrong. `'a` is not `'static`, and it will only be `'static` if it can be. It errors for the reason I explained above. – Chayim Friedman Aug 24 '23 at 08:28
  • @ChayimFriedman Now I may understand. You mean, once we use `&'a mut self` its lifetime is the same as Struct, meaning that whenever the instance of struct exists, we keep borrowing once we invoke a method with `&a mut self` right?? Sorry for multiple questions... Thanks in advance. – Hiro Aug 24 '23 at 09:02
  • Yes. Once you invoke a method with `&'a mut self`, you're borrowing the struct forever. – Chayim Friedman Aug 24 '23 at 09:11
  • @ChayimFriedman I got it. Extremely thanks! – Hiro Aug 24 '23 at 09:19

0 Answers0