FWIW, my personal lessons here is that good API design can’t prevent people from writing bad code. API-design-wise, Rust is great! It is very pedantic about what are strings, what are bytes, and what are OS-dependent paths. And the API SCREAMS at you if you use the wrong thing.
Like
// ra, rb are &[u8], raw bytes from the input files.
print!("{}", String::from_utf8_lossy(ra));
print!("{delim}{}", String::from_utf8_lossy(rb));
Who would’ve write that?! The only way this could be more obviously wrong is if your terminal gave an audible beep if you’d type that, and computer rebooted angrily. https://www.cve.org/CVERecord?id=CVE-2026-35375 is the same level of obviousness of brokenness.
But, yeah, a lot of people do routinely write code like that. And people who don’t, arguably, don’t benefit that much from extra API type-safety.
I would still say that, on the margin, appropriate API salt & sugar can help, but that is surprisingly less effective than one would think.
It seems plausible that Zig’s transparent treatment of paths as bytes makes Zig programs more correct on Unix, but I am not sure if that just doesn’t exchange some bugs for others.
Eg, if I run zig fetch non-ascii-bytes, it sends an HTTP request with invalid URL (so, violating the protocol, as far as I understand), instead of rejecting this early. Similarly, I’d be surprised if there are no subtle bugs with Zig’s making wft8 on windows visible to the users.