POSTS
Rust Variance
RustVariance
最近学习 Bevy 源码,参考大佬的 Bevy之书 看到 UnsafeWorldCell 时,
// 源码: crates/bevy_ecs/src/world/unsafe_world_cell.rs:84
pub struct UnsafeWorldCell<'w> {
ptr: *mut World,
#[cfg(debug_assertions)]
allows_mutable_access: bool,
_marker: PhantomData<(&'w World, &'w UnsafeCell<World>)>,
}
其中 _marker 签名有点让人困惑,涉及 Rust variance 的知识点,之前这里一直没有弄明白,知道有这个东西,但是不知道什么时候用。
主要就是参考官方文档 [1],[2], 然后就是一顿问 Claude。
大致就是 &'w World 对 'w 是协变(covariant), &'w UnsafeCell<World> 没啥用,也是协变作用. 如果要是不变(invariant)的话, 就要写成 UnsafeCell<&'w World>, 这里还有让UnsafeWorldCell为!Sync?
参考官方文档 [2] 的表:
PhantomDataCell<&'a ()> 才能对 'a 不变.
这个结论也可以参考 bevy 的当时的 commit, 其中 comment 提到:
@BoxyUwU BoxyUwU on Feb 3, 2023 We need to actually use the ‘w lifetime inside the struct or else rust gives a compile error, it probably could just be PhantomData<&‘w World> or PhantomData<&‘w UnsafeCell
> instead of both but i figured it probably doesn’t hurt to do both
参考
[1] https://doc.rust-lang.org/nightly/reference/subtyping.html#variance [2] https://doc.rust-lang.org/nightly/nomicon/phantom-data.html#table-of-phantomdata-patterns [3] https://zhanghandong.github.io/bevy-book/