How often does Rust change?
words.steveklabnik.com
words.steveklabnik.com
C++ is from 1985 and standardized in 1998, and it's still changing at a fast clip: C++11, C++17, Concepts will be a big deal when they happen in C++2?.
Rust wasn't announced until 2010 and didn't ship 1.0 until 2015. It's only had 5 years to bake since 1.0, vs the 22 for C++.
C++ pretty much didn't change between 1998 and 2011 though (2003 was mostly a bugfix and compatibility release). And these days it updates every 3 years (you forgot C++14 though it was a very minor release) which is a much slower pace than Rust's 6 weeks cycle.
That's not to say Rust is necessarily slower paced than C++ either, just that a raw number on release dates aren't helpful by themselves.
I think the "Rust is changing too much" feeling comes from people really wanting to use Rust because it has a cool new way of managing memory and zero-cost abstractions, but also feeling like it just keeps moving a little too much on them. Languages like Go and Kotlin just aren't moving much on them.
I think that another part of that feeling comes from the fact that Rust has two different pieces: a) the new way of dealing with memory and abstraction; and b) the syntax, sugar, etc. If you're looking for "a", Rust is the only game in town there. You can't just decide that you need the memory lifetimes and zero-cost abstractions, but don't want to deal with the rest of Rust's evolution.
This might be easier to illustrate by contrast. If I want a statically-typed, garbage-collected language, I can choose Java, Kotlin, C#, Scala, Go, TypeScript, etc. I feel like I have a lot of choice. If I want a dynamic language, I can go with Python, Ruby, JS, PHP, etc. If I want a language that doesn't need GC while not having memory leaks...I'm left with Rust. I can't decide that I don't like the other parts of Rust or don't want to deal with Rust's evolution. If Kotlin were evolving quickly and breaking lots of things, I could just say "Kotlin is dumb and I'll just use Java or Scala or C# or Go". I can't say "Rust is dumb and I'll use..."
When there aren't easy replacements, you're wedded to the decisions of the community. The easier the replacements, the less loud your complaints will be about a language. I think that Kotlin was pretty great for Java because it was highly compatible with Java and gave Java breathing room to figure out how it would evolve Java. Kotlin gave frustrated people a path; it gave Java breathing room to figure out its evolution; and it gave Java the opportunity to look at what worked well in Kotlin and figure out how it could apply that in Java.
When we look at Go, there are often complaints because Go offers things unavailable elsewhere: fast compile times and to a certain extent its concurrency support. So if you really want fast compile times, you don't have an alternative.
Rust is probably changing more than languages like Go and Kotlin which are similar aged. There's a good reason for that: Rust's brief is a lot more novel and expansive than those two languages. However, if you're sold on Rust's memory management and zero-cost abstractions, it might be annoying that it feels like more of a moving target than a language like Go or Kotlin - and you have no alternative to fill that void.
Perhaps that's by design, but it's frustrating.
I never used those languages, in fact I discovered them on previous HN posts, but it seems to me that in this category you can also have Nim and Zig, no?
I think Nim and Zig are both quite interesting and potentially very productive, but they have a long way to catch up to Rust in terms of community support.
Certainly other languages were able to become widespread with large communities and library ecosystems without being directly sponsored by a corporation, such as Python or Ruby. I tend to think of those as associated with an individual, Guido or Yukihiro, though I know in Guido van Rossum's case he's worked for Google and Dropbox, though that was after Python was in wide use at those companies.
Whereas with Rust I think "Mozilla" not "Steve Klabnik", because it was corporate-sponsored from the beginning and worked on by a team.
And if you want your favorite language to grow into its potential, you need funding, and corporations have a lot of funding to put into things like potentially productive new languages.
I think this post alludes to my issue, the language it self i don't think changes at an unreasonable rate, the ecosystem felt like a problem. There's so much changing, what's the "right" way, the right library, expected syntax seemed overwhelming. maybe this doesn't change a lot, but it is compounded by the new user experience. Other things are out dated resources around the internet. The other thing I think that makes this seem worse is I think the a lot of the community is online and hobbyist work, and the speed communities change on line is just fast, information moves fast, blink and you'll miss something.
I do remember feeling excited about rust, but it felt like there was always something new learn, something around the corner, something better coming then a new feature would come out, i gotta learn that, what is going on in nightly. Supposedly editions fixed that, but even that I gotta go figure out what an edition is and what its implications are.
I haven't gone back to rust, at this point I feel like i need to relearn it to write anything worthwhile. Just basic stuff like how projects are laid out. I have a commit in the rust compiler, but i cant tell you the right way to organize a new project because at some point it changed. To much to keep in my head.
> However, maybe there’s a better way to surface “these are big changes” vs “this is a small thing,” or something like that. I’m not sure.
It might be as hard, or even harder, to quantify this than even deciding what gets put into the release notes. What might be a big change for one person is absolutely insignificant for another, and vice-versa.
We technically have not yet decided if there will be a Rust 2021. I think there should be, but it should be smaller than 2018.
That's pretty awesome! Should I assume this only applies if a "Rust 2.0" never happens, or is there a commitment to 2.0 never being a thing?
Every improvement added to rust makes it worse for me
There's nothing wrong with simply reading the "edition guide" every couple of years and using the automated tooling to perform 90% of the minor adjustments that you otherwise would have had to perform manually.
"cargo fix --edition-idioms" will perform many such adjustments for you.
https://doc.rust-lang.org/edition-guide/editions/transitioni...
This is OK for programmers who already know Rust. But for new programmers coming to the language, it presents a very difficult challenge.
To give one anecdote, I was trying out Rust a few days ago. Just baby steps. I wanted to read a file. But since the try! the macro syntax is changed, almost every example I could find on the Internet was broken. Took me almost an hour to figure out what was going on. (I have programmed professionally for more than 10 years in Java, JS, Objective-C, PHP, Python and Go) Lost the interest to pursue it further.
Another time, I thought I would read some small projects in Rust from Github to improve my understanding of Rust. I wanted to checkout "programs" and not libraries. So I went on exploring Rust projects on Github and tried out 2-3 smallish programs. But because of Rust version incompatibilities, I was not able to get them to build and run. Now I accept, if I had been dogged enough, maybe I could have found out the exact version of Rust required for the programs. But it was too much work for a weekend afternoon where I just wanted to learn something new in 2-3 hours.
Rust community and senior Rust programmers might not accept this, but the Rust ecosystem has instability issues from a NewBie perspective.
Edit: Sorry the problem I was facing about was related to writing a file and "unwrap" and "?" syntax. Not the try! macro syntax. (I think that surfaced some other time.) I just checked my example after posting this comment. But still keeping the comment here as it shows struggle a Rust noob faces while learning the language.
It's probably too late to help now but I recommend the official documentation[0] and book[1]. They both have examples.
[0]: https://doc.rust-lang.org/std/fs/struct.File.html
[1]: https://doc.rust-lang.org/stable/book/ch12-02-reading-a-file...
In this way I'd say rust is far ahead of the pack. If you want to do something in "2 or 3 hours" you can go to the official documentation https://doc.rust-lang.org/book/ and be certain that things are up to date and work. This is also why random things on the internet tend to not be as well maintained, there's no need and that's not where new people are expected to go.
There's only so much a community can do when users like yourself go out of your way to avoid reading any official documentation (and then are left confused).
That is, I don't dis-believe your experience. It's just so, so so hard to reproduce these things, and it happens to every language to some degree. Measuring that degree is very hard, and also, Google personalizes results, so it's impossible to recreate.
I don't expect you to have this handy, but if you had data, that is, what posts you found, what you searched for, that would be helpful.
Most users do not report this experience, though I'm sure that's survivorship bias.
Don't mind the downvotes as I just wrote from vague memory without properly verifying things.
I tried to look through my Google history to see how I landed into that specific problem. But was not able to find out how exactly I landed on that syntax issue about writing files. If it helps here is my chronological Google Search and visit history on that day about how I finally went from "try" macro to understanding how "?" operator is used in Rust.
* Searched for "try macro rust"
* Visited "std::try! - Rust"
* Visited "Learning to 'try!' things in Rust - Jonathan Turner"
* Searched for "rust expected expression, found reserved keyword `try`"
* Visited "Try keyword reservation breaks macro try - The Rust Programming ..."
* Searched for "rust try macro removed"
* Visited "Error Handling - The Rust Programming Language"
* Visited "How to use ? and catch in Rust? - Stack Overflow"
* Searched for "rust optional unwrapping"
* Visited "What is unwrap in Rust, and what is it used for? - Stack Overflow"
* Visited "Killing unwrap() • Dimitri Merejkowsky - dmerej.info"
* Searched for "rust ? operator"
* Visited "The ? operator for easier error handling - The Edition Guide"
Adding insult to injury, not that it is specific to Rust, there are so many bloggers out there that don't put a date and/or give version of the software they're talking about that you just can't know if the info is correct or obsolete.
One of my first trial programs in any language is a tcptraceroute, since it's a good mix of super-beginner tasks and one slightly advanced thing. I hit a problem in Rust right at the beginning: obviously I need to make a socket, but which crate do I use, "socket" or "socket2"? Socket doesn't build anymore, but it's still available as a crate and I have to include it as a dependency and "cargo build" my project to find out that it doesn't work. To make it more frustrating, the only other example of a Rust traceroute that I found uses socket, not socket2, so it doesn't build anymore, either.
I did figure it out, but it felt like an unnecessary speedbump.
OpenGL has this issue and it sucks, and i did bring this up during the edition discussions but it didn't stack up as well against arguments on the other side.
I'm self taught and "google things until it works" is a key aspect of how i learn, and i'm disappointed to see this workflow somewhat broken in Rust. Over time, it will heal (it's much harder to find stuff that uses `try!` now), but it's still annoying.
Rust is a toy for elite home code poets. And what beautiful things they craft! Those of us who are paid to program don't have the luxury of playing with it on work time.
That is the problem I have too.
There was a blog post a couple days ago that made the complaint. Not linking because even the author felt it was too easily misread. From my understanding, the crux of the complaint was that it is hard to "keep up" with Rust. I think the idea is similar to the complaints made here about Javascript frameworks and friends. This is where the current blog post comes in, trying to quantify things to see how much justification there is to the complaint.
Personally, I don't think Rust is changing too much but it can easily be perceived that way and we can do stuff to help that perception.
One goal of Editions was to provide a rolled up release announcement to catch everyone up. The current blog post calls out how feature announcements are different between releases and editions. So I feel there is something we can be doing better about Editions. Maybe we should always schedule them, even if there are divides where code breaks. This would build trust in the wider community that if they don't need something specific, they can watch the Edition releases from a distance.
Another thought I had is that we can do a better job classifying changes. The current post talks about major, medium, and minor. My framing is from C++: pervasive vs library features. Right or wrong, some complain about complex C++ features and it gets excused as a feature the average developer can ignore because it is more targeted at the type of people who write boost libraries. We can be a lot clearer in the Rust community with what role a feature fills. Is it for a niche? What niche? How do we let people know if they should care or not?
This is an attempt to figure out why that experience was had. I suspect that library and ecosystem breakage contributes to this feeling much more than the core distribution, so this is the first step towards that. I don’t yet have a methodology to quantify ecosystem breakage...
- Function/closure serde - Futures/Async - WASM
I'd be curious if part of the instability complaint is related to a problem of averages, the "average" program shouldn't be experiencing much change - but the average developer spends most of their time writing a non-average program, and will run into a stability issue related to some library/language feature.
Because the rate of change exceeds the community's rate of making good decisions.
Letting things bake for 2-3 times longer would lead to better designs.
I highly recommend you skim it. It will show you how meticulous the core team is and how long it took to arrive at this incredible, best in class design.
Since then the 2015 edition hasn't stopped either: warnings popped up to use `dyn`, warnings that deprecated `std` functions, new feature gates added and old feature gates were removed. Libraries weren't spared: The minor releases of `rand` are so incompatible that they needs upgrade guides themselves.
For 2018 I may learn it 'sometime', every change further delays. There's Futures, there's async now. I don't have time to decipher the types since I don't need it. However there was and is so much discussion that I'm already tired.
This is only a problem on nightly, which is a toolchain which explicitly makes no stability guarantees and is intended for experimentation?
> For 2018 I may learn it 'sometime', every change further delays. There's Futures, there's async now.
You don't have to interact with things that you don't use, though. For example I've been on Rust 2018 since day one, and I still haven't needed to learn about futures.
I don't know if you're looking for this, or if it will help, but here's the way I think of it:
In 2015, `use` paths are relative to the root module of the crate, and `extern crate` adds dependencies as items there.
In 2018, `use` paths are relative to one level above the root module of the crate, or "the root listing of all crates".
That's it- if you think of them like file paths, the edition basically just did `mv /your_crate/{all extern crates} /`, or alternatively `mv /{all your items} /crate/`.
https://doc.rust-lang.org/edition-guide/rust-2018/module-sys...
People are mossing the point, and instead of seeing that learning a moving target is a PITA they are "helping" you with solutions to your problems...
I love Rust. I hope to get a chance to use it professionally. But I expect my C coding skills are more valuable for now, so it will remain a hobby....
I'm not quite sure how it got to be that way, as the policy is that reference documentation is supposed to be written (if not actually in place) by the time a feature is stabilised.
(I know you know this, because you wrote that policy.)
Someone else wrote it actually! But, we ended up relaxing it recently, due to build system concerns. Polyrepos are hard :/
I understand why build system trouble meant the policy was changed from "the documentation must be in place" to "the documentation must be written". I do not understand why anything prevents the stabilisation process including a checklist item confirming that the documentation has been at least drafted.
> I do not understand why anything prevents the stabilisation process including a checklist item confirming that the documentation has been at least drafted.
Nothing really, but we have bigger designs for the RFC process ("staged RFCs") that would introduce this, and so I haven't pushed for it in the meantime as its own separate thing.
That exact same thing happened to me. When the 2018 edition came along and made a bunch of changes that seemed, from my perspective, arbitrary and unnecessary, I couldn't really be bothered to keep up anymore and lost a lot of enthusiasm for the future of language and the team in charge.
I also think the addition of async is interesting and I may have to bite the bullet and really learn 2018. Although I hate the postfix `.await` keyword that looks like member access. The recent `try` block discussion seems to be adding additional sugar that increases the learning curve for dubious gains. Would that the goal of minimalism of the standard library also applied to the language itself.
For me, an embedded systems developer, this is an order of magnitude too much. Rust is so appealing for my use case in many ways, but I need an environment that a team can easily work in for years. My current code base is 10 years old. Our base system dates from 2017, and it took until 2018 for us to update to that. We were going to do a late 2019 base update, but sadly the project was delayed for other reasons. Our application side updates monthly, a much smaller OTA DFU. (over the air device firmware update)
You can compare it Lua:
https://www.lua.org/versions.html
The community is much smaller but it's interesting to see even at it's comparatively glacial release schedule there's a large split between 5.1/5.3.
Why do a rapidly evolving language, stdlib, etc matter?
1. We're going to be year(s) behind. I need everyone to learn and be proficient at the languages we use. They need good consistent doc and manual for our version. And not complain that we're on 1.31.0 but this great feature is in 1.33.1.
2. Moving base languages is support, not direct project improvement. While we standstill moving the base system/language/tooling forward our customer releases a new feature.
3. People are always going to google "how to do silly thing" and get code snippets. Heck I do this all the time with Python. =) It's really nice for this be somewhat consistent/right.
Sigh, as an embedded dev I'm so torn on Rust.
This?
https://ferrous-systems.com/blog/2019-06-05-sealed-rust-the-...
Do you have a short version recap in 1 or 2 sentences? Plus any liensing/costs/etc/etc?
The short recap is: some folks are trying to get a subset of the language certified. They run an entire consultancy that does a lot of embedded Rust work. I am hoping that this will help to alleviate the issues you're talking about; we'll see how it goes!
rustup doc
gives the standard documentation (book and API) for whatever version is currently active. You should be able to install and default to any version of the toolchain you want e.g. `rustup default 1.31.0` and you're done> And not complain that we're on 1.31.0 but this great feature is in 1.33.1.
Surely that has nothing do do with Rust's evolution, and happens on every language which is not literally dead? Even on languages with a relatively slow release schedule this happens.
You mention Python, that's what we use at $dayjob, we're currently on 3.5 compatibility. Some colleagues would like to use f-strings, or walrus, or dataclasses, and they can't and that's life.
We're on python 3.7, 3.5 and 2.7, yay! :) Don't use it on embedded systems though, version just depends on who's backend, mfgtest, etc, we're dealing with.
Some complains it's moving too fast.
Some that's it's an old language that's stuck in the past.
The balance between stability and keeping up with modernity is hard to reach, and people will never be happy.
But also remember that happy people are silent. No one goes on a Twitter rant about THINGS ARE PRETTY OK!!!
There are plenty of happy Python people.
Compare this to Python 3, which cannot load Python 2 libraries, cannot be converted automatically, and is now effectively required with the sunsetting of Python 2 in January of this year. Python has a lot of strengths, and I think 3 is way better than 2, but the transition was very painful.
Meanwhile, I have a crate I wrote a while back for 2015 nightly, and it took me less than an hour to get it up and running for 2018 stable. But I didn’t have to! Everyone using 2018 (nightly) could still use the crate even if I hadn’t converted it.
`const fn` is a nice example, because it's a large number, but the cognitive impact could be neatly summarized for the general rust userbase by "neat, but I don't really care". The cognitive impact is directly proportional to how easily we can abstract the changes into a coherent story. Does it matter that there were exactly 138 "this fn is now const" changes in 1.33? No, because you already forgot that there were actually only 125. What's the actual difference between 13 extra `const fn` changes and a list of 13 other completely independent changes? 13 arbitrary library changes sound like a lot when they're not neatly bounded by a pre-existing frame of reference. In this case, "this fn is now const" * X where X is 'a big number' doesn't change in cognitive impact when X is replaced with X * 1.1.
I think that Kubernetes release notes are another interesting example. There's typically a huge number of changes due to the distributed nature of the project's development. The vast vast majority of the changes would have little to no effect on your k8s deployment, but there may be some nugget in there that does have a big impact on you. The problem is that that nugget is different for everyone.
So it seems like the key to communicating change may be to present the change in conjunction with a carefully selected frame of reference that enables the audience to easily conceptualize the bounds of the effects of the change in relation to their own experience, before being inundated with the details of the change that would only be useful to people occupying a different frame of reference. The problem is that everyone's experience is different and the impact a change will have will greatly depend on who's reading.
Maybe release posts need old school newspaper-like front pages where changes are scoped and summarized, and details are hidden unless the user wants more. Or maybe there should be multiple posts from the perspective of different user personas. But these ideas aren't cheap to implement, and the problem seems to approach something like "the fundamental difficulty of communication" which is way beyond my scope of understanding.
Exactly! This is how language and API changes are usually designed, and announcing them the same way is a great idea.
Are there any similar statistics for other languages? To me this seems high. It's not common that a program that compiles in other languages becomes illegal in a later release.
I mean I understand why the Rust developers make this choice—the language aims to provide strong static guarantees, but I hope they appreciate that users don't like when their programs break after a compiler upgrade.
Some changes that stand out to me: the try macro being deprecated was huge, and though the ? Operator is a thousand times nicer, that was a rather radical shift to the ecosystem where you could smell code from yesterday a mile way; I seem to remember try blocks were stabilized then removed but I seem to be mistaken on that count; async of course is a huge change and it absolutely does force you to use it since it’s a contagious language feature in pretty much all languages (I’m very disappointed with tokio on this count and have a feature I’ll probably file a PR for to help reduce this); the change allowing reusing the same variable name inside a match binding as the variable being assigned to was hugely beneficial but quickly broke backwards compatibility because of how nice it was to give up. I think the changes to std::error are also worth mentioning, they might be backwards compatible but they completely obviated an entire generation of crates and coding styles (I for one do not lament the death of quick error and co).
I feel a better metric for this might be to study the min rustc version to compile libraries, i.e. community adoption of new or breaking changes. If you take the releases from the top 250 crates in the past few years and see how many rustc versions back from whatever was stable at the time of release could compiled the release, that might give you a more data-oriented result.
Also, I think some of the real frustration might be from “core” crate breakage, such as the transition from tokio 0.1 to 0.3 and the ensuing mess or examples like gfx-rs that hundreds of other popular crates built on to get OpenGL support before they completely deprecated it and pivoted altogether such that not all are those crates left based on a dead-ended project but OpenGL users are all SOL (“just a little while longer!”) as the community-adopted alternative is wgpu which requires Vulcan/Metal/DirectX until the promised OpenGL support lands there.
I’m not complaining; NIH people generally get off easy with community deprecation of popular crates ;) and OSS developers are absolutely not beholden to anyone. But I imagine for developers plugged into the ecosystem, changes to extremely popular crates and changes to the language or standard library might result in a general annoyance that doesn’t distinguish between the two (and that’s also fair since the reason rust has a small standard library is so people use crates which can be more easily replaced or deprecated).
Stuff like C/C++ basically won't ever change*. Code that you write today will probably compile in ten years. If you're writing in C++17, there will probably be a C++17-mode in 2030, as there are C-99 and C-89 modes today.
Otherwise, if you want the newest shiny language, you shouldn't complain when it changes.
But it's nothing new really: there's no free lunch.
But also you’re wrong about C/C++, new versions of those compilers often uncover dormant undefined behavior when the compiler slightly changes behavior in certain areas.
If your program does not compile anymore because it was relying on undefined behaviour, it was wrong from the beginning and deserved it.
It is completely different of old sane codebase not compiling anymore due to syntactic sugar change in the language.
That is a stronger guarantee being made by Rust than C or C++ have made.
That is not very common with Rust.
If you just download some project off of Github (or using some dependency) from 2015, it is very very likely to "just work" even with a new compiler, due to how editions work.
A more likely way to encounter issues is by pasting some code from Stackoverflow into a Rust project that is using a different edition. Yes, that can happen, but it's not anywhere close to as big of a problem.
I never say it is. You guys are quite on defensive stance :)
By and large, this has not happened to rust.
This:
> If your program does not compile anymore because it was relying on undefined behaviour, it was wrong from the beginning and deserved it.
Has sort-of happened in that soundness fixes are allowed to break BC.
There is a reason commercially backed language have a mush slower release pace and big release. It is easier to write doc for and prepare formations, classes and certifications
For better or worse, in corporate/industrial landscape those are kings. If Rust does not understand that it might stay in the hobbyist category.
With Javascript being the exception. Unless I am completely wrong and it is the new norm.
And Python. And Ruby. And C++. And Kotlin. And Swift.
1. Quite often.
2. With some breakage of existing programs.
... and this is a fundamental paradigm difference between Rust and C++, for which the answers are:
1. Every 3 years.
2. Changes are backwards-compatible [1]
-----
[1] There are slight specific manageable caveats. Example: The repurposing of the `auto` keyword.
Note that none of this analysis analyzes breaking-ness of changes, so I’m not sure how you got this from the post.
C++ won't let you just (seamlessly) use a C++98 library in a C++20 project, or vice-versa.
This is too strong. We have made some soundness fixes that have broken crates. (We spread the change out with warnings for a long time before actually breaking) We have changed type inference in ways that one or two crates needed to add an annotation.
The vast majority of the time this is correct though.
New things come and they make things easier, but anything from 6-24 months ago, still works in the identical fashion as it did at that point.