gpt4 book ai didi

rust - 为什么 std::rc::Rc 需要 PhantomData?

转载 作者:行者123 更新时间:2023-11-29 07:43:56 25 4
gpt4 key购买 nike

我知道 PhantomData旨在使用数据类型定义中的生命周期或类型参数,否则这些参数将不会被使用。我最近在查看 Rc 的定义在Rust std lib并注意到它似乎使用了 PhantomData , 但它看起来像 T正在兄弟字段中使用ptr作为 NonNull<RcBox<T>> .文档说 NonNull"*mut T but non-zero and covariant."并继续使用声明进一步扩展该定义:

Unlike *mut T, NonNull<T> is covariant over T. If this is incorrect for your use case, you should include some PhantomData in your type to provide invariance, such as PhantomData<Cell<T>> or PhantomData<&'a mut T>.

因此,它是需要方差还是更多是因为 NonNull实际上是一个原始指针和 PhantomData需要将省略的生命周期消耗为 this answer seems to imply

最佳答案

PhantomData在这里用来告诉丢弃检查器丢弃 Rc<T> may cause a value of type T to be dropped .

当我们宣布我们可能会删除类型为 T 的值时,丢弃检查器确保 T 中的任何生命周期比 struct 长寿本身。正是这个检查阻止了 following code从编译。在这种情况下,Rc 的通用参数是PeekOnDrop<&'a u8> ,其生命周期为 'a .

use std::{fmt, rc::Rc};

struct PeekOnDrop<T: fmt::Debug>(T);

impl<T: fmt::Debug> Drop for PeekOnDrop<T> {
fn drop(&mut self) {
println!("{:?}", self.0);
}
}

struct SelfReferential<'a> {
value: Box<u8>,
rc: Option<Rc<PeekOnDrop<&'a u8>>>,
}

fn main() {
let mut sr = SelfReferential {
rc: None,
value: Box::new(1),
};

sr.rc = Some(Rc::new(PeekOnDrop(&*sr.value)));

// `sr` would be dropped here, which could drop `value` before `rc`.
// The destructor of `PeekOnDrop` would then try to inspect the (dangling)
// reference, resulting in UB!
}

有关此处底层逻辑的完整解释,请参阅 the nomicon , 但请注意没有 PeekOnDrop , 前面的例子 compiles just fine .这是因为 Rc<T>在其 Drop impl 中声明它的通用参数 T#[may_dangle] .在这样做时,它 promise 其 Drop impl 对 T 的值不做任何操作它拥有除了(也许)放弃它。仅当丢弃检查器递归检查 Drop PeekOnDrop 的含义并发现它可以访问 T是否发生错误。

为了完整性,here's an example of an undefined program这是通过断言 PeekOnDrop 来实现的的 Drop impl 不访问 T使用 #[may_dangle] .如果Rc,原始示例中将显示相同的未定义行为。没有使用PhantomData声明它可能会删除 T 的值.

关于rust - 为什么 std::rc::Rc 需要 PhantomData?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58027838/

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