Stream: t-lang/wg-unsafe-code-guidelines

Topic: Conversion between references to repr(C) structs


Thom Chiovoloni (Aug 06 2019 at 23:42, on Zulip):

If I have two #[repr(C)] (and Copy) structs Vec4 { x: f32, y: f32, z: f32, w: f32 } and Vec3 { x: f32, y: f32, z: f32 }, is it legal for a &Vec3 to alias a &Vec4? e.g. if i transmute &Vec4 to &Vec3 is that allowed? (I want to know if some of my older code is unsound, or just... dodgy)

nagisa (Aug 06 2019 at 23:49, on Zulip):

Dodgy, definitely. Whether that will work depends entirely on layout compatibility, which is not necessarily compatible for these two structures.

Thom Chiovoloni (Aug 06 2019 at 23:55, on Zulip):

the complete declaration is

#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct V3 { pub x: f32, pub y: f32, pub z: f32, }

#[derive(Copy, Clone, Debug, Default, PartialEq)]
#[repr(C)]
pub struct V4 { pub x: f32, pub y: f32, pub z: f32, pub w: f32 }

(with some whitespace removed for brevity) is that enough to determine layout compatibility? or is this something that's still unspecified

Thom Chiovoloni (Aug 06 2019 at 23:56, on Zulip):

e.g. there are no other repr's involved, if that's what you meant

Thom Chiovoloni (Aug 07 2019 at 00:00, on Zulip):

it also does stuff like convert &[V4] to &[f32] (via from_raw_parts and some pointer casting). avoiding that would be... harder, unfortunately. this feels less dodgy to me though, but I can't really place why (it might just be that I... want it to be fine :sweat_smile:)

nagisa (Aug 07 2019 at 00:16, on Zulip):

reinterpretation to a slice would be not fine on any target where f32 was aligned to 64 bits, for example.

nagisa (Aug 07 2019 at 00:16, on Zulip):

not that any real target like that comes to mind.

nagisa (Aug 07 2019 at 00:17, on Zulip):

Oh wait, never mind, I’m stupid. Repeated note to self: do not think about complicated things when its 3am.

Thom Chiovoloni (Aug 07 2019 at 00:17, on Zulip):

@nagisa wouldn't V4 have to be have the same alignment?

Thom Chiovoloni (Aug 07 2019 at 00:17, on Zulip):

ah, i'm the same way. sleep is... hard.

gnzlbg (Aug 07 2019 at 14:00, on Zulip):

If I have two #[repr(C)] (and Copy) structs Vec4 { x: f32, y: f32, z: f32, w: f32 } and Vec3 { x: f32, y: f32, z: f32 }, is it legal for a &Vec3 to alias a &Vec4? e.g. if i transmute &Vec4 to &Vec3 is that allowed?

I think this is always legal, because the alignment requirement of Vec4 and Vec3 are the same for all targets we can ever support.

gnzlbg (Aug 07 2019 at 14:02, on Zulip):

AFAICT, the only condition that must be met is that &Vec4 must point to an allocation that's suitably aligned for Vec3.

gnzlbg (Aug 07 2019 at 14:03, on Zulip):

In your case, since the structs are repr(C), this always holds. But even if you were to construct a different case where the alignment requirement of Vec4 was smaller than that of Vec3, you would still be able to do that as long as the concrete Vec4 being aliased would live at an address that's a multiple of the alignment requirement of Vec3.

Last update: Nov 19 2019 at 17:35UTC