rust - 安全地搬出借来的内容

标签 rust borrow-checker

<分区>

我有一个对结构的可变引用,我想通过函数传递它来更改其中一个字段,并将结果设置为该字段的新值。但是,我收到“无法移出借用的内容”编译错误。

这是一个演示我的问题的简单示例:

struct InnerStruct {
    num: usize,
}

struct MyStruct {
    inner_struct: InnerStruct,
}

fn do_something(inner_struct: InnerStruct) -> InnerStruct {
    inner_struct
}

fn main() {
    let mut my_struct = MyStruct {
        inner_struct: InnerStruct { num: 0 },
    };

    let my_struct_ref = &mut my_struct;
    // This line compiles:
    // my_struct_ref.inner_struct = InnerStruct { num: 0 };
    my_struct_ref.inner_struct = do_something(my_struct_ref.inner_struct);
}

这是我得到的编译错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:21:47
   |
21 |     my_struct_ref.inner_struct = do_something(my_struct_ref.inner_struct);
   |                                               ^^^^^^^^^^^^^ cannot move out of borrowed content

do_something 函数必须拥有内部结构的所有权才能执行其工作(在真实源代码中,它在 Tokio futures 上运行)。

我有很多标题相同的帖子“无法移出借用的内容”,所有这些帖子的解决方案都是克隆某些内容或传递引用而不是移动所有权,但我无法将这些解决方案应用于我的案例。

我不明白 Rust 编译器在这种情况下试图防御什么。在我能想到的每一种可能性中,my_struct 都保持一致。

改用这一行编译成功:

my_struct_ref.inner_struct = InnerStruct { num: 0 };

下面三行也可以:

let inner_struct2 = InnerStruct { num: 0 };
let inner_struct = std::mem::replace(&mut my_struct_ref.inner_struct, inner_struct2);
my_struct_ref.inner_struct = do_something(inner_struct);

为什么这被认为是安全的,而第一个代码却不是?

对于如何解决这个问题的任何想法,或者对我正在尝试做的事情的错误/不安全的解释,我将不胜感激。

最佳答案

如果 do_something panic 解除是不可能的 - 您无法将 my_struct_ref 恢复到有效状态,但外部上下文需要 my_struct_ref 有效。

如果有一种通用的方式来表达“如果这种 panic 只是崩溃而不是解除”,那就太好了,据我所知这将使此类操作安全。

take来自 take_mut crate 提供了一个安全的包装器(它捕获了一个展开的 panic 并使其中止,从而解决了展开的问题)。

关于rust - 安全地搬出借来的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47486147/

相关文章:

api - 使用 JSON 作为内容操作结果类型

rust - 翻转 boolean 值的最快方法

rust - 了解特征和对象安全

vector - 如何从函数中的Vec返回单个元素?

enums - 为什么我不能从枚举中可变地借用一个原语?

rust - 错误[E0277] : the trait bound `Vec<TokenStream2>: ToTokens` is not satisfied

generics - 如何将 Rc<RefCell<ConcreteType>> 转换为 Rc<RefCell<dyn Trait>>?

循环中的 Rust 生命周期问题

rust - 使用包含借用参数的结构

hashmap - 如何在 Rust 中懒惰地创建其构造使用 self 的映射条目