我有这段代码展示了我的问题的简化。
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)]
才能使其更安全。
您需要
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())
}
}