4 ms·
I know the GC is designed to make a lot of task-centric things work nicely. I mean, it's good that the GC is optional and I think Rust is well-designed but you
by codewright 14y ago
I know the GC is designed to make a lot of task-centric things work nicely.
I mean, it's good that the GC is optional and I think Rust is well-designed but you get what I'm saying about "pay for only what you use". GC being optional alone doesn't constitute embracing that mindset.
It's a far-reaching sentiment that explains a lot of the stranger design decisions in C++. I'm sure Rust could end up being great for Servo, but there's more to how C and C++ get used than that.
It takes a lot of unintuitive design compromises to make a language that's just as suitable in a 4kb RAM embedded device as it is in an HPC cluster. Only a committee of people from very diverse backgrounds is generally going to be able to account for that sort of thing.
For better or worse, C and C++'s design-by-committee did result in languages that were capable of coping with a vast variety of extremes, even if it meant giving up a lot of 'niceness' and never really taking safety seriously beyond tooling/testing.
"Pay only for what you use" means safety optional, GC optional, dynamic allocation optional, everything. I know you're a very well read and highly experienced programmer and I have a lot of confidence in the Rust-dev team, but you are not replacing C++.
You're replacing C++ for Mozilla.
- pcwalton 14y agoI'm curious what in particular in Rust's design that you feel closes off optimization opportunities. "Safety optional, GC optional, dynamic allocation optional" are all true for Rust, for example. I don't feel that we're replacing C++ for everybody, of course. C++ is a very nice language for what it does, and there's a huge amount of infrastructure and an ecosystem built around it. I don't think that we're at an optimization/performance disadvantage relative to C++ in terms of the language design, however. (Compiler toolchain immaturity is another issue, though; currently we aren't really using LLVM to its full potential in various ways.)
- codewright 14y agoYou are willing to do things at runtime that C++ would never countenance. What parts of the runtime are non-optional? It seems like you'd be in a weird and precarious position, as well as lose access to a number of features, if you shut off the GC. C++ doesn't assume the existence of a GC, because it's designed to make manual or semi-automatic memory management as performant or accessible as possible that mode of operation is better accommodated when the time for performance arises. D let you shut off the GC too, except now you were "on your own". What can't be shut-off that happens at runtime? In C++, "pay only for what you use" isn't really a compiler flag (although some things are), it's a core design principle of the language and it was designed from the ground-up for that. Adding a few compiler flags for a mode of operation that wasn't designed for from the beginning isn't really the same thing, no? Further, Rust doesn't accommodate as much variety or control over the concurrency semantics for the sake of promoting the use of tasks. That is unconscionably unacceptable for systems programming where you need to be able to use virtually any approach to concurrency depending on the nature of the problem being solved.
- pcwalton 14y agoIf you don't use the GC, then you can use stack allocation, unique allocation (like std::unique_ptr), arena allocation, or reference counting with smart pointers. You don't give up memory safety; it is still not designed to be possible to have dangling pointers, wild pointers, etc. As an example, I wrote an MP2 decoder that didn't use dynamic allocation or unsafe code at all, and it wasn't particularly unnatural to write in this way. The reason why GC pointers are built into the language is that GC really requires compiler support to do well (with stack maps) and, in particular, to interoperate with the parts of the language that don't require GC in a safe way. You can't just add GC to a language that wasn't designed for it and have it work as well; the best you can do at that point is conservative GC. If you want good GC, that's a decision you need to make early on, and you need to bake it into your language to some extent. (That doesn't mean you need to rely on it though; that's exactly what Rust is trying to prove!) There is very little that is not planned to be able to be shut off, relative to C++. One of the biggest is failure; if your functions fail, then you have to arrange to run all destructors on the stack while your thread exits. (This is similar to C++ exceptions, and are in fact implemented with C++ exceptions under the hood right now, although we plan to change this.) I suppose we could also have a mode whereby we just leak everything on failure to avoid this overhead (basically like -fno-exceptions in GCC; this is pretty much exactly the same tradeoff as C++ offers). I don't think it'd be popular though :)
- codewright 14y agoSadly I'd edited something just as you posted this, so I'll reiterate here: What about building up arbitrary concurrency mechanisms from scratch such as is possible in C and C++? The impression I had from the IRC channel was that very little beyond tasks and a couple more lower-level tools for concurrency would be accommodated.
- pcwalton 14y agoSome of the concurrency mechanisms are built from scratch today. For example, pipes (the new channel communication layer) are entirely written in bare Rust, with no C++ at all. They use atomic operations: https://github.com/mozilla/rust/blob/master/src/libcore/pipes.rs https://github.com/mozilla/rust/blob/master/src/libcore/pipe... Other interesting parts of the runtime that are built using Rust are task spawning (lots of locks): https://github.com/mozilla/rust/blob/master/src/libcore/task/spawn.rs https://github.com/mozilla/rust/blob/master/src/libcore/task... And implementations of mutexes: https://github.com/mozilla/rust/blob/master/src/libcore/private.rs https://github.com/mozilla/rust/blob/master/src/libcore/priv... The current plan is to implement the entire runtime in Rust itself. That includes the userland scheduler. So we will need all the low-level OS primitive mutexes, condition variables, pthread infrastructure, etc. There's no reason we can foresee why this would be particularly difficult; the only reason why it wasn't done this way from the start is for bootstrapping reasons.