Access a field of "self" as mut and still be able to call a "self" method?

Is there any way to access a field of self and still be able to call a &mut self method?

pub struct StreamProcessor {
    poll: Poll,
    events: Events,
    temp: [u8; BUFF_SIZE],
}

impl StreamProcessor {
    pub fn new() -> Result<Self> {
        Ok(Self {
            poll: Poll::new()?,
            events: Events::with_capacity(128),
            temp: [0u8; BUFF_SIZE],
        })
    }

    pub fn read_request(&mut self, stream: &mut TcpStream) -> Result<Buffer> {
        self.poll.registry().register(stream, STREAM_RD, Interest::READABLE)?;
        self.read_all(stream).finally(|| {
            drop(self.poll.registry().deregister(stream));
        })
    }

    fn read_all(&mut self, stream: &mut TcpStream) -> Result<Buffer> {
        let mut buffer: Option<Buffer> = None;

        loop {
            match self.poll.poll(&mut self.events, None) {
                Ok(()) => {
                    for event in self.events.iter() {
                        match event.token() {
                            STREAM_RD => {
                                match self.handle_event_read(stream, &mut buffer) {
                                       /* ... */
                                }
                            },
                            _ => unreachable!(),
                        }
                    }
                }
                Err(err) => return Err(err),
            }
        }
    }

    fn handle_event_read(&mut self, stream: &mut TcpStream, buffer: &mut Option<Buffer>) -> Result<bool>
    {
        /* ... */
    }

    [...]
}

Error:

error[E0502]: cannot borrow `*self` as mutable because it is also borrowed as immutable
  --> src\net\processor.rs:57:39
   |
54 | for event in self.events.iter() {
   |              ------------------
   |              |
   |              immutable borrow occurs here
   |              immutable borrow later used here
...  
57 |             match self.handle_event_read(stream, &mut buffer) {
   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here

Can the code be refactored to solve this problem?

Thanks!

If handle_event_read needs to access events, then no.

Otherwise you can move the method to a free function which takes as arguments only those fields which it uses. Simplified example:

type Events = Vec<i32>;
const BUFF_SIZE : usize = 8;

pub struct StreamProcessor {
    events: Events,
    temp: [u8; BUFF_SIZE],
}

fn handle_event_read(buf : &mut [u8; BUFF_SIZE], i : i32)
{
    buf[0] = TryFrom::try_from(i).unwrap_or(0);
}

impl StreamProcessor {
    fn read_all(&mut self) {
      for event in self.events.iter() {
        // self.handle_event_read(*event); // doesn't compile
        handle_event_read(&mut self.temp, *event);
      }
    }

    fn handle_event_read(&mut self, i : i32)
    {
      self.temp[0] = TryFrom::try_from(i).unwrap_or(0);
    }
}
2 Likes

Does handle_event_read access other elements from self.events? If not you could make it a free function and pass it the required fields or refactor the required fields into a EventHandler and make it a member of StreamProcessor.

Another alternative would be to remove the processed events from self.events via while let Some(event) = self.events.pop().

Thanks!

In fact, I only need to access self.temp in the handle_event_read() method.

So yeah, I can remove &self completely and only pass self.temp as parameter explicitly :+1:


BTW: Weird, that one can't access a member field and call a member method in the same method :exploding_head:

The reason is that a function taking a &mut is a contract that it's allowed to get a mutable reference to any of the struct fields, including events. The compiler does not examine the body of a function to see which fields it does in fact access.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.