循环中的可变借用

Cre*_*oat 0 reference lifetime rust

我的代码:

struct Foo<'a> {
    bytes: &'a mut [u8],
}

impl<'a> Foo<'a> {
    fn bar<'b>(&'b mut self) {
        self.bytes = &mut self.bytes[1..];
    }
}

fn baz<'a, 'b>(foo: &'b mut Foo<'a>) {
    println!("baz!");
    
    for _ in 0..3 {
        foo.bar();
    }
}
Run Code Online (Sandbox Code Playgroud)

也在Rust Playground 中

这会导致以下错误回溯:

   Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:12:27
   |
12 |         self.bytes = &mut self.bytes[1..];
   |                           ^^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
  --> src/main.rs:11:12
   |
11 |     fn bar<'b>(&'b mut self) {
   |            ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:12:27
   |
12 |         self.bytes = &mut self.bytes[1..];
   |                           ^^^^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
  --> src/main.rs:10:6
   |
10 | impl<'a> Foo<'a> {
   |      ^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:12:22
   |
12 |         self.bytes = &mut self.bytes[1..];
   |                      ^^^^^^^^^^^^^^^^^^^^

For more information about this error, try `rustc --explain E0495`.
error: could not compile `playground` due to previous error
Run Code Online (Sandbox Code Playgroud)

目标

我正在寻找更改bar/的函数签名baz以使其编译。我的理解是,我需要在'a&上指定生命周期界限'b,它会起作用,但我在两个函数中'b: 'a都得到不同的错误。'a: 'b

我还浏览了大约 10 个其他“循环中可变借用”问题,但我不太理解答案,无法将它们应用到我的问题中,所以即使这是重复的,我也会很感激与此相关的答案具体是玩具示例。

任何帮助表示赞赏!

Cae*_*sar 6

bytes@vikram2784 的解决方案有效,但可以通过仅替换而不是整个来表达得更简洁Foo

impl<'a> Foo<'a> {
    fn bar(&mut self) {
        let tmp = &mut [][..];
        let bytes = std::mem::replace(&mut self.bytes, tmp);
        self.bytes = &mut bytes[1..];
    }
}
Run Code Online (Sandbox Code Playgroud)

Foo如果包含一些没有明显默认值的附加字段,此模式也更易于使用。

关于这种解决方案需要注意的一件事是:如果发生bytes[1..]恐慌,空的临时文件将保留在原处。在这里,我能想到的恐慌的唯一原因就是bytes空虚,所以没关系,但根据情况,你可能会被它咬住。