The whole lifetimes business, which is done more generally for memory safety. It adds a lot of complexity.
On the other hand, there's clearly a niche need for a language with no GC at the systems level, so I can appreciate the reasons for Rust's decision. But after playing around with Rust for quite a bit, I'm come to the decision that at least for me, Rust's lifetimes are too complex, and (partly as a result of no GC), the overall language is just not functional enough to be a general purpose programming language. Scala is currently filling that role for me.
Additionally, lifetimes are also part of the system that statically avoids problems that appear in GC'd languages like iterator invalidation (for instance, ConcurrentModificationException).
The problem is that a lot of mainstream programming languages pretty much ignored the state of the art when implementing their concurrency models. See Per Brinch Hansen's rant about Java [1], for example.
Thank you for the references (although I think you meant Flanagan without an h). From a quick glance at one of the papers (without any guidance from an expert I have no idea where to start for a good summary), it seems like the retrofitted PRFJ has to fight the pervasive sharing of having a GC, resulting in a much less orthogonal system with higher annotation burden. In any case, at least two of the Rust team did PhDs in the areas of parallelism/concurrency so I'm sure they can give a more academic comparison of Rust and the research.
Neither. I am just unhappy that these days avoidance from data races often gets reduced to the ownership approach and I wanted to provide a more complete picture (even if a quick summary is still woefully incomplete).
(And thanks for pointing out the typo – now fixed.)
That "additionally" is exactly why I said "more generally". I didn't say that lifetimes were not for thread safety. I just said that they were more generally for memory safety (I would count iterator invalidation etc as memory safety, would you not?).