通过 `mem::transmute()` 指针存储泛型

Pointer-stashing generics via `mem::transmute()`

我正在尝试为 C 集合库 (Judy Arrays [1]) 编写 Rust 绑定,它只为自己提供存储指针宽度值的空间。我公司有大量现有代码使用此 space 直接存储非指针值,例如指针宽度整数和小型结构。我希望我的 Rust 绑定允许使用泛型对此类集合进行类型安全访问,但我无法使指针存储语义正常工作。

mem::transmute() 函数似乎是实现所需行为的一种潜在工具,但尝试在参数化类型的实例上使用它会产生令我困惑的编译错误。

示例代码:

pub struct Example<T> {
    v: usize,
    t: PhantomData<T>,
}

impl<T> Example<T> {
    pub fn new() -> Example<T> {
        Example { v: 0, t: PhantomData }
    }

    pub fn insert(&mut self, val: T) {
        unsafe {
            self.v = mem::transmute(val);
        }
    }
}

产生的错误:

src/lib.rs:95:22: 95:36 error: cannot transmute to or from a type that contains type parameters in its interior [E0139]
src/lib.rs:95             self.v = mem::transmute(val);
                                   ^~~~~~~~~~~~~~

这是否意味着仅由参数 "contains type parameters in its interior" 组成的类型因此 transmute() 在这里不起作用?对正确的方法有什么建议吗?

(,试图达到相同的结果,但不一定通过 mem::transmute()。)

[1] 我知道现有的 rust-judy 项目,但它不支持我想要的指针存储,而且我编写这些新绑定主要是作为一种学习练习。

您可以将 &T 转换为 &usize,而不是直接将 T 转换为 usize

pub fn insert(&mut self, val: T) {
    unsafe {
        let usize_ref: &usize = mem::transmute(&val);
        self.v = *usize_ref;
    }
}

请注意,如果 T 的大小小于 usize 的大小或对齐要求不同,这可能会从无效的内存位置读取。这可能会导致段错误。您可以添加一个断言来防止这种情况发生:

assert_eq!(mem::size_of::<T>(), mem::size_of::<usize>());
assert!(mem::align_of::<usize>() <= mem::align_of::<T>());