7 ms·
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 bet
by pron 3mo ago
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.
- saghm 3mo ago> 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".
- pron 3mo ago> 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.
- saghm 3mo ago> 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.
- duped 3mo agoPeople find it immensely useful in practice, though.
- pron 3mo agoThey find it immensely useful in practice only when the safe subset is useful. In C, you could say that the same definition of memory-safety exists, only the safe subset is empty, and in that case people don't find the fact that C could be described as memory-safe in that way useful at all. And that's exactly my point. The safe subset of Rust doesn't sufficiently cover the very things that I choose a low-level language for in the first place, and the parts it does cover I can do at least as well in even safer high-level languages. Now, I'm not saying there aren't programs where Rust's precise mix of safety and unsafety is better than the alternatives. For example, I've never written a browser rendering engine, and it's possible that I would find Rust to be the best fit for that task. I don't know that I would, but I also have no experience with that domain to suggest that I wouldn't.
- duped 3mo agoYou don't find it useful that use after free, double free, uninitialized memory, and many kinds of race conditions are just impossible in code that compiles? What exactly is the low level subset you feel like you can't use?
- pron 3mo ago> You don't find it useful that use after free, double free, uninitialized memory, and many kinds of race conditions are just impossible in code that compiles? Sure, but memory safety by itself is not the reason to pick Rust because other languages do memory safety even better. > What exactly is the low level subset you feel like you can't use? The things that make me want to use a low-level language in the first place, such as controlling exactly when memory is allocated and freed and where exactly objects are placed in memory. When I don't need to do these things and all I want is memory safety and performance, then I already have better options.
- CJefferson 3mo agoDo you find most of your rust code is unsafe? Because I also find I do some unsafe stuff, because of the algorithms I work on I often end up with some unchecked array accesses and a couple of raw pointers into those arrays I pass around. But 98% of the code is safe and I find this makes it easier to reason about.
- imtringued 3mo agoYes, it's pron. Pron works on a JVM so he looks at everything from a language runtime lens. To him, the entire code base might as well be unsafe. The argument that you can contain unsafe in safe abstractions does not interest him, because of the nature of the projects he works on.
- pron 3mo ago> To him, the entire code base might as well be unsafe. Not at all. I would very much like the code to be safe, it's just that I reach for a low level language to get the thing that low-level languages are designed to offer me, which is control, and no language offers control and safety at the same time. So when the interesting parts of the code could be written in safe Rust, I have to give up control, and in that case I'd rather use a more convenient language that doesn't give me full control. And when the interesting parts of the code need full control, Rust doesn't give me safety anyway, and I still pay for its complexity. As to encapsulating unsafe, that doesn't help at all if the most tricky parts of the code are inside. What happens there is that Rust makes the hard parts harder and the easy parts easier, and for me that's a net negative.
- pron 3mo agoP.S. And that brings me back to the universality point, that you're actually repeating, so let me explain it again. All programming languages bring a certain aesthetic that appeals to some and repels others within their intended domain. For example, I prefer Java to C# and Kotlin because I place a value on language simplicity, but I'm well aware that some other people like a lot of convenience features and they have the opposite preferences. I don't expect everyone to like Java even among those who work in the domains in which it is intended. For the same reason, I prefer Haskell over Scala and Clojure to Common Lisp, yet I fully recognise there are those who have the opposite preference. Yet when people say they don't like Rust, the reaction among those who do is often one of: you don't want it to work, you don't care about correctness, your situation is special, or you just don't get it. I.e. they expect Rust to be universally liked unless there's a some good exceptional reason not to. But this is not the case for any language, let alone a language as complicated and as rich as Rust, which is certain to evoke a strong aesthetic reaction either for or against. So I have a long, long record of working with low level languages, I have a long record of working with formal methods and studying software correctness in general, I've worked extensively on safety-critical and mission critical systems, and I find Rust unappealing. There is nothing that should be surprising about that, there is nothing special about Rust or any other language that should lead anyone to expect it to be universally liked among those in the domains for which it is intended, and indeed, it is not the case for Rust as it is not the case for any other language. This amazement that quite a few people, even those with the relevant expertise, don't like your favourite language is exactly this sense of universality that I find annoying. That some people get it yet don't want to choose a language is the case for Java, it's the case for Haskell, it's the case for Zig, and it's the case for Rust. Some people who really care about writing correct low-level code will have good reasons to choose Rust over other languages, while others who really care about writing correct low-level code will have equally good reasons to choose other languages over Rust. It's not because our programs are special, but it's because we think we can do it better with other languages. That's just the reality of all programming languages ever made, and that's what I mean by no universality. There is no external, objective requirement for any program that makes any (general purpose) language objectively best for that program. Choices always involve some kind of personal aesthetic preference. That your favourite language isn't "objectively best" and isn't universally preferred even among those who care about the things you care about isn't something that should bother you, and pointing out this simple fact isn't trolling. It's something you should expect, because it's always true.
- gf000 3mo agoBut unsafe Rust is still considerably safer than C (not sure about how it stands up to Zig, though)