Struggling with multiple mutable borrows

⚓ Rust    📅 2025-07-19    👤 surdeus    👁️ 13      

surdeus

Warning

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

Can you please teach me what would be the correct, "Rust way" to achieve what I am trying to do?

My expectation is that:

  • I call a.find_foo_identifier
  • find_foo_identifier returns &str, and I expect this reference to be directly copied from the foo array, from the borrowed value from inside the Vec, which I got from iter() - in fact, I have this map call in which I do the dereference all the way down to &str.
  • And because of this copy, I expect that this should release a from being borrowed, because the data is copied from it.
  • And then I call push_foo., mutate a, all clean
  • And then I call push_bar , mutate a again, all good clean

What instead happens:

  • push_foo requires mutable borrow
  • push_bar requires mutable borrow
  • compiler doesn't allow me to have them at the same time
  • and find_foo_identifier does an immutable borrow, and it's not compatible with either of the mutable borrows.

It's as if everything is just in a permanent borrowed state, shouldn't it be, like, released after the reference is done being used?

I am observing an error at a.push_foo("very good");. It says: "cannot borrow a as mutable because it is also borrowed as immutable"

Question: how can I achieve what I'm trying to do in the proper Rust way, so that the borrow checker is satisfied?

Code in question:

struct A<'a> {
    foo: Vec<&'a str>,
    bar: Vec<&'a str>,
}

impl<'a> A<'a> {
    pub fn find_foo_identifier(&self, identifier: &str) -> Option<&str> {
        self.foo.iter()
            .find(|local_node| **local_node == identifier)
            .map(|s|*s)
    }
    fn push_foo(&mut self, s: &'a str) {
        self.foo.push(s);
    }
    fn push_bar(&mut self, s: &'a str) {
        self.bar.push(s);
    }
}

fn build_a<'a>() -> A<'a> {
    let mut a = A { foo: vec![], bar: vec![] };

    for _ in 0..20 {
        let found = a.find_foo_identifier("asdf");

        if let Some(s) = found {
            a.push_foo("very good");
            a.push_bar(s);
        }
    }

    a
}

3 posts - 3 participants

Read full topic

🏷️ rust_feed