Почему компилятор жалуется на заимствование поля как на неизменяемое, хотя моя функция никаким образом не обращается к этому полю?

Я пытаюсь запрограммировать приложение, которое прослушивает запросы в сокете, а затем добавляет их в очередь для обработки. Часть моего кода выглядит следующим образом:

pub struct Middleware {
    listener: TcpListener,
    queue: Vec<String>,
    servers: Vec<String>,
}

impl Middleware {
    pub fn run(&mut self) {
        for stream in self.listener.incoming() {
            let mut stream = stream.unwrap();
            let mut buffer = vec![0u8; 512];
            stream.read(&mut buffer).unwrap();
            self.queue.push(String::from_utf8(buffer).unwrap());
        }
    }
}

Тем не менее, если я попытаюсь абстрагировать часть кода в run() в функцию (буквально просто скопировать/вставить):

impl Middleware {
    pub fn run(&mut self) {
        for stream in self.listener.incoming() {
            let mut stream = stream.unwrap();
            self.handle_client(stream);
        }
    }

    fn handle_client(&mut self, mut stream: TcpStream) {
        let mut buffer = vec![0u8; 512];
        stream.read(&mut buffer).unwrap();
        self.queue.push(String::from_utf8(buffer).unwrap());
    }
}

Я получаю следующее сообщение об ошибке:

cannot borrow `*self` as mutable because `self.listener` is also borrowed as immutable
--> src/lib.rs:21:13
   |
19 |         for stream in self.listener.incoming() {
   |                       ------------- immutable borrow occurs here
20 |             let mut stream = stream.unwrap();
21 |             self.handle_client(stream);
   |             ^^^^ mutable borrow occurs here
22 |         }
   |         - immutable borrow ends here

Насколько я понимаю, self.listener.incoming() на самом деле заимствует не только "поле" слушателя, но и всю структуру. И затем, поскольку у нас не может быть изменяемого заимствования одновременно с неизменяемым заимствованием, компилятор жалуется. Тем не менее, я должен сделать self изменяемым в handle_client(), иначе я не смогу ничего добавить в его очередь.

Я думал о том, как по-другому структурировать код, чтобы решить эту проблему, но не могу найти решение, не меняя мою структуру Middleware (например, при удалении некоторых полей и т. д.).

Можно ли как-то структурировать код для использования функции (как в моем втором фрагменте кода)?


person j_beck    schedule 23.10.2017    source источник
comment
Напротив; это вынуждает вас добавлять больше абстракции.   -  person Shepmaster    schedule 24.10.2017
comment
@Shepmaster Итак, если я правильно понимаю, в вашем коде handle_client() заимствует self.queue, что не является проблемой, по сравнению с заимствованием только self, что было проблемой в моем коде (потому что это родительский объект заимствованного self.listener?)?   -  person j_beck    schedule 24.10.2017
comment
Как обсуждалось в связанных дубликатах, Rust может только сказать, что вы выполняете непересекающиеся заимствования члена структуры внутри метода single. Теперь метод run видит, что вы заимствуете self.listener и self.queue и что они не пересекаются — вызов handle_client не может изменить self.listener.   -  person Shepmaster    schedule 24.10.2017
comment
Хорошо, я думаю, я понял, спасибо большое   -  person j_beck    schedule 24.10.2017