Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it safe to cast references to unsized transparent types?

Tags:

rust

The #[repr(trasparent)] attribute marks a type to have the same type layout as its single non-zero sized field, but does the same apply to references/pointers of said types when the types are unsized?

Specifically, can I safely cast between &MySlice<T> and &[T] in the below example?

#[repr(transparent)]
struct MySlice<T>([T]);

let std_slice: &[i32] = &[ 1, 2, 3 ];

// is this safe?
let my_slice: &MySlice<i32> = unsafe {
    std::mem::transmute(std_slice)
};
like image 588
Frxstrem Avatar asked Apr 26 '20 13:04

Frxstrem


1 Answers

According to The Rust Reference, the single field of the struct with the #[repr(transparent)] will have both the same representation and ABI.

This means that the ABI of a &MySlice<T> is the same as that of a &[T], since MySlice has no other fields, and we can therefore treat it the same as [T]. It is therefore safe to convert between them.

However the way you are doing it is unsound, and can actually lead to lifetime errors, since std::mem::transmute does not keep lifetimes if its type parameters have lifetimes, and neither does pointer casting, although, pointer casting is generally understood to be safer since the compiler can intervene should you make a mistake.

Therefore, the correct way to create a &MySlice is as follows:

#[repr(transparent)]
struct MySlice<T>([T]);

impl<T> MySlice<T> {
    pub fn make<'a>(value: &'a [T]) -> &'a Self {
        unsafe {
            &*(value as *const [T] as *const Self)
        }
    }
}

Playground.
This preserves lifetimes and avoids transmute.


Additionally, one could also use unions:

#[repr(transparent)]
struct MySlice<T>([T]);

union SliceRepr<'a, T> {
    slice: &'a [T],
    my_slice: &'a MySlice<T>,
}

impl<T> MySlice<T> {
    pub fn make<'a>(value: &'a [T]) -> &'a Self {
        unsafe {
            SliceRepr { slice: value }.my_slice
        }
    }
}

Since this also cares for lifetimes.

like image 154
Optimistic Peach Avatar answered Nov 16 '22 02:11

Optimistic Peach