由于循环中可变而无法借用

Gur*_*ngh 7 rust

我有以下代码

pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
    loop {
        read_exact(buf);

        if let Some(packet) = to_packet(buf) {
            return packet;
        }
    }
}

fn read_exact(_: &mut [u8]) {
    todo!()
}

fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
    todo!()
}
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

error[E0502]: cannot borrow `*buf` as mutable because it is also borrowed as immutable
 --> src/lib.rs:3:9
  |
1 | pub fn read_packet<'a>(buf: &'a mut [u8]) -> &'a [u8] {
  |                    -- lifetime `'a` defined here
2 |     loop {
3 |         read_exact(buf);
  |         ^^^^^^^^^^^^^^^ mutable borrow occurs here
4 | 
5 |         if let Some(packet) = to_packet(buf) {
  |                                         --- immutable borrow occurs here
6 |             return packet;
  |                    ------ returning this value requires that `*buf` is borrowed for `'a`
Run Code Online (Sandbox Code Playgroud)

我认为它应该有效,因为:

  1. 可变借入read_exact在第 3 行完成。
  2. 如果to_packet返回Some,则该值将返回给调用者。
  3. 如果不是,则不可变借用to_packet在循环结束时结束。因此,在下一次迭代中可以自由地进行可变借用。

有人可以告诉我为什么这不起作用吗?

编辑:

这似乎是当前借用检查器的限制。我尝试在夜间使用 Polonius,效果很好

RUSTFLAGS=-Zpolonius cargo +nightly check
Run Code Online (Sandbox Code Playgroud)

Net*_*ave 2

这是一个编译器限制 atm。您可以重构为:

pub fn read_packet<'a>(buf: &'a mut [u8]) {
    loop {
        if read_exact(buf) {
            break;
        }
    }
}


fn is_packet(a: &[u8]) -> bool {
    true
}
fn read_exact<'a>(a: &'a mut [u8]) -> bool {
    is_packet(a)
}

fn to_packet<'a>(_: &'a [u8]) -> Option<&'a [u8]> {
    todo!()
}

fn process_packet<'a>(buf: &'a mut [u8]) {
    read_packet(buf);
    let _packet = to_packet(buf);
}
Run Code Online (Sandbox Code Playgroud)

操场