logoalt Hacker News

steveklabnikyesterday at 12:02 AM1 replyview on HN

That’s a related concept but not the same thing.

The “validity” rules in Rust (like C’s trap representations) are about which bit patterns represent valid values, not about which pointer types may alias the same memory.

Strict aliasing is a type-based access rule; validity is a value-based representation rule.

Rust enforces the latter (invalid values are undefined behavior), but explicitly does not enforce the former (raw pointers may alias arbitrarily). That’s the difference.

To put it into code:

  float foo(const uint32_t *xs) {
      const float *fp = (const float*)xs; // UB: incompatible effective type
But in Rust, the equivalent:

  fn foo(xs: *const u32) {
      let ptr = xs as *const f32; // not UB to access through ptr later
(I am on my phone and so may have made small errors and revised a few times, my apologies.)

It’s also true you must pay attention to validity: this works in Rust because all bit patterns of u32 and f32 are valid for f32 (IEEE-754). If you tried u32 -> bool, you’d hit UB not because of aliasing, but because many u8 patterns are invalid for bool (only 0 and 1 are valid). Creating the pointer is fine; dereferencing would only be okay if you first ensure at runtime that the stored bits are valid for the target type, and alignment is satisfied.


Replies

ueckeryesterday at 8:43 PM

I understand the difference and this is why I said "similar constraints". Once you have non-value (trap) representations you need to be careful when dereferencing pointers cast to different types, even if you do not have strict aliasing. The point under the discussion upthread was that in unsafe Rust this would not be a problem because it does not have strict aliasing and my argument that it still is would be because of non-value representations.

show 1 reply