1. 48
  1.  

  2. 17

    I give Steve lots of credit to go about this in a data-directed way and be brave enough to confront that the data disagreed with his intuition and explore why. One thing that might worth counting is changes that likely lead to code needing to be changed vs those that just add functionality.

    1. 1

      Depends what you mean by needing. Rust is backwards-compatible with 1.0, so you didn’t need to change anything (unless you were unlucky and hit an edge case in type inference, or a compiler bug that has been fixed).

      To maintain a heathy Rust-idiomatic codebase, I think you’d be pressed to:

      • replace try!() -> ? in 2016,
      • run cargo fix --edition in 2018,
      • adopt async/await in 2020.

      The last one is a major shift, but others can be applied with tools. In the meantime there were also two deprecations: trim*left/right() renamed to trim*start/end(), and Error stopped requiring description().

      1. 1

        Needing to stay idiomatic. Rust is thankfully better than Haskell now where minor version releases of GHC will make code stop compiling on purpose. I think the pressure is real and I think if tooling (like linters) could be developed to ease the burden, people won’t feel the pressure as much.

    2. 14

      TL;DR: the article asks “how often does Rust change?” And the answer is “every six weeks”. Regardless of how big the changes are, you have to check every six weeks to see if something changed. Like someone said the other day on Lobsters, it’s like getting your pizza sliced into 42 slices versus 12. Sure it’s the same amount of pizza but the cognitive load is higher.

      The endless release posts with tons of stuff in them makes it feel like a lot is happening.

      TFA seems to argue that yes, Rust changes a lot, but they aren’t “big” changes.

      The problem is, big or not, I’m trying to learn the language and it feels like a moving target. As a neophyte I don’t know what’s important about the new version and what isn’t.

      It’s also interesting to note the number of language changes in each release. Standard library changes are one thing, but language changes make things more difficult to learn.

      For example, from the release of Python 3.5 (which introduced explicit async/await syntax, the last major syntax revision) in late 2015, there’s been around 40 Python releases across both Python 2.x and Python 3.x. If you only track Python 3, there were around 30 releases. The majority of these releases were bug fixes, with no or minimal standard library changes. There were of course some big standard library changes, but they were the exception.

      In the same time frame, there were around 65 releases of Rust. These changes were not just bug fixes but all over the place.

      My point is, with Rust I’d have to go through twice as many release notes and while the list of changes is generally small, it’s not always clear what’s a big change and what isn’t. With Python, it’s obvious that “fixed bug in how whatever works” is a bug fix. In Rust “this macro can now be applied to structures” doesn’t mean anything to a neophyte. Is that a big change? A small one? I don’t know.

      Of course you can find counter examples in Python releases and bug fixes in Rust releases, but it just feels different. It feels impossible to keep up.

      Compare to languages like C, where there were literally no changes between the last two standard revisions (C11 and C18), or Go which has had around 10 significant releases in five years and an explicit language standard that allows alternative implementations. (Go has had more than ten minor releases in that time, but anything where only the minor version changes are bug fixes).

      I really like Rust. The type system is beautiful. The ownership model is gorgeous and innovative. The toolchain is fantastic. I just feel like using it would be on a treadmill, every six weeks poring over release notes to see what changed. Sure I can stick to Rust 2018, but by doing that I’ve run into third party code that used newer features that I didn’t know about. I’ve also run into trouble with distro-packaged Rust being “too old” to build something I find online. Sure I can use rustup, but I like having the OS packaged and supported tools.

      (Again, of course, other languages have problems with the packaged version being too old but I’ve used Python for many years and not had that many problems and Rust for a couple of months and run into it twice).

      I really, truly, think that Rust’s rapid release schedule is my and perhaps others’ primary barrier to adoption.

      (Also, and this is a minor thing, but one of the major Rust contributors tweeted (or retweeted) a thing about how “COBOL was designed by women and just works and C was designed by men and it’s impossible to use securely.” Despite being inaccurate it also struck me as really unwelcoming. I was following that person’s Twitter feed specifically to start participating in the Rust community and that did not encourage me.)

      1. 14

        Regardless of how big the changes are, you have to check every six weeks to see if something you rely on changed.

        Or else what? If you only check every 12 weeks and read a pair of posts at a time, or only check once a year, what goes wrong? Your code will keep on working.

        You miss out on anything new and nice, but only as much as if Rust was releasing less often.

        1. 7

          Well partially because it’s not just my code.

          If I want to use a third-party crate (which is almost a given because of the way Rust’s ecosystem is designed*), I need to audit that crate to make sure it’s secure and correct for my purposes. A rapidly-changing language makes it harder for me to read other people’s code regardless of how static my code is.

          * this is not necessarily a negative thing

          1. 10

            Among the changes Steve enumerated here, are there any that you feel would impact your ability to audit code without having known about the feature ahead of time?

            I would think if you are auditing and encounter something unfamiliar like const fn or dyn Trait or some new standard library method, it’s easy enough to then learn about it via search and the Rust documentation.

            For standard library methods, by far the main way people learn about them is not from release posts. They find them in documentation when searching for that functionality, or look it up when they see it in someone’s code. But in a safe language this works for the things classed as “language changes” as well. The feeling of being compelled to read the release notes isn’t well founded in my experience.

            1. 4

              The ?, for example, was a problem for me getting started. I’d never seen it before and while I understand its purpose and it makes great sense, I then had to go say “okay this way of doing things that I’d already read about and started getting a handle on has two ways of expressing it.”

              It’s not the end of the world, of course, or that difficult to understand, it just seems like there are a lot of little changes like that that increase cognitive load for me.

              Again, this is just me and my opinion. Obviously Rust is very popular and this release strategy works for them. I’m just pointing out what has been a difficulty for me and, given the articles posted recently here, for some others too.

              1. 6

                You now shifted from “changes every 6 weeks” is a problem to “this syntax change was a problem”. I believe you that ? Was confusing at first. However, the post shows that syntax changes are rare. If and when you do see it, you go look up what it is. No way that is happening every 6 weeks.

                1. 13

                  You now shifted from “changes every 6 weeks” is a problem to “this syntax change was a problem”.

                  You asked for an example from a limited set of possibilities, and I gave one. I didn’t imply my list was exhaustive. You then accuse me of changing my argument…because I gave you an example from one of the possibilities you asked and explained how I felt about it as a new user of the language.

                  I’ve said several times that this release schedule seems to work for Rust and a lot of people like it. I’ve also said that it seems to be a barrier to adoption for some people, myself included. I’m choosing to try to overcome because I think Rust is a fascinating and worthwhile language.

                  I don’t appreciate the implication that I’m somehow lying in my impression of a programming language or trying to “win” some debate here with gotcha tactics. That Rust changes often is a concern that a lot of people seem to have. As someone who has decided to learn the language, my impression is that I think this argument holds some water. I’ve presented my feelings in response to a topical post regarding the same issue.

                  1. 2

                    I’m not denying that try/? change was an issue for you, but how could Rust avoid causing you that problem?

                    You’re saying that it should release less frequently, but I don’t see how that avoids the fact that it changed at all. If Rust didn’t change ? in 2016, it would change it in 2018. The result in both cases is the same: you — a Rust 2015 user — wouldn’t know the new syntax.

                    1. 1

                      Nobody expects a language to be static. It’s like I said above, it’s easier to understand larger release notes twice a year than smaller release notes eight times a year, at least for me and obviously some other people.

                      There’s also the issue that, okay, it’s not Rust 2015….but it’s not Rust 2018 either. It’s something in between. I can’t say “oh yeah, that’s from Rust 2018,” I have to say “that’s from Rust 1.27.0” or whatever. There are many more versions of Rust to keep track of than just 2015 and 2018. I learn the ? syntax and that’s great…but that doesn’t teach me Rust 2018, it just teaches me part of one of eight or nine steps between the editions.

                      (And maybe I’m wrong but there doesn’t seem to be any concrete sum documentation for the Rust editions. The documentation at rust-lang seems to track stable and there doesn’t appear to be a “Rust 2015” snapshot of the documentation except in dead-tree form. Please correct me if I’m wrong. That means that as I’m studying the language, the documentation changes out from under me, not a lot but some.)

                      As I said above, a lot of people seem to like this sort of schedule with smaller changes more often. That’s great.

                      What I feel like some Rust advocates aren’t getting is that some people don’t like this schedule and the Edition mechanism doesn’t seem to totally fix the problems they have with it…and that’s okay. People are allowed to say “I like Rust but I’m having trouble with this part and it’s a major pain point.” Rather than try to “prove them wrong” about how they feel about the release schedule maybe acknowledge that it can be a problem for some people.

                      1. 2

                        Why do you have to know from which version a thing is? I get that in C or C++ you have to know when each feature has been added, because there are different camps that settle on different past decades, but in Rust there’s no such thing. If you know a feature has been released, you can use it.

                        there doesn’t seem to be any concrete sum documentation for the Rust editions

                        There has been only one so far, and it’s here: https://doc.rust-lang.org/edition-guide/

                        The documentation at rust-lang seems to track stable and there doesn’t appear to be a “Rust 2015” snapshot

                        Old docs are archived here: https://doc.rust-lang.org/1.30.0/

                        But “Rust 2015” isn’t a version of Rust. It’s not a thing that can be targetted or snapshotted. It’s a parsing mode that changes interpretation of a few bits of syntax. It’s like "use strict" in JavaScript or Quirks Mode in HTML. “2015” parsing mode in latest Rust has all the new features of the latest Rust, except a couple that would conflict with some keywords/syntax in 2015.

                        The Rust team created a lot of confusion around this by marketing “cool new features we’ve released in the past year you may have missed” together with the “new parsing mode” switch, creating a false impression that “2015” and “2018” are different languages. They’re the same language with the same standard library, but “2015” mode can use async as a variable name.

        2. 2

          Thanks for chiming in with this view. It makes a lot of sense.

          However, I also feel that the Internet encourages this sort of firehose-style of releases. To many developers, a slow release cadence indicates project stagnation. And, to them, stagnation does not imply stability, but rather, a dead-end. I’m pretty sure the rust team puts releases frequently for other reasons that are more important, but there are virtues to signaling frequent project activity. IOW, I don’t think the Rust core team caters to the “always be committing” crowd, but they do try to stay on the collective radar.

          FWIW I have been on both sides of the module change and I lost a few hours to trying to understand it. But that’s been about it so far. Haven’t ventured into asynchronous stuff yet.

          1. 1

            Worth pointing out that Python has been around since the early 90s. How much did Python change at an equivalent point in its lifecycle? How would Python look if it had been locked in amber at that point?

            1. 10

              People get hung up a lot on Python 2/3, but forget how much Python changed prior to that. During the Python 2.x series, the language gained:

              • The bool type
              • Opt-in unified type hierarchy and “new-style” classes with full operator overloading
              • Context managers/the with statement
              • Unified integral type
              • Integral versus “true” division
              • The set type
              • The logging module
              • The unittest and doctest modules
              • The modern import-hook system
              • Lazy iterables and the itertools module
              • Generator expressions
              • The functools module
              • Ternary conditional expressions
              • Absolute versus relative imports
              • Decorators
              • The format() method and formatting mini-language
              • The collections module
              • Abstract classes and methods

              And on and on… sure, you could say that code written for Python 2.0 still worked on Python 2.7 (which wasn’t actually true – there were deprecations and removals in the 2.x series!), but idiomatic Python 2.7 contains so many things that would be unrecognizable to someone who knew only idiomatic 2.0 that it might as well be a completely different language.

              1. 2

                No doubt, but early Rust was very different from modern Rust (there was a garbage collector at one point, major differences in the type system, etc).

                I’m not saying Rust doesn’t deserve its youthful vigor and changes because of course it does. I also don’t think Python was as popular that early in its life as Rust is, relatively speaking (at least from my fuzzy memories of those ancient days where I worked mostly in Perl and C). Python didn’t really explode to be everywhere until after the 2.0 release, IIRC. Python 2.0 and Python 3.8 are of course pretty different, but there’s something like 20 years there versus ten for Rust with I would argue even greater changes.

                Regardless of the relative age of the languages, I do think Rust’s change schedule is a barrier to adoption for a lot of people (with the anecdotal evidence of the couple of articles posted recently here talking about just that).

                Again, that’s just me. I’m sure a lot of people like Rust’s release schedule and it seems to be working well given Rust’s rising popularity.

                1. 0

                  Why would you compare that to Rust’s changes now and not to Rust’s pre-1.0 changes?

              2. 4

                The changes aren’t bad, but it changes more often than I have time for. I had been struggling keeping up for a while when I finally dropped out for good at 1.38

                I already have to keep up with so many other changes for things (C++, Python, so on, etc.), since I’m not paid to write Rust, I simply run out of time. The issue isn’t some arbitrary metric of number of changes, it’s that when I’ve come back, catching back up has been an incredibly painful process. Since I do a variety of hobby work, sometimes it might be several months also due to work and family commitments before I come back to a project.

                I did this a few times. I came back and there were some changes. I came back and dyn and impl trait were a thing. I started seeing ? all over example code and had a fun time trying to google it to figure out what was going on. There are some really good comprehensive resources like https://cheats.rs/, but unfortunately, I’m tired of restarting a project by reading pages of language changelists or being unsure of what new stuff there is. I have a Rust project from 2017 I’d like to do some more work on, but it’d take multiple days of just reading again and thinking about how language changes affect it.

                I like Rust, but I’m waiting for the next big release (edition).

                1. 5

                  The changes aren’t bad, but it changes more often than I have time for. I had been struggling keeping up for a while when I finally dropped out for good at 1.38

                  I stopped reading the release notes every six weeks quite a while ago (probably 2 years or so)… and nothing happened. My code still compiles, I still contribute to third-party crates. Every few months or so, I look up what is new.

                2. 2

                  I’ve gathered data for standard library changes by grepping Rust sources for #[stable] markers (which are added to all functions and types that get released as stable):

                  https://users.rust-lang.org/t/counting-number-of-stable-methods-of-libstd/40802/4

                  I’ve also got a complete list of all feature flags from all releases of Rust:

                  https://users.rust-lang.org/t/counting-number-of-stable-methods-of-libstd/40802/3

                  It seems like there’s a lot of them (like 10 or 20 per release!), but if you look closer, almost all of them could just be a footnote “and misc. minor changes”.

                  IMHO only 4 releases changed the way idiomatic Rust looks like:

                  • 1.13 = ? operator
                  • 1.15 = proc macros (serde made possible)
                  • 1.31 = Edition 2018
                  • 1.36 = Futures

                  The rest was like “now you can convert an array of bytes to an IP address” or “File can change permission flags”. These were useful small improvements, but people were only affected by the lack of them, not by their presence.

                  1. 0

                    Hopefully for Rust 2 they will reconsider the breaking changes speed, similar to Python or Go.

                    1. 12

                      What breaking changes? Rust has a strong backwards compatibility policy. Code written for Rust 1.0 will happily compile with Rust 1.42, 5 years later.

                      1. 3

                        I think the only possible shift in speed would be up, surely? As far as I can tell, you can continue to compile software from Rust 1.0 with the current toolchain and will be able to do so into the future.

                        1. 1

                          Modulo some cases where the compiler now catches unsound code and didn’t before. But that’s a good thing.

                        2. 1

                          There is not going to be Rust 2. Rust has adopted the edition system instead.