4 ms·
The premise of the Rust half of the article makes no sense. 'Rust has more rules' is not true, references have more rules, and in unsafe code, you aren't using
by pie_flavor 2y ago
The premise of the Rust half of the article makes no sense. 'Rust has more rules' is not true, references have more rules, and in unsafe code, you aren't using them very much. Comparing the rules that apply to references in Rust to the rules that apply to raw pointers in C and Zig is nonsensical: if you transliterate the Zig code to Rust, no new problems appear! 'What if I create a reference' is easily solved by not creating a reference, just as you are not creating a reference in the Zig code (because Zig doesn't have them). Every problem on Rust's end was just trying to use references instead of pointers. The article then trumpets Zig's tracing allocator as a unique benefit, even though you can do the exact same thing in Rust.
- 3836293648 2y ago> What if I create a referecnce is easily solved by not creating a reference Except it isn't easy. Rust implicitly creates references constantly and in unsafe code it may be UB for those to exist. It's why Rust has all the crazy offsetof macros and such because you can't reliably do the obvious &raw (*struct_pointer).field
- SkiFire13 2y agoI guess you meant the `addr_of!`/`addr_of_mu!` macros? Those have since been given proper syntax with `&raw` and `&raw mut` expressions.
- NobodyNada 2y ago> &raw (*struct_pointer).field This is not correct -- dereferencing a raw pointer does not implicitly create a reference. That code snippet is perfectly valid as long as the underlying pointer arithmetic is valid. See the Rust reference on "Behaviors considered undefined": [0] > Accessing (loading from or storing to) a place that is dangling or based on a misaligned pointer. No problem here, dereferencing a raw pointer creates a place expression but we do not load or store from it. > Performing a place projection that violates the requirements of in-bounds pointer arithmetic [1]. A place projection is a field expression, a tuple index expression, or an array/slice index expression. Alright, so we're doing place projection. Let's check the link to see the requirements for in-bounds pointer arithmetic: > The offset in bytes, computed on mathematical integers (without “wrapping around”), must fit in an isize. > If the computed offset is non-zero, then [the base pointer] must be derived from a pointer to some allocated object, and the entire memory range between [the base pointer] and the result must be in bounds of that allocated object. In particular, this range must not “wrap around” the edge of the address space. Okay, so your "obvious" snippet is sound as long as struct_pointer points to valid memory that's at least big enough to contain the field offset you're accessing. There's no rules about aliasing, or even alignment. These semantics are more or less the same as the equivalent C code. They might even be slightly more relaxed, since I don't recall if C has requirements on alignment or strict aliasing when doing pointer projections. I have no idea what Zig's requirements are -- I spent about a half hour searching and couldn't find any documentation or discussion on whether and when pointer projection, or even just pointer arithmetic, can lead to undefined behavior in Zig. I'd be pretty uncomfortable writing pointer heavy code in Zig when I can't find documentation or even a GitHub issue on whether basic pointer operations can trigger UB or not. [0]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html https://doc.rust-lang.org/reference/behavior-considered-unde... [1]: https://doc.rust-lang.org/std/primitive.pointer.html#method.offset https://doc.rust-lang.org/std/primitive.pointer.html#method....