Borrowing reference in structure

杀马特。学长 韩版系。学妹 提交于 2020-01-13 13:05:36

问题


I'm trying to put in one structure information about inotify events and hashmap with inotify watch id as key and name of the file as value.

extern crate inotify;
use inotify::INotify;
use std::sync::{Arc, Mutex};
use std::collections::HashMap;

struct Notificator {
    inotify: INotify,
    watch_service: Arc<Mutex<HashMap<inotify::wrapper::Watch, Arc<String>>>>,
}

impl Notificator {
    pub fn new() -> Notificator {
        Notificator {
            inotify: INotify::init().unwrap(),
            watch_service: Arc::new(Mutex::new(HashMap::new())),
        }
    }

    pub fn resolving_events(&mut self) {
        {
            let mut events = self.check_for_events();
            self.events_execution(events);
        }

    }

    fn check_for_events(&mut self) -> &[inotify::wrapper::Event] {
        self.inotify.available_events().unwrap()
    }

    fn events_execution(&self, events: &[inotify::wrapper::Event]) {
        for event in events.iter() {

        }
    }
}

During compilation I am receiving an error

src/main.rs:204:13: 204:17 error: cannot borrow `*self` as immutable because it is also borrowed as mutable [E0502]
src/main.rs:204             self.events_execution(events);

I thought the best solution would be to separate somehow inotify variable in Notificator structure with watch_service, but I can't dereference self.check_for_events(); because I receive

src/main.rs:203:17: 203:27 error: the trait bound `[inotify::wrapper::Event]: std::marker::Sized` is not satisfied [E0277]
src/main.rs:203             let mut events = *self.check_for_events();

I understand the core of the problem: I'm trying to borrow reference by check_for_events and then using it as parameter in events_execution which also requires self as parameter, but I have no idea how to resolve it.


回答1:


One thing you could do, although it's not very elegant, is to have your mutable method consume its mutable borrow and return an immutable one that you can then use:

pub fn resolving_events(&mut self) {
    let (slf, events) = self.check_for_events();
    slf.events_execution(events);

}

fn check_for_events(&mut self) -> (&Self, &[inotify::wrapper::Event]) {
    let events = self.inotify.available_events().unwrap();
    (&self, events)
}

I've made a small proof-of-concept on the playground (using vecs of u64 as the mutable state, but the principle is similar). It might be cleaner to refactor your code so that some external client can (mutably) borrow the Notifier, produce the events, release the borrow, and borrow it (immutably) to process them...




回答2:


This is a known issue in the borrow checker (more discussion on internals). You cannot have a function taking a &mut T to an object and returning a &T without losing the ability to access the object again until the &T goes out of scope. You can't work around it due to the way inotify is implemented.

But you can ask the inotify authors to create a get_available_notifications method that doesn't fetch new data. This way you can call available_notifications once and drop the returned value. Then call get_available_notifications (which doesn't take &mut INotify, but just &INotify) and work from there.



来源:https://stackoverflow.com/questions/38078936/borrowing-reference-in-structure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!