包装器类型之间的不安全类型转换

unsafe type casting between wrappers types

提问人:Timothée Delabrouille 提问时间:10/27/2023 最后编辑:Colonel Thirty TwoTimothée Delabrouille 更新时间:10/29/2023 访问量:42

问:

struct Wrapper1(u32);

impl Wrapper1 {
    fn inner(&self) -> &u32 {
        &self.0
    }
}

struct Wrapper2(u32);

struct Wrapper3(Wrapper1);

trait GetInner {
 fn inner(&self) -> &Wrapper2;
}

impl GetInner for Wrapper3 {
    fn inner(&self) -> &Wrapper2 {
     let raw_pointer = self.0.inner() as *const u32 as *const Wrapper2;
     unsafe {  &*raw_pointer }
    }
}

我有这段代码片段,展示了我的问题的简化。 我必须依靠,因为我不能只这样做:unsafe

impl GetInner for Wrapper3 {
    fn inner(&self) -> &Wrapper2   
      &Wrapper2(*self.0.inner())
    }
}

声音好吗?我的团队中有人对一致性提出了担忧。 其他人提到我们必须在包装器类型上使用,以使其更安全。#[repr(transparent)]

Rust Wrapper 不安全 的原始指针

评论

1赞 user2407038 10/28/2023
一般来说,您肯定必须用于此类类型。在特定情况下,编译器似乎不太可能(尽管在技术上是可行的)会生成不同的布局。对于有壁龛的类型,即使是简单的情况,它也可能会做“奇怪”的事情。不要冒险,使用#[repr(transparent)]u32#[repr(transparent)]
0赞 Timothée Delabrouille 10/28/2023
For types with niches it may do "weird" things even for simple cases. 您能否对此进行扩展并分享有关此现象的一些链接?总结一下你的观点: - 如果我使用它会是合理的 - 如果我不这样做,可能会导致未定义的行为(尤其是对于更复杂的内部类型)#[repr(transparent)]

答:

0赞 Chayim Friedman 10/29/2023 #1

您需要是 或 .不保证结构的布局。Wrapper2#[repr(transparent)]#[repr(C)]#[repr(Rust)

但是,如果你这样做了,你就不再需要不安全了 - 你可以使用 bytemuck

struct Wrapper1(u32);

impl Wrapper1 {
    fn inner(&self) -> &u32 {
        &self.0
    }
}

#[derive(bytemuck::TransparentWrapper)]
#[repr(transparent)]
struct Wrapper2(u32);

struct Wrapper3(Wrapper1);

trait GetInner {
    fn inner(&self) -> &Wrapper2;
}

impl GetInner for Wrapper3 {
    fn inner(&self) -> &Wrapper2 {
        bytemuck::TransparentWrapper::wrap_ref(self.0.inner())
    }
}