Rust – 如何在同一个参数上指定可变生命周期和不可变生命周期?

huangapple go评论57阅读模式
英文:

Rust - How to specify a mutable lifetime and an immutable lifetime on the same parameter?

问题

我有一个函数 `foo`,它的两个参数是可变引用:`vec1`  `vec2`。`foo`  `vec1` 中添加值,然后将这些值的引用存储在 `vec2` 中。因此,`vec1` 的生命周期与 `vec2` 中的引用的生命周期交织在一起。这导致了函数定义 `fn foo<'a>(vec1:&'a mut Vec<bool>, vec2:&mut Vec<&'a bool>)`。然而,这意味着只要 `vec2` 存在,`vec1` 就是可变的。但是,在调用 `foo` 后,`vec1` 不能再是可变的。有办法可以指定这一点吗?

一个最小化的可重现示例可能如下所示:

```rust
fn foo<'a>(vec1:&'a mut Vec<bool>, vec2:&mut Vec<&'a bool>){
    vec1.push(true);
    vec2.push(&vec1.get(0).unwrap());
}

fn main() {
    let mut vec1 = vec![];
    let mut vec2 = vec![];
    foo(&mut vec1, &mut vec2);
    bar(&vec1,&vec2);
}

fn bar(vec1:&Vec<bool>,vec2:&Vec<&bool>){

}

这导致以下编译错误:

error[E0502]: cannot borrow `vec1` as immutable because it is also borrowed as mutable
  --> src/main.rs:12:9
   |
11 |     foo(&mut vec1, &mut vec2);
   |         --------- mutable borrow occurs here
12 |     bar(&vec1,&vec2);
   |         ^^^^^ ----- mutable borrow later used here
   |         |
   |         immutable borrow occurs here

定义 foo,使得在 foo 的作用域内 vec1 是可变的,但在生命周期 'a 中作为不可变引用存在,将解决我的问题,也不会违反 Rust 的借用规则。

我猜这是不可能的,我需要一些使用 RefCell 的解决方法。


<details>
<summary>英文:</summary>

I have a function `foo` which has two mutable references as parameter: `vec1` and `vec2`. `foo` adds values to `vec1` and then stores references to these values in `vec2`. Hence, the lifetime of `vec1` is intermingled with the lifetime of the references in vec2. This results in the function definition `fn foo&lt;&#39;a&gt;(vec1:&amp;&#39;a mut Vec&lt;bool&gt;, vec2:&amp;mut Vec&lt;&amp;&#39;a bool&gt;)`. However, this means that `vec1` is now mutable as long as `vec2` lives. But `vec1` cannot be mutable after the call to foo. Is there a way to specify this?

A minimal reproducable example may look like this:

fn foo<'a>(vec1:&'a mut Vec<bool>, vec2:&mut Vec<&'a bool>){
vec1.push(true);
vec2.push(&vec1.get(0).unwrap());
}

fn main() {
let mut vec1 = vec![];
let mut vec2 = vec![];
foo(&mut vec1, &mut vec2);
bar(&vec1,&vec2);
}

fn bar(vec1:&Vec<bool>,vec2:&Vec<&bool>){

}


This results in the following compiler error:

error[E0502]: cannot borrow vec1 as immutable because it is also borrowed as mutable
--> src/main.rs:12:9
|
11 | foo(&mut vec1, &mut vec2);
| --------- mutable borrow occurs here
12 | bar(&vec1,&vec2);
| ^^^^^ ----- mutable borrow later used here
| |
| immutable borrow occurs here


Defining `foo` so that `vec1` is mutable in the scope of `foo` but lives as immutable reference for lifetime `&#39;a` would solve my problem and not hurt Rust&#39;s borrow rules.  

I guess this is not possible and I need some workaround with `RefCell`.

</details>


# 答案1
**得分**: 2

关于生命周期问题,我认为你无法避免在函数调用之后延长引用的生命周期。但你可以做的是,将那些可变引用分离出来。例如,你可以将函数拆分为以下部分:

```rust
fn foo_start(vec: &mut Vec<bool>) {
    vec.push(true);
}

fn foo_end<'a>(src: &'a Vec<bool>, idx: usize, dest: &mut Vec<&'a bool>) {
    dest.push(src.get(idx).unwrap());
}

fn main() {
    let mut vec1 = vec![];
    let mut vec2 = vec![];
    
    foo_start(&mut vec1);
    foo_end(&vec1, 0, &mut vec2);
    bar(&vec1, &vec2);
}

fn bar(vec1: &Vec<bool>, vec2: &Vec<&bool>) {

}

不幸的是,这可能会破坏你的算法的“封装性”,因为你需要在这两个分离的函数之间建立数据流链接。

英文:

Regarding lifetimes, I don't think you can avoid this lifetime extension beyond the function call. What you can do, is decouple those mutable references to the vectors. For example, you can split the function in parts like so


fn foo_start(vec:&amp;mut Vec&lt;bool&gt;) {
    vec.push(true);
}

fn foo_end&lt;&#39;a&gt;(src: &amp;&#39;a Vec&lt;bool&gt;, idx: usize, dest:&amp;mut Vec&lt;&amp;&#39;a bool&gt;) {
    dest.push(src.get(idx).unwrap());
}

fn main() {
    let mut vec1 = vec![];
    let mut vec2 = vec![];
    
    foo_start(&amp;mut vec1);
    foo_end(&amp;vec1, 0, &amp;mut vec2);
    bar(&amp;vec1,&amp;vec2);
}

fn bar(vec1:&amp;Vec&lt;bool&gt;,vec2:&amp;Vec&lt;&amp;bool&gt;){

}

Unfortunately it may break some "encapsulation" of your algorithm, as you'll need to link the data flow between those two splitted functions

huangapple
  • 本文由 发表于 2023年3月9日 17:10:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/75682488.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定