rust - 解决嵌套可变借用冲突的惯用方法

标签 rust borrow-checker

考虑下面的最小示例,它呈现了我在一些实际代码中遇到的情况:

use std::collections::HashSet;
type HS = HashSet<String>;

fn fn1(x: String, hs0: &mut HS, hs1: &mut HS) {
    // ...
}

fn fn0(hs0: &mut HS, hs1: &mut HS) {
    hs0.get("").map(|x| fn1(x.clone(), hs0, hs1));
}

fn main() {
    let mut hs0 = HS::new();
    let mut hs1 = HS::new();
    fn0(&mut hs0, &mut hs1);
}

借用检查员不高兴:

error[E0500]: closure requires unique access to `hs0` but `*hs0` is already borrowed
 --> <anon>:9:21
  |
9 |     hs0.get("").map(|x| fn1(x, hs0, hs1));
  |     ---             ^^^        ---      - borrow ends here
  |     |               |          |
  |     |               |          borrow occurs due to use of `hs0` in closure
  |     |               closure construction occurs here
  |     borrow occurs here

on the Rust playground


我理解上面的错误消息,并且我想知道解决此问题的惯用方法。请注意:

  • 出于可读性/可测试性的原因,我希望 fn0fn1 成为单独的函数。 (也就是说,它们本身就有意义。)

  • 我想在 .map(...) 链式调用中使用相同的参数从 fn0 调用 fn1

不使用 .map 是唯一明智的选择吗?

最佳答案

粗略地说,hs0 一直是借用的,直到没有对其任何部分的引用为止。也就是说,当 x: &String 存在时,您不能可变地借用 hs0。这意味着我们需要做一些事情来结束 x 的生命周期,例如将其转换为 String 并将该字符串传递到下一个 map

fn fn0(hs0: &mut HS, hs1: &mut HS) {
    hs0.get("").map(|x| x.clone()).map(|x| fn1(x, hs0, hs1));
}

关于rust - 解决嵌套可变借用冲突的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44775806/

相关文章:

rust - 如何在 Rust 中解构和取消引用元组

rust - 如何借用一个字段进行序列化,但在反序列化时创建它?

rust - 通用 `impl<T: Read + Seek> KaitaiStream for T {}`的Rust特征暗示

rust - 返回对外部引用的过滤向量的引用时如何安抚借用检查器

rust - "Does not live long enough"`Weak<RefCell<_>>` 错误

rust - 如何实现可能的突变的通用穿插

immutability - 我如何强制结构的字段在 Rust 中始终不可变?

rust - 从 HashMap 或 Vec 返回引用会导致借用超出其所在范围?

Rust:将值移出选项并压入堆栈

rust - 从 HashMap 或 Vec 返回引用会导致借用超出其所在范围?