Have there been any proposals for improved ergnomics with #[repr(transparent)] newtypes

Have there been any proposals for improving the ergonomics converting between a struct and a #[repr(transparent)] newtype that wraps that struct?

For example:

struct Coord {
    x: f32,
    y: f32,
}

#[repr(transparent)]
struct Point(Coord);

fn main() {
    let coord = Coord { x: 1., y: 1. };
    let coords: Vec<Coord> = vec![coord];

    let points: Vec<Point> = coords; // error
    let points = coords as Vec<Point>; // error
}

My understanding is it's sound to use the unsafe mem::transmute in this situation, but I'm trying to avoid unsafe for this use-case. I'm wondering if there's a way to do there's been a discussion or RFC about making this possible.

You may be interested in the Safe Transmute working group. They are working towards defining a set of transmute-like conversions that can be made safe.

1 Like

No, transmute is not safe here. You will need to go through Vec::from_raw_parts instead.

Can you expand on why it's not safe?

Vec does not commit to a particular layout. Vec<Coord> and Vec<Point> might have the pointer/length/capacity fields in a different order or might have different padding. This can happen in the real world e.g. in the case of applying profile-guided optimization to type layouts.

1 Like

I don't think the Rust guarantee that the Wrapper<T> and Wrapper<U> are layout compatible even if the T and U are layout compatible, so transmuting Vec<Coord> into Vec<Point> may not be sound.

Vec:::from_raw_parts() seems to address layout compatibility problem so it would be ok.

1 Like

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.