首页 文章

安全地搬出借来的内容[重复]

提问于
浏览
0

这个问题在这里已有答案:

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

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

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期货上运行) .

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

在这种情况下,我无法理解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);

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

我将很感激有关如何解决这个问题的任何想法,或者对我正在尝试做什么的错误/不安全的解释 .

1 回答

  • 2

    如果 do_something 恐慌无法展开 - 您无法将 my_struct_ref 恢复为有效状态,但外部上下文要求 my_struct_ref 有效 .

    如果有一种通用的方式说“如果这种恐慌只是崩溃而不是放松”,这将是很好的,这将使这样的操作安全,据我所知 .

    来自take_mut crate的take提供了一个安全的包装器(它捕获了一个放松的恐慌并使其中止,解决了解除问题) .

相关问题