> Putting the word "semantically" in front of deadlock doesn't change its meaning:And focusing on hangs in concurrent programs that are caused by using a data structure called "mutex" doesn't stop one getting exactly the same symptoms via your apparently-perfect channels.
One can use channels to get all four of the conditions required for a deadlock, especially Go's synchronous-by-default channels.
Any time you have a protocol of multiple tasks communicating with each other in some structured way, it's possible to break that protocol and hence have tasks sitting around waiting for messages that aren't coming. Especially in languages like Go/JavaScript/... which aren't powerful enough to model things like session types in their type system, e.g.
https://www.reddit.com/r/rust/comments/3jhd56/session_types_...
> I can't emphasize this enough — data races are not the only kind of concurrent programming error, yet they are the only kind prevented by borrow checking
Yes, that's exactly why the whole Rust community tries to be very careful about using "data race" when talking about concurrency in Rust.
However, it is the case that data races are the worst sort of concurrency bug: they are undefined behaviour and so can lead to arbitrary memory corruption, possibly only appearing a long way from the actual place with UB. Deadlocks and other problems are, by default, much more controlled in their failure modes.
Rust focuses on truly outlawing large classes of horrible problems: dangling pointers, iterator invalidation, data races (and all without requiring a garbage collector, although a GC barely helps with the latter two). It also tries to help with other problems with fewer guarantees, but even just being memory safe is a huge step up from widely used low-level languages (i.e. C/C++).
All the languages you mention are quite opinionated in their concurrency, imposing costs that Rust doesn't and can't, for its target space. (And, Go certainly doesn't provide any guarantees at all, not even data race freedom.)
> in addition to providing massive performance benefits vs. naive native threading
Important qualification: for IO bound tasks. Which is perfectly fine, but it needs to be understood.
> I think the time to add good concurrency abstractions to a language is before 1.0, but I'm in strong disagreement with the community there
What's so important about being pre-1.0? You seem focused on it, but I don't understand why. What benefit does Rust gain by delaying the release of 1.0 for months/years just to get good async IO support? Why is this particular pet feature any more important than everyone else's pet feature? (There have been so many requests: "why couldn't X make it into 1.0?")
If you're concerned about theoretical fragmentation of the ecosystem... that's not a problem in practice: mio is the standard.
> And judging by this thread, concurrent IO isn't even on the core team's roadmap
Wrong, it's very much on the roadmap, e.g. Alex Crichton (core team member) has been adding windows support to mio himself.
> Look at the situation 10 months ago. How much has it improved?
A lot. There's a burgeoning ecosystem built around mio.
---
In any case, Rust has been stable for barely 3 months. Be patient, and give it time for the concurrency story to blossom from the seeds that have been sown so far. Based on the experience so far, I'm pretty confident that Rust can easily be much better (i.e. more performant and reliable) than both Node and Go and even Erlang. (Of course, it may be syntactically less nice, since those languages bake it in deeply, while Rust is less opinionated.)