如何从原始指针创建一个 ?Sized 类型?

How do you create a ?Sized type from a raw pointer?

这是一个如何从原始指针转换 Sized 类型的示例:

use std::mem;

#[derive(Eq, PartialEq)]
#[repr(packed)]
struct Bob {
    id: u32,
    age: u32,
}

unsafe fn get_type<'a, T: Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

#[test]
fn it_works() {
    let bob = Bob {
        id: 22,
        age: 445,
    };
    let bob2: &Bob = unsafe {
        let ptr: *const u8 = mem::transmute(&bob);
        get_type(ptr)
    };
    assert_eq!(&bob, bob2);
}

但是,对于我的应用程序,我希望能够获得 ?Sized 类型而不是 Sized 类型。但是,这不起作用:

unsafe fn get_type2<'a, T: ?Sized>(p: *const u8) -> &'a T {
    mem::transmute(p)
}

失败并显示此错误消息:

error: transmute called with differently sized types: *const u8 (64 bits) to &'a T (pointer to T) [--explain E0512]
 --> src/main.rs:2:9
  |>
2 |>         mem::transmute(p)
  |>         ^^^^^^^^^^^^^^

我试图通过使用 std::slice::from_raw_parts 转换它来给它一个 &[u8](胖指针),但它失败了,并出现了几乎相同的错误消息。

由于错误消息中引用的原因,您实际上不能。

Rust 引用可以是指针大小的(对于 Sized 类型)或 更大的(对于 !Sized 类型)。例如,如果 Trait 是特征,则 &Trait 引用实际上是 std::raw::TraitObject.

定义的两个字段

因此,为了形成对未确定大小的类型的引用,您必须:

  • 准确识别它是哪种未调整大小的类型(特征?切片?...)
  • 选择正确的表示形式(std::raw::TraitObjectstd::raw::Slice、...)

然后你必须填写空白(不仅仅是一个指针)。

因此,除非您可以将函数限制为生成 &T where T: Sized,否则您不能将原始指针转换为 &T