Live data from Hacker News

How Our Rust-to-Zig Rewrite Is Going

rtfeldman.com

61–70 of 336 posts

Re: How Our Rust-to-Zig Rewrite Is Going

#61

Zig's incremental builds are DEFINITELY a killer feature. In the short term, I could see why you'd make a switch to get it. But, in the medium term, can we really not expect to see this in Rust in the somewhat near future? I want to go fast, but I don't want to go fast just to shoot my foot off. If only somehow we could get Rust's safety with all of Zig's features and Go's runtime without GC... That's what I'm workin…

Rust's compile times will get faster long before Zig gets safer.

Re: How Our Rust-to-Zig Rewrite Is Going

#62

I think this is a fine post. But one comment: > remember that for compilers which emit machine code, like roc and rustc, doing memory-unsafe things is a big part of the job I don't really think that this is true, in the way that it's written. I think that for the hot binary patching / code reloading features, yes, that is going to need unsafe. But for regular old "producing an executable" compilation? Emitting machin…

I agree that it’s not inherent to emitting machine code but I do think it reflects a different set of priorities. In extremely high performance code you use different data structures and algorithms and change your approach to memory allocation. TigerBeetle famously does all memory allocation once on startup. Roc is attempting to make a similar set of trade-offs in their compiler as Zig, so it makes sense that the aut…

I do think it reflects different priorities, but one of those differences is that from my perspective, safety and performance are not inherently at odds. Yes, sometimes it is needed, but not as much as some people seem to think. Sometimes, it also means writing code in ways that communicate things to the compiler that you may not think of if you're not used to thinking in this manner.

A lot of the ways in which the zig compiler works doesn't use pointers, it uses indices. This stuff is easier to write as safe code, not less easy.

> Roc is attempting to make a similar set of trade-offs in their compiler as Zig, so it makes sense that the author finds many shared patterns.

I do think that that makes sense, but it also doesn't mean that they have to. I am doing a compiler project that takes a lot of inspiration from Zig (as my language currently inherits some major things from Zig, and I also care a lot about compiler performance) and it's written in Rust, and does not use much unsafe code (outside of the usual suspects of FFI in the runtime, etc).

Re: How Our Rust-to-Zig Rewrite Is Going

#63
post #49

Earlier quoted context omitted.

It's impossible to add a borrow checker to any existing language. The reason Rust has a working borrow checker is because every part of the language from structs, enum, traits, generics and all the way to the syntax itself has been designed to support lifetimes and borrow checking. It's is not something you can just tack on to an existing language without fundamentally changing it.

I wouldn't say it's impossible, rather un-ergonomic. TypeScript can add type information to ordinary JavaScript code via JSDoc comments; the result can both be executed as ordinary JavaScript as-is and type-checked with TypeScript. But it's a huge pain to try to write (and maintain) everything that way, it was supported as a hack to help migrate legacy codebases. You could probably take a similar "the lifetimes are e…

That is possible (clang has experimental lifetime annotations support), but that is not enough to guarantee memory safety.

As a simple example, Zig has no private fields. That makes encapsulating any unsafety impossible.

Re: How Our Rust-to-Zig Rewrite Is Going

#64
While I'm a rust enthusiast, I do agree that certain languages lend themselves well to particular domains. So a rewrite from Rust to something better suited is fine by me. In fact, while I do work on a rust project, I would not have and still would not recommend it as the choice for that particular project.

That being said, I had to do some double takes while reading this.

> https://rtfeldman.com/rust-to-zig#memory-safety-post-rewrite

I feel that it's a bit weird to compare a rather well tested 7 (?) year old rust implementation with a brand new not yet released less than a year old Zig implementation. Without that context, this looks like a bad comparison for rust, when it is in fact the complete opposite.

> https://rtfeldman.com/rust-to-zig#build-times

The swiftness of the Zig compilere here is insane, and would would very much shift my recommendation of Rust if it got to similar speeds.

That being said, I do find it funny that currently, the compilation speed is actually worse on Zig than Rust, despite Zig (anonymous commenters at least tbf) claiming the opposite for years.

How did you eventually discover the 35 ms figure for Roc? Did you have to temporarily update the codebase to 0.17?

> https://rtfeldman.com/rust-to-zig#memory-control-zero-parse-...

Nothing negative here. I did play around with implementing a scripting language in this DOD-ish, index-based paradigm and yeah, it is neat.

I was thinking that it might be possible to do resumable computation across the network like this (in the context of frontend frameworks "resuming" UIs), but ultimately I have no use for this so just the experience itself was enough.

One note here is that it does tend to break completely if non-pointer-free data is introduced. It seems like it's either all or nothing.

> https://rtfeldman.com/rust-to-zig#ecosystem-relevance

