I am currently teaching a course where Rust is the main language and this is already a problem. Some recent changes have made Rust more difficult to understand. E.g. impl in argument positions have are really opaque. For example, it is quite easy to explain and understand the difference between
fn foo<T>(t: &T) where T: SomeTrait
and fn foo(t: &SomeTrait)
because the type parameters are explicit in the static binding case. On the other hand, fn foo(t: &impl SomeTrait)
is really opaque. I know that it is an ergonomic win and provides consistency between impl in argument and return positions, but it makes Rust more difficult to understand for new language user. Other magical/difficult to understand semantics: automatic derefs in pattern matching, deref coercion, different drop orders for structs/local variables, impl coherency rules, the distinction between copy/move types, etc.Don't get me wrong, Rust is my all-time favorite language. But I agree that increased complexity is the most dangerous pitfall for Rust. I fear the day higher-kinded types are added and the catogory-theory fest will be added in addition to the existing complexity.
fn foo(t: &dyn SomeTrait)
&dyn SomeTrait and &impl SomeTrait are then more directly comparable. “&impl SomeTrait” should be read as “a reference to a type implementing SomeTrait”.It’s different from the angle-bracketed generic syntax you may be used to, but I think it’s generally superior. I certainly find it much easier to write and read than the generic syntax or generic-syntax-with-where-clause versions. Well, I say generally superior—but its potential downfall is the turbofish issue, that impl in argument place is not just sugar for the generic syntax. And thus that for now impl in argument place is arguably unsuitable for library code and only suitable for application code. We’ll see how that pans out.
You mention higher-kinded types: there is actually a plan now for a feature equivalent to HKT, generic associated types (associated type constructors), https://github.com/rust-lang/rfcs/pull/1598, and I’m glad; note when I say that that I was one of the few that campaigned before Rust 1.0 for explicitly not touching HKT for a few years purely for marketing reasons—they’re scary and will put people off Rust. But certainly I have encountered a couple of situations where generic associated types would substantially improve ergonomics in my HTTP and web work, and this is a proper Rust-flavoured take on the concepts behind HKT. I believe it will be good to have.
I am still a bit anxious about the volume of change happening, just as you, others, and graydon just now on the forum post.
e.g.
Type declaration
Function declarationThe audience for the edition isn’t just those who follow Rust closely, but for those who don’t. And even for those who do, we want to take a look at some of the things that make writing Rust feel differently in the last few months. Turns out the match stuff was good enough to stabilize a bit earlier, even though it was designed with all of these other features.
There remains a small part of me that enjoyed the explicitness of fighting the compiler to understand what type I was actually dealing with (forced learning).
rust is so damn good and the team behind it has delivered so much we hold them to impossible expectations.
Yet all other major mainstream language also are, with an history of 20 years of versions, huge libraries and quite a few breaking changes between them.
Picking up Python as an example since it is deemed simple, there is quite a stuff there to learn in 167 pages of language reference, 1942 pages of library reference, major community libraries, keep track of the breaking changes between all versions or when were specific features introduced.
By the way, it's probably a bit early to say that Go's dependency management system is broken, and anyway it has little to do with the language's complexity.
C++ got that why by accretion of features.
Rust, on the other hard, removes non ergonomic syntax, or changes convoluted features to easier to grasp ones.
Even when it adds a second mechanism (e.g. async/await over futures) that's still a huge win, and nothing like the mess C++ is in.
C++ has been removing features as well, to the extent they don't cause major breaks.
A major OS vendor states "if you want to target my OS here is the language".
(talking as someone who was working on a C-to-C# transpiler for PSMobile to port my C game engine to it before Sony axed it :-P)