That framing may seem intellectually satisfying, but it's not useful in practice. Consider the extreme edge case of C: We can clearly mechanically delineate between the empty program and a non-empty one, we call the empty program safe and any program that isn't empty unsafe (i.e. C is memory-safe if you want to do nothing and not if you want to do anything). And so, we also have this property that in C you can't do anything unsafe without noticing.
Now, that's ridiculous, but something not too different happens to me with Rust. I reach for a low-level language when I want to do low-level things in a more convenient way than in Java, but the very things that would make me reach for a low-level language in the first place are unsafe in Rust. So in ~100% of the programs I want to write in a low-level language, Rust and Zig offer the same level of memory safety (but I need to pay a higher price for Rust). That Rust reminds me that what I want to do is unsafe doesn't help me.
Of course, other people may want to reach for a low-level language in other situations and their perspective could be different, but if I pay the price and get little in return I can't see how that would be "table stakes". Table stakes imply some universality that is obviously not here.
> That framing may seem intellectually satisfying, but it's not useful in practice.
Honestly, that's exactly how I feel in reverse. The framing you gave is more intellectually interesting, but it doesn't help explain the actual real-world outcomes where in practice, Rust and Java both don't have much problem with unsafety, whereas C does, and at least from what I've heard, Zig does as well.
> I reach for a low-level language when I want to do low-level things in a more convenient way than in Java, but the very things that would make me reach for a low-level language in the first place are unsafe in Rust. So in ~100% of the programs I want to write in a low-level language, Rust and Zig offer the same level of memory safety (but I need to pay a higher price for Rust). That Rust reminds me that what I want to do is unsafe doesn't help me.
I mean, sure, if you want to do things that are fundamentally not possible to validate because you think you're smart enough not to screw up, that's going to make Rust a tough sell. My issue with it is that history has shown that the best C and C++ programmers in the world still write code where memory safety rears its head, so I'm distrustful of the claim that being smart and diligent is enough to prevent the sort of bugs that we're still dealing with after half a century of us learning how not to write C. You need to have an excess of either talent or hubris to consider that a reasonably safe path, and given that the amount of talent needed is a lot higher than the amount of hubris, it seems way more likely that it's the latter.
The alternative is just learning how to write code that doesn't require expressing things in a way that can't be validated. While there are some things that fundamentally are not possible to, I'm dubious that it's anywhere close to as high as you seem to expect if your experience is that you literally can't reduce the amount of unsafe code you need in Rust below "literally my entire program is unsafe".
> Rust and Java both don't have much problem with unsafety, whereas C does, and at least from what I've heard, Zig does as well.
I'm not interested in the definition so much as I am in calling it "table stakes", and so the fact that these languages satisfy their promises is uninteresting in isolation. What matters is the value of their promises. The majority of Rust programs I see, I wouldn't have written in a low-level language, so the fact that it offers memory safety for the things I don't need it to do does nothing for me.
Now, clearly, Rust's originators didn't consider what Java offers (or at least what it offered 20 years ago when Rust was first conceived) to be table stakes or they wouldn't have wanted Rust. Java exacted some price in exchange for its memory safety that was unacceptable to Rust's originators and trumped its memory safety. But the same thing happens with Rust vs Zig. Rust exacts a heavy price for its memory safety, that - just as in Rust's case vs Java - is sometimes unacceptable. So I can't see how any of these could be "table stakes".
> I mean, sure, if you want to do things that are fundamentally not possible to validate because you think you're smart enough not to screw up, that's going to make Rust a tough sell.
What Rust can validate and what can fundamentally be validated are two very, very different things. Compared to what ATS can validate, what Rust can validate is almost indistinguishable from C. In Rust you have to do lots and lots of things that require you to be "smart enough not to screw up" that you could prove in ATS, and still no one (including Rust programmers) would say that what ATS offers is "table stakes" because, obviously, it comes at a high price that the people who choose Rust don't want to pay.
So clearly different languages offer different capabilities and charge a price for them. Sometimes the price is worth it and sometimes it isn't.
> so I'm distrustful of the claim that being smart and diligent is enough to prevent the sort of bugs that we're still dealing with after half a century of us learning how not to write C
But Java or Rust programs still suffer from a lot of bugs that ATS could eliminate, if you're willing to pay the price, and you're clearly unwilling. ATS programmers could say about Rust programmers what you say about C++ programmers. Clearly there's no universal table stakes here.
> I'm not interested in the definition so much as I am in calling it "table stakes", and so the fact that these languages satisfy their promises is uninteresting in isolation. What matters is the value of their promises. The majority of Rust programs I see, I wouldn't have written in a low-level language, so the fact that it offers memory safety for the things I don't need it to do does nothing for me.
I mean, if you're already going to say "I don't want a low level language for anything other than what I can use unsafe for", then of course Rust will seem like overkill. I'd argue that the value of Rust is that it makes low-level viable for a lot of stuff that would otherwise require a lack of memory safety; a lot of it is stuff that might be written in a higher level language, but that's just because relatively few programs are impossible to write in higher level languages. That doesn't mean that the ones that need to be lower level can't be written in Rust though.
> Now, clearly, Rust's originators didn't consider what Java offers (or at least what it offered 20 years ago when Rust was first conceived) to be table stakes or they wouldn't have wanted Rust. Java exacted some price in exchange for its memory safety that was unacceptable to Rust's originators and trumped its memory safety. But the same thing happens with Rust vs Zig. Rust exacts a heavy price for its memory safety, that - just as in Rust's case vs Java - is sometimes unacceptable. So I can't see how any of these could be "table stakes".
Yes, "table stakes" is a value judgment, and one some people will disagree with. The cost for memory safety in Java is performance overhead though, and the cost for memory safety in Rust is not being able to express certain valid things that can't be validated; those are both objectively different from not offering memory safety at all, and my point is that the cases where what you want to express is literally impossible in Rust to do safely while actually being memory safe are pretty rare. There are some cases where what you're trying to do are fundamentally unsafe, in which case you need to use an unsafe block, but that's not anywhere close to the same as removing validation from the entire program. I'm fairly skeptical that you're basing your view that there are so many cases where you want to do something that's guaranteed to be safe but impossible to write in safe Rust on objective criteria, and extremely skeptical that the programs you write are anywhere close to entirely comprised of logic that can't be expressed safely.
> What Rust can validate and what can fundamentally be validated are two very, very different things. Compared to what ATS can validate, what Rust can validate is almost indistinguishable from C. In Rust you have to do lots and lots of things that require you to be "smart enough not to screw up" that you could prove in ATS, and still no one (including Rust programmers) would say that what ATS offers is "table stakes" because, obviously, it comes at a high price that the people who choose Rust don't want to pay.
> So clearly different languages offer different capabilities and charge a price for them. Sometimes the price is worth it and sometimes it isn't.
Sure, no one is disputing that. But that doesn't change the fact that some languages objectively require you to opt into which parts are memory unsafe, and others don't. It's obvious we won't see eye to eye on whether that's table stakes or not, but that's a difference of opinion, and having a different opinion than you isn't literally illogical; I find your take on it to be as hard to understand as mine is to you.
> But Java or Rust programs still suffer from a lot of bugs that ATS could eliminate, if you're willing to pay the price, and you're clearly unwilling. ATS programmers could say about Rust programmers what you say about C++ programmers. Clearly there's no universal table stakes here.
You're again taking an empirical argument as an abstract one and ignoring the real world outcomes that languages produce. You mentioned finding the fact that they actually produce real world software that in practice do not suffer from the class of bugs that C/C++ suffers from uninteresting, and that's fine, but it's meaningful for people who care about software actually getting used in the real world for real things. You seem to be arguing that unless you can eliminate literally the most bugs of any language in existence, then eliminating any bugs by picking a language that eliminates some of them is a useless endeavor. To me, the reasonable thing would be to choose a place to draw the line and say "anything beyond this is too risky, but I'll tolerate anything that's at least this safe", and memory safety is in practice the place I think it makes sense to do. I don't agree at all that not drawing any line at all is the only logical choice in a scenario when there are multiple places to draw it.