This is more of an LLVM thing, which is fair, but I find it funny that "LLVM unstable bad" while "Zig unstable whatever".

Overall though, this was an interesting read. And if the folks contributing to roc like zig then more power to them.

Last thing, the link here is broken (points to a TODO):

> Zig's compiler itself is another

Re: How Our Rust-to-Zig Rewrite Is Going

#65
post #28

Earlier quoted context omitted.

Yeah that is definitely 1000% wrong. A compiler can do its job with totally abstract data structures. If anything would need to do unsafe stuff in memory, it would probably be a linker.

> probably be a linker I don't think that's any different either. The core job of linking isn't particularly unsafe. (Unless, similarly, you're doing the hot reloading stuff)

I've noticed that people equate "low level stuff" with unsafe, regardless of whether it's contextually justified.

Re: How Our Rust-to-Zig Rewrite Is Going

#66

Earlier quoted context omitted.

Rust moved away from OCaml when it decided to be re-written in Rust. The post alludes to this as being a usual time for a wholesale re-write, and I'd agree.

I appreciate the insight, and on closer reading the post clearly states that realistically only Zig and Rust were ever considered anyway. Since you're here, could you comment on the approach Rust took in their rewrite? Was it more of a straight translation like Go did when they self hosted -- similar to the recent Bun transliteration? Or were there architectural changes made along the way like this article describes…

The Rust re-write happened before I got involved. If pcwalton is around and sees this comment, maybe he can provide a more first-class account.

> Was it more of a straight translation like Go did when they self hosted -- similar to the recent Bun transliteration? Or were there architectural changes made along the way like this article describes with Roc?

From what I remember, it was a whole-sale re-write from scratch, not a transliteration. While Rust took a lot of inspiration from OCaml, especially in those days, it was different enough that I'm not sure that a more direct transliteration would have been particularly possible, though again, see above, I wasn't there, so I don't know for sure.

Re: How Our Rust-to-Zig Rewrite Is Going

#67

Zig is a pre-1.0 language while Rust is post-1.0. This alone is settles which one to pick for may developers. The library support is probably favours Rust too. Rust build times are much slower than Zig, I get that, but I rarely optimize software for build times.

Zig is not pre-1.0 because it’s not ready for production (bugs or missing features), it’s pre-1.0 because they want to be able to make breaking language changes. Nowadays when you can just point an agent at release notes and have it update everything, I actually prefer not having to wait through rare major releases to get new language features.

> Nowadays when you can just point an agent at release notes and have it update everything

Except that means that not only you lose compiler bugfixes, you also pretty much has no access to the ecosystem. For most production codebases, this is a deal breaker.

Re: How Our Rust-to-Zig Rewrite Is Going

#68
post #5

Earlier quoted context omitted.

Layperson here: what is special about Go's runtime, aside from the GC?

It's literally the most sophisticated scheduling engine in the world. In practice, Go can typically outperform Rust in throughput (using more memory), despite having a mountain of disadvantages against it in theory. That's how good the Go scheduler/runtime is.

I think this is interesting and warrants explanation. There are cases where a GC can be faster (sort of, Arenas get you most of the gains) but "the most sophisticated scheduling engine in the world" should be easy to at least partially support.

Re: How Our Rust-to-Zig Rewrite Is Going

#69
post #25

Earlier quoted context omitted.

It's literally the most sophisticated scheduling engine in the world. In practice, Go can typically outperform Rust in throughput (using more memory), despite having a mountain of disadvantages against it in theory. That's how good the Go scheduler/runtime is.

This is the first I've heard anyone claim higher throughput for Go than Rust. Any articles you'd point to to learn more?

I think one of the few performance benefits with a GC is that you can defer allocations. You can do that in Rust too though.

Re: How Our Rust-to-Zig Rewrite Is Going

#70
Nitpicking ahead:

I am not sure, but there might be a bug in their pattern matching example.

What happens if 'verb' is "GET" and 'path' is "/users/1234/posts/1234/extra_path/and/more/"? Will 'post_id' become "extra_path/and/more/"?

I tried running it in the sandbox, and it does indeed seem to buggily result in:

"Post ID: 1234/extra_path/and/more"

I suspect that the reason it is behaving like it is, is due to how it handles characters in the string literal. The example program exploits that only the slashes present in the string literal pattern are matched, to enable matching on 'page' having slashes. But then in the nested 'match', it forgot to account for any possible extra slashes.

Nitpicking end.

I have not read the whole post yet, but the pattern matching not requiring any allocations, seems very nice. The string literal patterns also seem interesting, though I am not completely sold on them, also as per the above possible bug. It seems really clean in some ways, but the specific semantics, I am not fully sure about. Maybe it is excellent, and is so clean and concise that it is overall less bug-prone than alternatives in other programming languages. I do not know.

Post reply on HN