如何创建 DST 类型?

How to create a DST type?

DST(动态大小类型)现在是 Rust 中的一个东西。我已经成功地使用了它们,最后一个灵活的成员是编译器已知的(例如[u8])。

但是,我想要做的是创建自定义夏令时。比如说:

struct Known<S> {
    dropit: fn (&mut S) -> (),
    data: S,
}

struct Unknown {
    dropit: fn (&mut ()) -> (),
    data: (),
}

预期用法为 Box<Known<S>> => Box<Unknown> => Box<Known<S>>,其中中间件不需要知道具体类型。

注意:是的,我知道 Any,不,我对使用它不感兴趣。

我愿意接受有关 KnownUnknown 布局的建议,但是:

  1. size_of::<Box<Known>>() = size_of::<Box<Unknown>>() = size_of::<Box<u32>>();那就是它应该是一个细指针。
  2. dropping Box<Unknown> 删除其内容
  3. 克隆Box<Unknown>(假设是可克隆的S),克隆其内容
  4. 理想情况下,fn dup(u: &Unknown) -> Box<Unknown> { box u.clone() } 有效

我对 (3) 和 (4) 有特别的困难,我可以通过手动分配内存来解决 (3)(不使用 box,而是直接调用 malloc),但我更喜欢为用户提供惯用的体验。

我找不到任何关于如何通知 box 要分配的正确大小的文档。

目前unsized object正好有两类:slices([T]),这里增加了一个length成员;和 trait 对象(TraitTrait + Send&c.),它在其中添加了一个 vtable,其中包含一个析构函数,该析构函数知道要释放多大的对象。

目前没有任何机制可以声明您自己的各种未确定大小的对象。

此时,你应该从Arc::new_uinint_slice and Arc::from_ptr中寻求灵感。

虽然我们没有使自定义 DST 很好地协同工作的良好机制,但Arc<Known<T>> 令人讨厌。

我们仍然总是用 CoerceUnsized 创建 Arc<dyn Trait> 因为你目前不能从 DST 中创建特征对象。

您可以尝试使用 the vptr crate,它将 vtable 指针与数据而不是指针一起存储。