As @leonardo pointed out before, it’s not a bug, it’s a feature
Negative indices are a bad design from a performance point of view, because they essentially force extra checking and branching in the Index implementation, which costs performance even for those who do not use the feature!
A better fit for Rust would be some sort of “slice length placeholder”, which is automatically replaced by slice.len() under the hood (think e.g. [..$-3]).
I’d be really interested in seeing what some will say to this. Personally, I’m not sure I’ve found anything I’d deem severe but there are definitely things beyond just papercuts. A few examples:
Type inference. It’s basically wonderful until it’s not. I have a hard time analyzing some piece of generic code and guessing whether it’ll definitely break some callsite code due to inference.
Trait objects are not always easy to use (e.g. you must specify the associated type of the contained trait). There are also “edge cases” like “generic lifetime parameters in trait objects are invariant” - not easy to see/anticipate a priori until you know about it.
There’re some odd borrowck edge cases where code that seems like it should work doesn’t. I’d like to see NLL and perhaps Polonius come through to see how things look with them.
Coherence/orphan rules can be a pain, which has been discussed many a time in this forum (and elsewhere).
It’s very difficult to model/abstract borrows via trait methods. Perhaps virtual fields will help, or a first class notion of “borrow regions” (although not too hopeful about the latter).
& vs &mut vs interior mutability “confusion”. Normal mutation needs &mut, but mutation isn’t really about & vs &mut afterall as witnessed by interior mutability. But interior mutability requires extra boilerplate. Not sure what a good solution to this is, but the dichotomy is noticeable.
No good solution exists to the self-referential struct case; although rare/niche, they’re not pretty when present themselves.
Sorry, Github is blocking me from editing my comments (it says: Too many edits, wait 20hrs), otherwise, I would have added a summary. This thread collects all the posts in the continued-from thread about where Rust has (supposed) shortcomings. This thread is a bit of a meta-thread in that there are several shortcomings mentioned, but, some of the mentioned points should only require one or two refutations, while others with more merit are meant to be branched off to a new topic linked here.
I’ve added short comments as replies instead of edits to get around this. Best is for users to comment on specific parts of the linked posts with summaries/responses to give some direction to the discussion.
I can think of one particular shortcoming, maybe not severe but IMO still significant: how traits are implemented for arrays is pretty much a dirty hack. And the unfortunate consequence is that documentation is polluted. We only may hope that at some point in the future Rust will get shiny const generics and similar hacks will be deprecated or even removed altogether. I think, Rust 2.x, it’s when we’ll get a chance to bring breaking changes, is going to have a great leap forward in terms of productivity and usability.
I don’t believe Rust has any severe shortcomings. Certainly it has shortcomings, particularly surrounding API design: const generics, arrays, GADTs, code sharing primitives (‘delegation’/newtype boilerplate, diamond specialization), unsafe guidelines, keyword args & var args…
But a function is a very strong abstraction, and plenty of languages have lived on to solve great problems when the only API design available looks like a grab-bag of functions, and certainly Rust can do at least that. Rust’s shortcomings have a bigger impact on the overall ecosystem, not the its capabilities as a programming language. (This is probably unavoidable for a new language, and quadruply so for an open-source, cross-platform, general-purpose, opinionated language.)