5 ms·
This seems weak. In a language like Rust, the compiler will “lock” the pointers for you, and you can’t forget. In a language like C++ (and presumably Zig), on
by amluto 1mo ago
This seems weak.
In a language like Rust, the compiler will “lock” the pointers for you, and you can’t forget.
In a language like C++ (and presumably Zig), one could, in theory at least, have the iterators and slices that reference the storage of a dynamic array hold some sort of lock that pins the storage.
But this API requires the programmer to remember to lock the pointers and also requires the programmer to keep the lock alive for the correct region of code. And it looks to me like even the example in the blog post has the lock taken completely outside the function that requires stability, so there is nothing whatsoever that gets the lock scoping right. Even the type system can’t help — the offending parse function can’t declare that it wants a pointer-locked ArrayList parameter.
- pron 1mo agoI reach for a low-level language only when I want low-level control over what operations happen and when, what memory is used and when etc.. At present, no language offers me this control and safety at the same time. With Rust, when I need such control (which is always, otherwise I would use a higher-level language), I need to give up safety, anyway, at which point I have no safety and the complexity of a language that offers safety. So right now, when we want control, we need to give up some safety, but weaker things are still helpful. Also, in low-level code, the problem of "I might forget to do something" sometimes clashes with the problem of "I need to see exactly what operations are done and where". Various kinds of implicitness help with the former at the expense of the latter. I'm not saying this is universally better than other approaches, but many people who do serious low-level programming would prefer this.
- pjmlp 1mo agoExcept the point that Zig should do better than Object Pascal, Modula-2, with solutions already available on Insure++ and friends for use after free, 30 years ago.
- duped 1mo agoWhat are some examples of things you "always" need that require unsafe Rust?
- yefol 1mo ago[dead]
- afdbcreid 1mo ago> for instance by causing a stack overflow That's not "for instance", that's literally the only place Rust has unfixable UB on embedded (code on OS has other such things, e.g. reading/writing to `/proc/self/mem`). > projects that need performance often use unsafe You'll be surprised to hear how often it's not needed at all. And when it is, you'll be surprised to hear how many times you can still avoid it with some tricks. Contrary to popular belief, performance isn't the most common reason for unsafe (FFI probably is).
- insanitybit 1mo agoI haven't needed `unsafe` for performance since crates like zerocopy etc exist. It's been years, and I've worked hard to shave nanoseconds off of code, using valgrind to measure single digit changes to branch predictions.
- delamon 1mo agoObjects belonging to multiple double-linked lists at the same time. Easily done with intrusive lists. Safe rust would require Rc/Arc: penalty both on memory usage and cpu time.
- xeonmc 1mo agoThose who would give up low-level control to purchase a little memory safety, deserve neither control nor safety.” - Benjamin Franklin, or something like that
- slopinthebag 1mo agoBut the point of unsafe {} in Rust is not that you should never use it, it's that it creates a clear boundary between code that is safe and the code that needs that lower level control. In other languages, everything is inside an unsafe block. If everything you do requires such low level control over every allocation and access, it sounds like you should be using assembly.
- uecker 1mo agoWhile I think this is a good idea, I think this the importance is massively exaggerated. Not everything in other languages is unsafe, there are also different features one can distinguish where some are safe and some are not. It is not as clearly labelled and a set of features one must screen for instead of one keyword, but pretending this then makes it everything unsafe is disingenuous. At the same time, the distinction is Rust is also not always that clear, as the correctness of the unsafe block may depend on logic outside of the block while soundness of the safe parts may be compromised by issues in the unsafe blocks.
- pocksuppet 27d agoWhat is the benefit of having a boundary?
- afdbcreid 1mo ago> With Rust, when I need such control (which is always, otherwise I would use a higher-level language), I need to give up safety, anyway, at which point I have no safety and the complexity of a language that offers safety. This is a very, very, very common claim. And unfortunately I have no other way to describe it other than a strawman. In 95% (at least) of the application that need systems programming (not to talk about all applications that don't necessarily need it but will benefit from the performance and it wasn't an option because C++ wasn't an option), you have at most 20% (wildly overestimating) of code that needs to be unsafe. The rest could be completely safe. And amongst code that must be unsafe, you can very commonly encapsulate it in some safe pattern. Many times even extract it to a reusable crate. That is the point of Rust. Not avoiding unsafety, but limiting and encapsulating it. And evidence proves that to work (for example https://blog.google/security/rust-in-android-move-fast-fix-things/ https://blog.google/security/rust-in-android-move-fast-fix-t...).
- yefol 1mo ago[flagged]
- dwattttt 1mo agoI'm not super certain you're interested in answers, but assuming good faith: > https://github.com/rust-lang/rust/blob/main/library/core/src https://github.com/rust-lang/rust/blob/main/library/core/src... How large a percentage of the logic code there is inside of an unsafe block? The claim isn't "there's no unsafe". You've linked one file out of an entire stdlib; it uses unsafe to implement its algorithm, and of all the Rust code that could exist, this has one of the highest requirements for being maximally performant. Now if you'd said "most of the Rust std library is unsafe", or "most Rust code is unsafe, you'd have a good rebuttal. But that's not the case. > And, if you have an unsafe block that is 100% correct, but it relies on safe code being correct, do you need to vet all that safe code? Potentially whole modules needing to be vetted? Then the unsafe block is not 100% correct. I can slap a wrapper around memcpy and call it "safe", and say that if anyone passes wrong parameters it's their fault. Rust as a language says I'm at fault for saying it's safe though. > Is unsafe Rust code generally harder to get correct than code in other languages, due to... Harder than other systems programming languages? Having worked in a fair few, I disagree. Harder than "higher" level languages? Some of them yes, some of them no; I've seen "simple" languages admit very poor architectures, and fall in a "safe" heap when the project has to grow. > Do Rust libraries, including std, historically have had UB bugs? https://materialize.com/blog/rust-concurrency-bug-unbounded- https://materialize.com/blog/rust-concurrency-bug-unbounded-... Are you suggesting this is a bar a language should achieve? Some examples of this would be interesting. As for the rest, I don't think anything meets this bar you're setting. Certainly not languages that would otherwise be used where Rust is.
- surajrmal 1mo agoI've written systems level code (drivers and os code) for years and outside of ffi, I've managed to go on year long stretches without touching unsafe. It's really not a commonly needed tool in a well architected code base with good libraries to encapsulate common reasons it might otherwise be necessary. And we don't really consider using unsafe taboo, it's just not necessary.
- Someone 1mo agoI agree. https://news.ycombinator.com/item?id=49501582 https://news.ycombinator.com/item?id=49501582 says: “I use it in a lot of places where I know the max capacity ahead of time -- ensureCapacity() followed by a lot of AssumeCapacity()-styled commands. It's convenient for all of the ... convenience ... methods (append() requires some bookkeeping somewhere, appendSlice() requires more, and so on). In those usages, it's basically syntactic sugar over a slice”* I suspect “where I know the max capacity ahead of time” covers most if not all use cases (if it you use this without knowing max capacity, you either accept your code may panic, or you do some unlock, grow, lock again dance when you discover your initial estimate is wrong) If so, wouldn’t adding a growable container where you specify capacity at construction time and removing access to the internal pointers of ArrayList be a better way to handle this?
- frmdstryr 1mo agoDo any languages have a notion of "relative pointers"? So in the example if instead of appending "line" as ptr & len, it'd instead be appending an offset & len which could in theory be used to safely compute the actual location even with relocations.
- Someone 1mo agoIf you squeeze your eyes a bit, C compilers for Windows used to have them, with far pointers (https://en.wikipedia.org/wiki/Far_pointer https://en.wikipedia.org/wiki/Far_pointer) Similarly, CPU architectures that use descriptors can (have to?) have languages with that notion.
- sparkie 1mo agoThe FS and GS segment selectors are still used in x86-64, typically for `thread_local` storage, but they can be repurposed. `thread_local` is an example of a "relative pointer" though. Instructions to access the thread local are prefixed with `fs:` or `gs:`, and point relative to the address in the respective segment register.
- pocksuppet 27d agoThat's the same as any other index or member access. It's myThreadLocalBlock->myVariable. thread_local is an example of something else unusual though - a struct linker as seen in https://yosefk.com/blog/i-want-a-struct-linker.html https://yosefk.com/blog/i-want-a-struct-linker.html and it even supports dynamic loading.
- frmdstryr 1mo agoAfter more searching I found this article https://www.gingerbill.org/article/2020/05/17/relative-pointers/ https://www.gingerbill.org/article/2020/05/17/relative-point... A far pointer sounds like the global based pointer described in that article. The far pointer Wikipedia article says they are problematic but doesn't give much reasoning as to why.
- slopinthebag 1mo agoThis is how it is with languages which provide less guarantees than Rust. Sure you can try to hold all the invariants and restrictions in your head, but a sufficiently advanced compiler can do this for you without the possibility of making mistakes. I have no idea why people claim that's too restrictive - if you're not enforcing those rules manually you're just setting yourself up for issues down the road.
- insanitybit 1mo ago2026 and developers still use memory unsafe languages. I hope we get regulated at this point, disgusting.
- mirashii 1mo agoTo make matters worse, there’s also a weaker documentation problem. Where should one learn that they need to do this? zig.guide’s page on ArrayList doesn’t mention it. https://ziglang.org/documentation/master/std/#std.ArrayList https://ziglang.org/documentation/master/std/#std.ArrayList doesn’t mention it, https://ziglang.org/documentation/master/std/#std.ArrayList https://ziglang.org/documentation/master/std/#std.ArrayList doesn’t mention it at the top level, just a method in the midst of dozens of other methods. I honestly don’t know how one is meant to discover this outside of random blog posts.
- csande17 1mo agoThe devlog is the very first place changes get written about when they land in Zig's master branch (and sometimes even before!), so presumably zig.guide will mention this change once it actually makes it into a release.
- Meneth 1mo agoIdeally, the documentation changes would have been merged together with the code changes. In practice, Zig has very poor documentation overall.
- hiccuphippo 1mo agoThe documentation is the most 0.x piece of Zig. It will come but it will take time.