5 ms·
I think that Rust's approach to safety -- soundly eliminate UB in safe code -- comes at the high cost of complexity. This affects how easy it is to write custom
by pron 7y ago
I think that Rust's approach to safety -- soundly eliminate UB in safe code -- comes at the high cost of complexity. This affects how easy it is to write custom compilers (very important in the embedded space), but it is also not necessarily the best way to reduce bugs. For some, this cost is acceptable, and I'm sure some people may even welcome the high-level-looking code [1] that Rust and C++ support, but I think there are better ways, ones that are more appealing in low-level ("systems") programming in general and the embedded space in particular: https://news.ycombinator.com/item?id=21970987 https://news.ycombinator.com/item?id=21970987, https://news.ycombinator.com/item?id=22021237 https://news.ycombinator.com/item?id=22021237
Rust is without a doubt a (much) "better C++" but I'm not sure a better C++ is necessarily what systems programming needs most.
[1]: Not that writing that code is as easy as in a high-level language, nor does it offer the same level of abstraction as high-level languages, where changing the details of the implementation does not affect the API and its clients, but it looks high level, or "expressive", on the page.
- alxlaz 7y ago> Rust is without a doubt a (much) "better C++" but I'm not sure a better C++ is necessarily what systems programming needs most. I agree but if better C++ is what the PL industry can give me, then I'll take it, thank you very much! (Frankly at this point I'll take anything that isn't C++...)
- pron 7y agoThere are alternatives that more appeal to my taste in the works. Given the cost of changing language, any language, I'll wait and see how they turn out before making decisions.
- jeltz 7y agoWhich ones are more to your taste? For me it is mostly Zig which seems closer to what I want to see in a language. Crystal also looks promising but I prefer languages without GC. Rust is a good language but it is a bit too complex and restrictive at times.
- pron 7y agoYep, Zig is the one I like, and IMO it's a language that shows an interesting yet very simple model for what systems programming can be. But I'll admit that it's easier to look good before you're put to the test in the field, so I'll wait and see what becomes of it.
- devit 7y agoAs far as I can tell Zig is equivalent to a subset of C++ and thus completely lacks all the guarantees that Rust provides and several of the features that C++ has; so there is no point to use it instead of those languages.
- pron 7y agoIf you prefer languages with more features, then simple languages aren't for you. But me? If you told me you'd give me language X but with far fewer features, my eyes would light up, and I'd only ask, are you sure you can't get rid of any more? As Saint-Exupery said, "Perfection is achieved, not when there is nothing more to add, but when there is nothing left to take away." Zig has all you need to write clear, efficient, generic, systems code and nothing more, but also nothing less. It is also intended to help you write safe code, but it goes about it differently from Rust.
- devit 7y agoAs far as I can tell Zig only has C-like malloc/free-based allocation and thus is vulnerable to use-after-free, and so does NOT help you write safe code. It also doesn't seem capable of safe concurrency.
- pron 7y agoYou assume that the only way a language can help you write safe code is by making sound guarantees; this is wrong. A language can also help you write safe code by making it easy to selectively add runtime checks (that can then be selectively turned off in production), by making code-build-test cycles faster, and by making it easy to inspect what the code does. This approach has tradeoffs: it is unsound so it will let some undefined behavior bugs through; on the other hand it might do more to reduce bugs that are unrelated to undefined behavior.
- derefr 7y ago> This affects how easy it is to write custom compilers (very important in the embedded space) Is there a reason you’d write your own Rust compiler frontend, rather than just letting rustc generate LLVM IR as it does, and then writing your own LLVM arch target? None of the Rust complexity leaks over into the LLVM IR it generates; it looks just like the LLVM IR that e.g. clang generates.
- Const-me 7y ago> None of the Rust complexity leaks over into the LLVM IR it generates The leakage even triggers performance issues in compilers: https://users.rust-lang.org/t/5-hours-to-compile-macro-what-can-i-do/36508 https://users.rust-lang.org/t/5-hours-to-compile-macro-what-...
- derefr 7y agoNo, that's not "Rust leakage", because that misbehavior has nothing to do with the semantics of Rust as a language. That's the effect of some non-optimized function-scope-level pattern-matching substitutions that LLVM is applying, as applied to the user's very large function body. Quoting a reply in that same thread: > LLVM is not good at big functions, I have seen this before as well. One of the functions you are generating is almost 100,000 lines of Rust code including tons of internal control flow. The same would happen if you wrote (or generated) 100,000 lines of C in one function body, and fed it through Clang with -O2. If you're wondering, there's nothing in rustc that makes it implicitly turn regular code into huge function bodies, either. It's just someone abusing Rust macros to codegen badly, not taking into account how the granularity of units of compilation interacts with the time-complexity of optimization passes.
- Const-me 7y ago> that misbehavior has nothing to do with the semantics of Rust as a language. Macros are part of the language; they aren’t an external code generation tool. > The same would happen if you wrote (or generated) 100,000 lines of C in one function body Absolutely, but neither C nor C++ makes it easy to generate such code. Technically doable with C preprocessor, but it’s not easy. C++ templates don’t normally expand into 100k lines functions either, they can easily expand into 100k small functions.
- aidenn0 7y ago> Rust is without a doubt a (much) "better C++" but I'm not sure a better C++ is necessarily what systems programming needs most. As an embedded consultant, a better C++ is what systems programming needs most not for technical reasons, but social. So many embedded shops are embracing C++ and it's causing all the sorts of problems you might imagine. While it's possible that these shops will tack back towards a lower-level language, my prediction is that would be a much harder sell than something like rust.
- pron 7y agoThe problem is that Rust doesn't solve C++'s problems (my top two: language complexity and build time), it just brings fewer of them with it. I think that C still rules the embedded space, but those that switch to C++ might not do it because they love its (and Rust's) approach so much as they need to do things that C does badly (partial evaluation and polymorphism). There are other languages out there that address those concerns without C++'s or Rust's complexity.
- Rusky 7y agoYou've been asserting this for a while now, without really describing what you mean by "Zig's approach." What features are you thinking of here, and why would we expect them do any better than existing tools in C++ (or even C)? For example, "modern C++" is also often described as having similar benefits to safety.
- pron 7y agoZig's approach to safety is to optionally add runtime checks either in debug builds and/or in arbitrary code scopes even in product builds, rather than to try to soundly eliminate them. This means that the language can be drastically simpler. Some UB can escape this kind of unsound safety, but on the other hand the simplicity of the language makes the semantics of an expression easier to understand -- which may make, say, code reviews cheaper -- and may free up time for other kinds of assurance, be it through faster compilation, shorter development cycles, and possibly static analysis tools, that generally like simple languages. Now, note that I am not saying that Zig's approach to safety is definitely better than Rust. Correctness is an extremely complex issue, with many factors, and it's hard to say with any certainty what works and why. My preference for Zig (which is largely hypothetical as Zig doesn't really exist in a meaningful sense yet) is because I personally value language simplicity and short cycles over what some call "expressivity", but as someone who is also very much interested in formal methods and software correctness in general, I am not convinced that Rust's complexity buys you increased correctness over Zig, and it may even be worse. So the tradeoff is simplicity vs. "expressivity", where correctness can go either way.
- Rusky 7y agoC and C++ have plenty of analogous checks- debug assertions in the standard library, runtime checks for uninitialized memory, sanitizers, etc. Do we have an idea how effective they are there? Do we have reason to expect Zig's to be any better? In fact, Rust approaches most of these particular problems the same way- arithmetic overflow, array bounds checking, stack overflow handling, etc. are all checked at runtime. Rust's language complexity is dedicated to things that Zig simply doesn't check, and that C and C++ have checked only recently. This goes back to a previous conversation of ours[1]- Rust's complexity is allocated very differently than C++'s. It has many of the same advantages as Zig (if not more) when it comes to understanding and code review. Painting Rust's static analysis and associated language complexity as an alternative to C/C++/Zig-style runtime checks looks like a category error to me. [1]: https://www.reddit.com/r/programming/comments/eehe6t/a_backwards_introduction_to_rust_starting_with/fbv1h3u/?context=1 https://www.reddit.com/r/programming/comments/eehe6t/a_backw...
- einpoklum 7y ago> Rust is without a doubt a (much) "better C++" Huh? They are apples and oranges. Is Rust intended to provide "Direct mappings of built-in operations and types to hardware to provide efficient memory use and efficient low-level operations"? That's one of C++' design goals. If you change the design goals, you get different advantages and disadvantages. See more about the C++ design goals in this interview: https://www.electronicdesign.com/technologies/dev-tools/article/21798683/interview-bjarne-stroustrup-discusses-c https://www.electronicdesign.com/technologies/dev-tools/arti...
- steveklabnik 7y agoYes, this is a design goal that they both share, and generally accomplish in similar ways.
- MaxBarraclough 7y ago> it is also not necessarily the best way to reduce bugs I think this needs to be more specific. Comparing Rust and C, for instance, it seems complexity can be used to improve correctness; the tradeoff is worth it at least some of the time. It seems to me the best example of a simple correctness-oriented language isn't Zig, it's Ada SPARK, which has been used in various life-critical software systems. [0] SPARK's advantages are due to its simplicity: * The whole language has been defined formally (zero ambiguity) * The language is amenable to formal verification A monstrously complex language like C++ brings many features, but is much harder to reason about formally, and will never have a formal definition. [0] https://en.wikipedia.org/wiki/SPARK_(programming_language) https://en.wikipedia.org/wiki/SPARK_(programming_language)