Mutable borrow twice in loop/match

I try to write simple decoder, that reads bytes into an internal buffer when needed.

use std::io::{Error, Read};

struct DecodeError;

enum FillError {
    Overflow,
    Io(Error),
}

struct Decoder {
    buffer: Vec<u8>,
    read: usize,
    write: usize,
}

impl Decoder {
    fn decode<'a>(&'a mut self) -> Result<&'a [u8], DecodeError> {
        if self.write - self.read > 0 {
            let last = self.read;
            self.read = self.write;
            Ok(&self.buffer[last..self.write])
        } else {
            Err(DecodeError)
        }
    }

    fn fill<R: Read>(&mut self, reader: &mut R) -> Result<usize, FillError> {
        if self.write == self.buffer.len() {
            // Shift data
            if self.read > 0 {
                self.buffer.copy_within(self.read..self.write, 0);
                self.write -= self.read;
                self.read = 0;
            } else {
                return Err(FillError::Overflow);
            }
        }
        let n = reader
            .read(&mut self.buffer[self.write..])
            .map_err(FillError::Io)?;
        self.write += n;
        Ok(n)
    }

    pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
        loop {
            match self.decode() {
                Ok(data) => {
                    return Ok(data);
                }
                Err(_) => {
                    self.fill(reader)?;
                }
            }
        }
    }
}

playground

Compiler warns me about errors, but I don't understand what's wrong:

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/lib.rs:47:19
   |
45 |     pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
   |                 -- lifetime `'a` defined here
46 |         loop {
47 |             match self.decode() {
   |                   ^^^^^^^^^^^^^ `*self` was mutably borrowed here in the previous iteration of the loop
48 |                 Ok(data) => {
49 |                     return Ok(data);
   |                            -------- returning this value requires that `*self` is borrowed for `'a`

error[E0499]: cannot borrow `*self` as mutable more than once at a time
  --> src/lib.rs:52:21
   |
45 |     pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
   |                 -- lifetime `'a` defined here
46 |         loop {
47 |             match self.decode() {
   |                   ------------- first mutable borrow occurs here
48 |                 Ok(data) => {
49 |                     return Ok(data);
   |                            -------- returning this value requires that `*self` is borrowed for `'a`
...
52 |                     self.fill(reader)?;
   |                     ^^^^^^^^^^^^^^^^^ second mutable borrow occurs here

I guess the first borrowing ended here - Err(_) => {...},
but compiler does not.

That’s the typical problem case that GitHub - rust-lang/polonius: Defines the Rust borrow checker. will eventually fix, i.e. it’s a limitation of the current borrow checker.

3 Likes

Is it possible on stable compiler to solve this without using unsafe?

    pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
        while self.decode().is_err() {
            self.fill(reader)?;
        }
        Ok(self.decode().expect("Decode should be successful."))
    }

playground

That's not quite right yet: the expect will always fail because the first decode() advances the internal read head to the end.

You could use polonius-the-crab:

/*
[dependencies]
polonius-the-crab = "0.3.0"
*/

use polonius_the_crab::prelude::*;

use std::io::{Error, Read};

struct DecodeError;

enum FillError {
    Overflow,
    Io(Error),
}

struct Decoder {
    buffer: Vec<u8>,
    read: usize,
    write: usize,
}

impl Decoder {
    fn decode<'a>(&'a mut self) -> Result<&'a [u8], DecodeError> {
        if self.write - self.read > 0 {
            let last = self.read;
            self.read = self.write;
            Ok(&self.buffer[last..self.write])
        } else {
            Err(DecodeError)
        }
    }

    fn fill<R: Read>(&mut self, reader: &mut R) -> Result<usize, FillError> {
        if self.write == self.buffer.len() {
            // Shift data
            if self.read > 0 {
                self.buffer.copy_within(self.read..self.write, 0);
                self.write -= self.read;
                self.read = 0;
            } else {
                return Err(FillError::Overflow);
            }
        }
        let n = reader
            .read(&mut self.buffer[self.write..])
            .map_err(FillError::Io)?;
        self.write += n;
        Ok(n)
    }

    pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
        let mut this = self;
        loop {
            polonius! {
                |this| -> Result<&'polonius [u8], FillError> {
                    match this.decode() {
                        Ok(data) => polonius_return!(Ok(data)),
                        Err(_) => (),
                    }
                }
            }
            this.fill(reader)?;
        }
    }
}

Rust Explorer

2 Likes

Thank you for pointing that out.

If decode returns a non-referenced type, things go well.

playground

    fn decode(&mut self) -> Result<usize, DecodeError> {
        if self.write - self.read > 0 {
            Ok(std::mem::replace(&mut self.read, self.write))
        } else {
            Err(DecodeError)
        }
    }

    fn decoded(&self, last: usize) -> &[u8] { &self.buffer[last..self.write] }

    pub fn next<'a, R: Read>(&'a mut self, reader: &mut R) -> Result<&'a [u8], FillError> {
        loop {
            if let Ok(last) = self.decode() {
                return Ok(self.decoded(last));
            } else {
                self.fill(reader)?;
            }
        }
    }
1 Like

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.