5 ms·
If you must write unsafe code, what's wrong with just dropping down to unsafe in Rust when you need to? You have all the power unsafe provides, and you have a s
by bobbylarrybobby 2y ago
If you must write unsafe code, what's wrong with just dropping down to unsafe in Rust when you need to? You have all the power unsafe provides, and you have a smaller surface area to audit than if your entire codebase resides in one big unsafe block.
- chrisco255 2y agoUnsafe Rust is problematic: https://zackoverflow.dev/writing/unsafe-rust-vs-zig https://zackoverflow.dev/writing/unsafe-rust-vs-zig See also: https://github.com/roc-lang/roc/blob/main/www/content/faq.md#why-does-roc-use-both-rust-and-zig-rust-and-zig https://github.com/roc-lang/roc/blob/main/www/content/faq.md... Zig is not entirely unsafe. It provides quite a few compile time checks and primitives to catch memory leaks or prevent them altogether.
- oneshtein 2y agoYes, unsafe code is problematic in Rust, C, C++, etc. Is Zig different?
- mk12 2y agoIt’s harder to write correct unsafe Rust than correct Zig because (1) Rust uses references all over the place, but when writing unsafe code you must scrupulously avoid “producing” an invalid reference (even if you never deference it), and (2) there’s lots of syntax noise which obscures what the code is doing (though &raw is a step in the right direction).
- zozbot234 2y ago> Rust uses references all over the place This is mostly a concern with the Rust stdlib, though. And it's in principle fixable, by writing new varieties of those stdlib functions that take raw-pointer or &UnsafeCell<...> arguments, and delegating the "safe" varieties to those.
- kprotty 2y agoThere's compiler-level traits like `Iterator` and `Future` which enforce references. If wanting to do intrusive pointers into them, one risks creating overlapping references: https://github.com/tokio-rs/tokio/issues/3399 https://github.com/tokio-rs/tokio/issues/3399
- zozbot234 2y agoReferences to UnsafeCell<> should still be safe, because the only thing you can do with an &UnsafeCell<T> is extract a possibly-mutating raw pointer to T. (UnsafeCell<> is also special in that, like Cell<>, you can mutate through it without incurring UB.)
- oneshtein 2y agoFor Rust references, rules[0] are not hard to follow: The pointer must be properly aligned. It must be non-null. It must be “dereferenceable”: a pointer is dereferenceable if the memory range of the given size starting at the pointer is entirely contained within the bounds of that allocated object. Note that in Rust, every (stack-allocated) variable is considered a separate allocated object. The pointer must point to a valid value of type T. When creating a mutable reference, then while this reference exists, the memory it points to must not get accessed (read or written) through any other pointer or reference not derived from this reference. When creating a shared reference, then while this reference exists, the memory it points to must not get mutated (except inside UnsafeCell). [0]: https://doc.rust-lang.org/stable/core/ptr/index.html#pointer-to-reference-conversion https://doc.rust-lang.org/stable/core/ptr/index.html#pointer...
- mk12 2y agoOne reason it’s harder to follow is you can’t have references to uninitialized memory. In Zig pointers to uninitialized memory are fine as long as you don’t dereference them. That’s also true of Rust’s raw pointers, but most Rust code uses references, so it can’t be reused in unsafe contexts. As a concrete example, I previously used Vec in unsafe code that dealt with uninitialized memory. This should be fine because Vec is basically a raw pointer and two integers. But later they changed the docs to say that this was undefined behavior (essentially, Vec reserves the right to “produce” a reference whenever it wants, even if you avoid calling methods that would do that). So my code that previously followed the rules now appeared to violate them.
- oneshtein 2y ago> you can’t have references to uninitialized memory. The method is available[0] in nightly Rust pub const unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit<T>> where T: Sized, { // SAFETY: the caller must guarantee that `self` meets all the // requirements for a reference. if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit<T>) }) } } [0]: https://doc.rust-lang.org/stable/core/primitive.pointer.html#method.as_uninit_ref-1 https://doc.rust-lang.org/stable/core/primitive.pointer.html...
- zamalek 2y agoThis is precisely the myth that the article talks about. Miri finds significantly more UB in unsafe Rust than Zig's checks do. Even if it weren't, this exaggeration is a complete theater. You aren't supposed to use unsafe Rust unless you really have to. I have been using Rust since 2020 and I've used it once, for 3 lines of code. The entirety of all Zig codebases is unsafe. That's fine if you are fine with unsafe code, but this myth is dishonest, and I take great issue with using a language where the founder is the primary source of the dishonesty - because what else is being swept under the rug?
- throwawaymaths 2y agoyes but by the time you're using miri, why not just run zig with a separate static checker that does all the memory safety parts? https://github.com/ityonemo/clr https://github.com/ityonemo/clr
- pcwalton 2y agoFor one, it doesn't do all the "memory safety parts", according to the readme. I'm very skeptical that Zig can be made memory safe with a checker while still remaining compatible with existing code. Certainly neither C nor C++ can, and Zig isn't meaningfully different in expressivity (if anything, it's more expressive, which is the opposite of what you want).
- throwawaymaths 2y agoFTrepo: Q: You didn't do X, so Zig will never be able to track X A: Maybe. Only way to know for sure is to fork this (or, hopefully, a 'real' successor) and fail. However, consider that "trivially" it should be possible to externally annotate every zig file with lifetime/type annotations identical to that of Rust and run "exactly the same" analysis as Rust and get the same memory safety as Rust. it appears the clr author anticipated you: you didnt fork it, try, and fail, so you have ceded the authority to credibly make your speculative complaint > Zig isn't meaningfully different in expressivity it is meaningfully different in expressivity at the AIR level. AIR looks nothing like c, c++, zig, or rust.
- pcwalton 2y ago> It provides quite a few compile time checks and primitives to catch memory leaks or prevent them altogether. From what I've seen, clang has all of these and more for C++. If your metric is "tooling to help you catch UB", C++ is significantly superior to Zig.
- chrisco255 2y agoZig has a C and C++ compiler built into it and works seamlessly with it. Several C/C++ projects use Zig as a build tool. Zig makes different trade-offs with C++ from a language design standpoint. C++ has a lot more footguns to create UB in the first place.
- pcwalton 2y ago> C++ has a lot more footguns to create UB in the first place. I'd actually give the edge to C++ over Zig, because of smart pointers (not that I'm implying smart pointers are anywhere near sufficient).
- brabel 2y agoWTH they were talking about Rust and Zig, they did not even mention C++ and you come with "if your metrics is blah then C++ is superior, checkmate!", completely ignoring C++ is a monster of complexity while Zig is basically simple as C.
- Ygg2 2y agoIf you present an argument that you like X in a thing so you picked B, and A exist that's more X than B, it means your argument is partially (you like X and Z) or totally (you like Y) wrong. In this context of, if you are using Zig for its safety via tooling, there is a much more mature candidate C++.
- brabel 2y agoThat's exactly what I was criticizing: you just make the unfounded assumption that "argument that you like X" is the only thing that matters, and the debate is not only about X in the context of languages A and B. Introducing C to the debate is stupid, as then the obvious answer is just "but C has Y which is horrile" and so on.
- dolmen 2y agoIn related news, someone just published a PoC borrow checker for Zig: https://news.ycombinator.com/item?id=42923829 https://news.ycombinator.com/item?id=42923829
- ulbu 2y agothe barrier between unsafe and safe has additional rules. it’s not “just dropping to unsafe” – you need to make sure you leave it safely.