gpt4 book ai didi

send - Send 特征的终身问题

转载 作者:行者123 更新时间:2023-11-29 07:49:20 30 4
gpt4 key购买 nike

我很难理解为什么这段代码无法编译:

use std::cell::{Ref, RefCell};

struct St {
data: RefCell<uint>
}

impl St {
pub fn test(&self) -> Ref<uint> {
self.data.borrow()
}
}

// This code would compile without T constrained to be Send.
fn func<T: Send>(_: &T) {
}

fn main() {
let s = St { data: RefCell::new(42) };

{
let r7 = s.test();
// Do not compile
func(&r7)
}

// Compile
func(&s);
}

它给出了以下错误:

bug.rs:21:18: 21:19 error: `s` does not live long enough
bug.rs:21 let r7 = s.test();
^
note: reference must be valid for the static lifetime...
bug.rs:17:11: 28:2 note: ...but borrowed value is only valid for the block at 17:10
bug.rs:17 fn main() {
bug.rs:18 let s = St { data: RefCell::new(42) };
bug.rs:19
bug.rs:20 {
bug.rs:21 let r7 = s.test();
bug.rs:22 // Do not compile
...

当我试图约束 T 使其与 Send 特性兼容时,问题似乎出在函数 func() 中。没有这个约束,这段代码编译没有错误。

谁能向我解释这种行为的原因是什么?

最佳答案

Rust 1.0 更新

在 Rust 1.0 及更高版本中,示例中的代码(当 uint 被某些现有类型替换时)失败并出现另一个错误:

% rustc test.rs
test.rs:23:9: 23:13 error: the trait `core::marker::Sync` is not implemented for the type `core::cell::UnsafeCell<usize>` [E0277]
test.rs:23 func(&r7)
^~~~
test.rs:23:9: 23:13 help: run `rustc --explain E0277` to see a detailed explanation
test.rs:23:9: 23:13 note: `core::cell::UnsafeCell<usize>` cannot be shared between threads safely
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::Cell<usize>`
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::BorrowRef<'_>`
test.rs:23:9: 23:13 note: required because it appears within the type `core::cell::Ref<'_, i32>`
test.rs:23:9: 23:13 note: required by `func`

这有点棘手 - 另一个特点,Sync , 不知从何而来。

实现 Send 的类型trait(尽管目前肯定缺少它的文档)是可以跨任务边界转移的东西。大多数类型是 Send , 但有些, 比如 RcWeak , 不是 Send因为此类类型的实例可能共享非同步可变状态,因此在多个线程中使用是不安全的。

在旧的 Rust 版本中 Send暗示'static , 所以引用不是 Send .然而,自 Rust 1.0 以来,Send不再暗示 'static ,因此可以跨线程发送引用。但是,为了 &T成为Send , T必须是 Sync :这是以下实现所必需的:

impl<'a, T> Send for &'a T where T: Sync + ?Sized

但在我们的例子中,我们不需要 &TSend ,我们只需要 TSend ,所以这真的不重要,对吧?

没有。事实上,仍然有 引用,即使我们没有立即看到它们。请记住,类型为 Send它的每个组件都必须是 Send ,也就是说,结构的每个字段和枚举的每个枚举变体的每个部分都必须是 Send对于这个结构/枚举是 Send以及。 core::cell::Ref内部 contains struct BorrowRef 的实例,这又是containsCell<BorrowFlag> 的引用.这里是Sync来自:顺序或&Cell<BorrowFlag>成为Send , Cell<BorrowFlag>必须是 Sync ;然而,它不是也不可能是Sync因为它提供了非同步的内部可变性。这是错误的实际原因。

关于send - Send 特征的终身问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26784654/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com