MintX
July 11, 2023, 9:33am
1
I'm trying to find the best way to write a VectorN with the least code repetition possible and have easy access to both its fields x, y, z, w, ...
and its slice representation. Here's what I did:
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vector<T: Copy, const N: usize>([T; N]);
#[repr(C)]
#[derive(Clone, Copy)]
pub struct Vector4View<T>{
pub x: T,
pub y: T,
pub z: T,
pub w: T,
}
impl<T: Copy> Deref for Vector<T, 4> {
type Target = Vector4View<T>;
fn deref(&self) -> &Self::Target {
unsafe { mem::transmute(self) }
}
}
Now I can write most methods for all of VectorN's at the cost of some unsafe code and a non-standard Deref usage.
Question: Is this safe or sound? Is this a bad idea?
alice
July 11, 2023, 9:41am
2
You should use a pointer cast instead of transmuting the reference.
5 Likes
jbe
July 11, 2023, 9:44am
3
Maybe it should also be #[repr(transparent)]
instead of #[repr(C)]
? Though I guess it results in the same in the given case.
For the second declaration, repr(transparent)
isn't possible. I think for the first one it might make a difference for N = 0
.
jbe
July 11, 2023, 9:55am
5
Ooops, sorry I missed that.
jofas
July 11, 2023, 10:01am
6
alice:
pointer cast
Do you mean like this?
fn deref(&self) -> &Self::Target {
unsafe { &*(self as *const Vector<T, 4>).cast::<Self::Target>() }
}
MintX
July 11, 2023, 10:04am
7
#[repr(transparent)]
actually errors on [T; 0]
, but works just like #[repr(C)]
for [T; N]
when N is 0
1 Like
jbe
July 11, 2023, 10:23am
8
Oddly, it works with [u8; 0]
(Playground ).
File a bug. It looks like this was missed when in 1.55 we made repr(transparent)
require at most one thing that's not a 1-ZST, rather than the exactly one thing that's not a 1-ZST.
opened 04:19AM - 12 Oct 20 UTC
closed 10:10AM - 24 Jun 21 UTC
T-lang
C-bug
disposition-merge
finished-final-comment-period
A-layout
A-zst
```rust
#[repr(transparent)]
struct X(()); // ERROR: needs exactly one non-zer… o-sized field, but has 0
```
But
```rust
#[repr(transparent)]
struct X<T>(T);
println!("{}", mem::align_of_val(&X(()))); // 1
println!("{}", mem::size_of_val(&X(()))); // 0
```
The reference says
>The transparent representation can only be used on a struct or an enum with a single variant that has:
>- a single field with non-zero size, and
>- any number of fields with size 0 and alignment 1 (e.g. PhantomData<T>).
I do not see a reason for this restriction. Maybe simply replace "a single" by "at most one" and remove the check.
1 Like
system
Closed
October 9, 2023, 5:36pm
10
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.