-
Notifications
You must be signed in to change notification settings - Fork 162
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Affine2 (f32) Can’t Implement bytemuck::Pod #437
Comments
Yes, that does sound like it would violate Bytemuck's Pod constraints. I don't believe there are any checks in Bytemuck, I'm not sure it would be possible for bytemuck itself to check. |
The bytemuck derive macro is supposed to check the constraints: https://docs.rs/bytemuck/latest/bytemuck/derive.Pod.html Manual unsafe implementations of Pod of course don’t get such checks. |
Ah thanks, good to know. |
I think I didn't use derive because at the moment most features are fairly self contained implementation wise, e.g. all the bytemuck changes are in https://github.com/bitshifter/glam-rs/blob/main/src/features/impl_bytemuck.rs. I could use derive, it can just get a bit messy with lots of |
That's an interesting idea. I can imagine two solutions off the top of my head:
But since you can't add derives to a struct after it's defined, there's no easy way I can see to do these things without either duplicating some templates or adding more parameters to the templates, at which point you may as well generate the cfg-bounded Pod derives. You can get close to (1) with something like this for each type in each template (e.g., this one is for Affine2):
If that throws a compile error it will be because the sum of the field sizes is different from the size of Affine2. I borrowed the idea from bytemuck. But if you're not using the derive and have to copy the field types into the assertion, it's potentially error-prone. Other things can go wrong with Pod too, e.g. if generics are used the rules are a little different or if any field is not Pod it is not valid. |
Miri can catch some of these types of issues. I modified the unit tests in impl_bytemuck like so to add a loop that checks each byte against itself:
Now making |
Fix is committed, I am keeping this open as a reminder to look into ways of testing it, e.g. using miri as described above. |
Since Mat2 is 16 byte aligned and Vec2 only takes up 8 bytes, I believe there are 8 following padding bytes in Affine2. According to bytemuck’s documentation it’s illegal to implement Pod for structs with padding bytes (this causes UB when converting from a slice and bad data when converting to a slice).
This could be fixed by removing the unsafe impl Pod or by adding an explicit 8 byte _padding field to Affine2.
There may be other types affected by this too. Anything containing a 16 byte aligned type like Mat2 or Vec4 and then some other stuff may be suspect.
I’m not sure, but does the bytemuck Pod derive check that constraint? If so could it be conditionally applied on structs if the bytemuck feature is active rather than having these unsafe impls?
The text was updated successfully, but these errors were encountered: