s1n7ax
s1n7ax

Reputation: 3069

cannot borrow x as mutable because it is also borrowed as immutable error

I have following code that takes the piped lines of texts and logs finger movements required to type certain characters. LogReport takes &KeyLoggers in which details are stored. LogReport later prints the details from multiple &KeyLogger as a table of content.

let keyboard = KeyboardBuilder::build(...);
let mut key_logger: KeyLogger = KeyLogger::new(keyboard);
let mut report = LogReport::new();

report.add_logger(String::from("QWERTY"), &key_logger);

loop {
  let mut input = String::new();

  match io::stdin().read_line(&mut input) {
    Ok(len) => {
      if len == 0 {
        return;
      } else {
        input.chars().for_each(|char| key_logger.log(&char));
        report.print();
      }
    }

    Err(error) => {
      eprintln!("error: {}", error);
      return;
    }
  }
}

Compile error is clear enough to understand the issue, but how to fix the issue? I guess I will have to find a solution to print the report only once the piped text is logged but issue still exist regardless.

error[E0502]: cannot borrow `key_logger` as mutable because it is also borrowed as immutable
  --> src/main.rs:25:44
   |
15 |     report.add_logger(String::from("QWERTY"), &key_logger);
   |                                               ----------- immutable borrow occurs here
...
25 |                     input.chars().for_each(|char| key_logger.log(&char));
   |                                            ^^^^^^ ---------- second borrow occurs due to use of `key_logger` in closure
   |                                            |
   |                                            mutable borrow occurs here
26 |                     report.print();
   |                     ------ immutable borrow later used here

Even if the first immutable borrows is change to mutable, compiler still complains for cannot borrow key_logger as mutable more than once at a time. What is the Rust way to handle such scenarios?

Upvotes: 0

Views: 133

Answers (1)

Alexander Brassel
Alexander Brassel

Reputation: 65

Because of Rust's ownership rules, as you've noted, you can't borrow the keylogger as immutable or mutable prior to its mutable borrow later on.

If you must have a reference to the keylogger in the LogReport prior to its use later on, you have a couple of options.

  1. You could pass ownership of the keylogger to the logreport, and borrow mutably from it.
  2. You could use interior mutability (Rc and RefCell) to have shared ownership.
  3. You could instead assign an index to each keylogger and store them somewhere, and then look up by index later on.
  4. unsafe would probably work, but is very very unnecessary.

I'd personally go for option #1.

Upvotes: 1

Related Questions