Safe to reinterpret?

Is that safe to assume that these 3 types have the same memory layout:

I suspect not, but Vector of nalgebra defined like that

[[T; 2]; 1]

Could it have non-trivial layout?

The cgmath::Vector2 and nalgebra::Vector2 types make use of #[repr(C)] and #[repr(transparent)] in a way that guarantees compatible layout. The winit type does not.

2 Likes

aha! nalgebra does? where do you see it?

In general, you also need to consult the library's documentation. #[repr(C)] is a likely indication that stable layout is offered, especially for numeric vector types, but in general, a type might have a specific repr for internal reasons, not intended for external use, and change that representation in future library versions.

4 Likes

The matrix type looks like this in the documentation:

#[repr(C)]
pub struct Matrix<T, R, C, S> {
    pub data: S,
    // some fields omitted
}

The extra fields are just PhantomData. Here, the S type is ArrayStorage<T, 2, 1> which is #[repr(transparent)] around a [[T; 2]; 1]. So since both structs are #[repr(C)] or #[repr(transparent)] the layout is guaranteed.

The question of whether the crates would consider it a breaking change to remove these annotations is another matter.

3 Likes

Your are right!

Thanks! That makes sense.

Another factor to consider: unless you actually have, for example, a slice of data to be processed in bulk, there is no need to reach for unsafe code rather than simply copying the fields from one type to another. The compiler will (almost always) recognize that that code is trivial and eliminate it if the layouts are the same, and if they aren't the same, it'll do the right thing.

For example, in my code I have this very similar function to your question:

pub fn logical_size_from_vec(size: cgmath::Vector2<u32>) -> winit::dpi::LogicalSize<u32> {
    LogicalSize {
        width: size.x,
        height: size.y,
    }
}

This function will almost certainly be optimized down to no code at all. And it is always correct.

4 Likes

Yes, but my motivation is not as much performance as ability to write less code and ability to reuse code.

Also, in some cases optimization is not possible.

Never use unsafe for the sake of shorter code. That path leads to subtly broken programs.

4 Likes

Been conservative was always my weak side. Thanks for the advice.

There is a great Rust Koan which talks about this lesson:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.