Why this code not working?

#[derive(Debug)]
struct My<'a> {
    x: &'a mut Vec<u32>,
    z: u32,
}

fn main() {
    let mut s = vec![1, 2, 3, 4];

    let mut ok = My { x: &mut s, z: 44 };

    //    let x = &ok.x[..];
    
    let mut f = vec![4, 3, 2, 1];
    ok.x = &mut f;
    s = vec![];
    //  println!("{:?}", x);
    println!("{:?}", ok);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
warning: value assigned to `s` is never read
  --> src/main.rs:16:5
   |
16 |     s = vec![];
   |     ^
   |
   = note: `#[warn(unused_assignments)]` on by default
   = help: maybe it is overwritten before being read?

error[E0506]: cannot assign to `s` because it is borrowed
  --> src/main.rs:16:5
   |
10 |     let mut ok = My { x: &mut s, z: 44 };
   |                          ------ borrow of `s` occurs here
...
16 |     s = vec![];
   |     ^ assignment to borrowed `s` occurs here
17 |     //  println!("{:?}", x);
18 |     println!("{:?}", ok);
   |                      -- borrow later used here

For more information about this error, try `rustc --explain E0506`.
warning: `playground` (bin "playground") generated 1 warning
error: could not compile `playground` due to previous error; 1 warning emitted

The lifetimes don't quite work like that. The s vector will be borrowed by ok as long as the My struct exists, even if you change the reference to point elsewhere.

Namely, the lifetime of the struct you create is like so:

let mut ok = My { x: &mut s, z: 44 };  // My<'a> where 'a is alive here...
let mut f = vec![4, 3, 2, 1];          //
ok.x = &mut f;                         // ...here...
s = vec![];                            //
//  println!("{:?}", x);               //
println!("{:?}", ok);                  // ...here...
                                       // ...and all flow points between

That lifetime doesn't change based on what you put into the struct. So the borrow of s is also 'a (you stored a &'a mut Vec<_>). That's why you can't overwrite s before the println of ok -- s is still borrowed.

You could do something like this instead:

let mut s = vec![1, 2, 3, 4];
let mut ok = My { x: &mut s, z: 44 }; // 'a
let mut f = vec![4, 3, 2, 1];         // ('a)
                                      // ___ end of 'a
let ok = My { x: &mut f, ..ok };      // New lifetime 'b
s = vec![];                           // ('b)
println!("{:?}", ok);                 // 'b
                                      // End of 'b

The new binding can have it's own independent lifetime.

Playground.

Read more about the struct update syntax.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.