Code to reproduce 'cannot borrow `xxx` as mutable more than once at a time'

I'm trying to reproduce the following error:


error[E0499]: cannot borrow `cli` as mutable more than once at a time
  --> src/tail.rs:79:67
   |
79 |     Ok( match read_last_n_lines(cli.args().first().unwrap(), lns, cli.get_opt("c") == Some(&OptVal::Empty)) {
   |               ----------------- ---                               ^^^ second mutable borrow occurs here
   |               |                 |
   |               |                 first mutable borrow occurs here
   |               first borrow later used by call

So I created a model example as below:

struct AB {
    a: i16,
    b: i16,
    frozen:bool,
}

impl AB {
    fn set_a(&mut self, v:i16) {
        if !self.frozen {
            self.a = v
        }
    }
    
    fn set_b(&mut self, v:i16) {
        if !self.frozen {
            self.b = v
        }
    }
    fn freeze(&mut self) {
        self.frozen = true
    }
    fn get_a(&mut self) -> i16 {
        self.freeze();
        self.a
    }
    fn get_b(&mut self) -> i16 {
        self.freeze();
        self.b
    }
}
fn sum(a1:i16,a2:i16) -> i16 {
    a1 + a2
}
fn main() {
   let mut ab = AB {a:0,b:0,frozen: false};
   ab.set_a(3);
   ab.set_b(6);
   ab.set_a(1);
   let c = ab.get_b();
   ab.set_a(3);
   println!("sum {}", c + sum(ab.get_a(), ab.get_b()))
}

However, the model has compiled and ran fine. How can I modify it to observe the error?

Does this return a reference? That could do it, I think.

If I make get_a return &i16 and adjust the signature of sum accordingly, it fails to compile.

I see, indeed:

pub fn args(&mut self) -> &Vec<String> {
        if self.unprocessed {
            self.parse()
        }
        &self.args
    }

Thanks for resolving that.

&mut has a bit misleading name, because it's used to guarantee exclusive access, but is not necessary for mutation. You can use &self and interior mutability like OnceLock

Yes, Rust offers good possibilities to solve the problem. A bad thing is that I think still like I program in other languages. So Rust solution requires a serious redesign of the codebase. Unfortunately we do not have enough resources and time now. I hope AI will take over soon, and the problem will disappear.