Как обойти заимствование как изменчивое после неизменного

Я прохожу этап борьбы с заимствованием проверки Rust. У меня есть этот код:

use std::collections::HashMap;

#[derive(Default)]
struct Foo<'a> {
    str_bar: HashMap<String, Bar<'a>>,
}

struct Bar<'a> {
    x: u32,
    y: Vec<&'a Fiz>,
}

struct Fiz {
    x: i32,
    y: i32,
}

impl<'a> Foo<'a> {
    pub fn new() -> Foo<'a> {
        Foo::default()
    }

    pub fn add_str_bar(&mut self, string: String, fiz: &'a Fiz) {
        self.str_bar.insert(string, Bar { x: 0, y: vec![fiz] });
    }

    pub fn read_str_bar(&mut self, string: String, fiz: &'a mut Fiz) {
        // do something...
    }
}

fn main() {
    let mut my_foo = Foo::new();
    let mut my_bar = Fiz { x: 0, y: 1 };

    // I can't change the order of this
    my_foo.add_str_bar(String::from("foobar"), &my_bar);
    my_foo.read_str_bar(String::from("fizbar"), &mut my_bar);

    println!("hello world");
}

Это не компилируется:

error[E0502]: cannot borrow `my_bar` as mutable because it is also borrowed as immutable
  --> src/main.rs:38:49
   |
37 |     my_foo.add_str_bar(String::from("foobar"), &my_bar);
   |                                                ------- immutable borrow occurs here
38 |     my_foo.read_str_bar(String::from("fizbar"), &mut my_bar);
   |            ------------                         ^^^^^^^^^^^ mutable borrow occurs here
   |            |
   |            immutable borrow later used by call

Как мне обойти это, не меняя порядок операторов?


person xilpex    schedule 09.12.2020    source источник
comment
Когда read_str_bar запускается, my_foo содержит ссылку на my_bar, поэтому невозможно передать изменяемую ссылку на my_bar где бы то ни было. Что делает read_str_bar в этом случае? Вам действительно нужно add_str_bar для хранения ссылки, а не копии my_bar?   -  person loganfsmyth    schedule 09.12.2020
comment
@loganfsmyth -- read_str_bar изменяет fiz, и мне нужно add_str_bar для хранения ссылки.   -  person xilpex    schedule 09.12.2020
comment
Тогда ваш код невозможно написать со ссылками. &mut T не может одновременно иметь никаких других ссылок любого типа. Это фундаментальная часть Правила ссылок. Я был бы очень расстроен, если бы моя неизменяемая ссылка на my_bar изменилась.   -  person Shepmaster    schedule 09.12.2020
comment
Я думаю, что на ваш вопрос ответили ответы Нужно целостное объяснение о ячейке Rust и типах с подсчетом ссылок; Ситуации, когда Cell или RefCell — лучший выбор; Когда я могу использовать Cell или RefCell, что мне выбрать?. Если нет, отредактируйте свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный.   -  person Shepmaster    schedule 09.12.2020
comment
TL; DR: вы не можете использовать ссылки, потому что ваша изменчивость/неизменяемость не очевидна во время компиляции. Предложенные дубликаты применены к вашему запросу   -  person Shepmaster    schedule 09.12.2020
comment
@Shepmaster - я думаю, ты прав. Я отдал свой близкий голос. Спасибо!   -  person xilpex    schedule 09.12.2020