Rust 为什么std::rc::rc需要幻影数据?

Rust 为什么std::rc::rc需要幻影数据?,rust,Rust,我知道PhantomData旨在使用数据类型定义中的生存期或类型参数,否则这些参数将不被使用。我最近查看了中的Rc的定义,注意到它似乎使用了PhantomData,但它看起来像是T在兄弟字段ptr中被用作一个函数。文档称NonNull是,并进一步用语句扩展了该定义: 与*mut T不同,NonNull在T上是协变的。如果这对您的用例不正确,您应该在您的类型中包含一些PhantomData,以提供不变性,例如PhantomData或PhantomDataPhantomData在这里用于告诉拖放检查

我知道
PhantomData
旨在使用数据类型定义中的生存期或类型参数,否则这些参数将不被使用。我最近查看了中的
Rc
的定义,注意到它似乎使用了
PhantomData
,但它看起来像是
T
在兄弟字段
ptr
中被用作一个函数。文档称
NonNull
是,并进一步用语句扩展了该定义:


*mut T
不同,
NonNull
在T上是协变的。如果这对您的用例不正确,您应该在您的类型中包含一些
PhantomData
,以提供不变性,例如
PhantomData
PhantomData
PhantomData
在这里用于告诉拖放检查器拖放
Rc

当我们宣布可以删除类型为
T
的值时,删除检查器确保
T
中的任何生存时间都比
结构本身的生存时间长。正是此检查阻止了编译。在这种情况下,
Rc
的一般参数是
PeekOnDrop>>,
}
fn main(){
设mut sr=SelfReferential{
rc:没有,
值:框::新(1),
};
sr.rc=一些(rc::new(PeekOnDrop(&*sr.value));
//'sr'将被删除在这里,这可能会在'rc'之前删除'value'。
//“PeekOnDrop”的析构函数随后将尝试检查(悬空的)
//参考,导致UB!
}
有关此处底层逻辑的完整解释,请参阅,但请注意,在没有
PeekOnDrop
的情况下,前面的示例。这是因为
Rc
在its中声明其泛型参数
T
#[may_dangle]
。在这样做的过程中,它承诺其
Drop
impl不会对其拥有的
T
值进行任何处理,除了(可能)Drop它。只有当拖放检查器递归地检查
PeekOnDrop
drop
impl并发现它可以访问
T
时,才会发生错误


为了完整性,这取决于断言
PeekOnDrop
Drop
impl不会使用
#[可能悬挂]
访问
T
。如果
Rc
没有使用
PhantomData
声明它可能会降低
T
的值,则原始示例中将显示相同的未定义行为?没有可省略的生存期。啊,对了,因为没有显式的生存期,
T
的生存期边界,任何类型的引用,以及原始指针,我们没有提到生存期,但这是否意味着
幻影数据
将被提供给子类型关注点?我引用的后面的一句话接着说:“通常这是不必要的;协方差对于大多数安全的抽象都是正确的,比如Box、Rc、Arc、Vec和LinkedList。”iiuc这意味着提供幻影类型可以使外壳类型在
t
上保持不变,但是,
Rc
使用它,这句话暗示它在
T
上是协变的。
Rc
并不总是有
PhantomData
字段。这里介绍了提交:提交消息引用,但这似乎非常古老,也不能完全解释为什么要这样做。我猜它与丢弃逻辑有关,而与生命周期或子类型无关。我认为,链接到commit@PeterHall的消息支持我的猜测,并表明它与
Shared
NonNull
之间的区别有关(后者取代了
Shared
)。