A common criticism of some of the recent ergonomics RFCs is that the proposed changes break too much code, or cause too much churn.
In particular, @emk articulated this viewpoint so well on the previous modules proposal (which did involve more churn than the current proposal) that I can't help but sympathize with his concern:
Speaking as commercial user of Rust who's been bringing multiple in-house developers up to speed, and who already has a non-trivial code base to migrate, my feelings about this whole plan are mixed: some positive, some negative, and some wary. This is also the first time I've seen the whole "epochs" RFC, which is apparently a done deal. This is what I get for not reading r/rust all the time.
The whole "epochs" plan makes me very nervous. There are some good points: automatic migration tools, very gradual migrations, and the ability to run mixed-epoch programs indefinitely. But there are also bad points: This means that Stack Overflow is once again going to be filled with obsolete Rust code, and I'm going to have to retrain everybody on the new module system. As far as I'm concerned, this is a case of breaking the "No Rust 2.0 any time soon, Rust 1.0 is stable" promises. Yes, you're taking many steps to ameliorate that, but it's nonetheless bringing flashbacks of the bad old days before Rust 1.0. We absolutely need Rust to be a stable platform, even if that means it's not always perfect. So, my personal verdict on epochs: If the average epoch will involve a change as big as replacing the module system, then epochs are a sufficiently bad idea to make me rethink further investment in Rust. If the average epoch involves nothing worse than a new keyword or something, then the epoch plan is OK, given automatic migration tools and permanent compatibility. I mean, we are used to running cargo fmt on our code regularly.
...
So overall, my personal verdict is: This change is too large, and it would reduce my trust in Rust's stability and fitness for commercial use. If this is a one-time thing with excellent migration tools, then I can grudgingly accept it to improve Rust onboarding. But if the typical epoch is going to make changes this big, I would need to spend a lot more time defending Rust to my colleagues at work. The mere fact that this will break example code on Stack Overflow is a big deal.
Basically, the thought running through the back of my head is "We've had a golden era since Rust 1.0, but is this the end? Will I need to keep up with constant change again?" I simply have too many Rust crates, both at work and personally, to ever chase the upgrade treadmill again. The more I look at the automatic migration tools, parallel epoch support, etc., the more I realize that this isn't an entirely fair reaction. But that's my underlying gut reaction. And that will probably be the gut reaction of some of my colleagues, at least until I explain the whole epochs plan to them, which will take time. Like it or not, those kinds of conversations are also part of the developer experience that's being proposed.
Plus, @glaebhoerl very accurately pointed out that the rust-lang/rfcs comment crowd is probably more likely to support "breaking changes" than production Rust users (even if epochs/checkpoints mean they're not actually breaking anything).
I think it's highly plausible that the demographics of people who participate in discussions on rust-lang/rfcs diverge from that of Rust users in general. I would conjecture that hobbyists and "language enthusiasts" (that is, people like me) are likely to be overrepresented: people who care about Rust to some extent for its own sake, find questions about its design exciting, and basically just want it to be the best language it possibly can be. And that people who use Rust for "real-world purposes" are likely to be underrepresented: people who are interested in Rust merely as a tool to accomplish the things that they actually care about, and whose day probably consists of coming in to work, writing code (which may happen to be in Rust) and doing other work things, and then going home, and where spending time reading and debating Rust RFCs is probably not part of the job description.
And I think the first group is likely to be the most in favor of breaking changes to improve the language, and the second group, having the most to lose, is likely to be the least in favor. But since the purpose of Rust is first and foremost to be a useful tool for accomplishing real-world tasks, we should care more about the opinions of the latter group with respect to this question than the former!
Personally, I spend every weekday maintaining C++ and Javascript code that goes out to tens of thousands of clients in production. I do not use any Rust code at work (mostly because I haven't come up with a sensible place to add any). We're mostly stuck on C++03 and ES5, and have been waiting years for the various infrastructure teams below us to migrate everything we depend on to C++11 and ES6. Some of that migration included us manually changing a bunch of code we owned that was broken by the new standards. So, part of the reason I supported the epochs/checkpoints RFC is that it commits Rust to having a far better "breaking changes story" than either C++ or Javascript have had (even in my limited 2-3 years of personal experience as a professional programmer), which seems really, really good! That's why I don't personally have the concerns described above.
But we could do even better than that, and it sounds like a significant (possibly heretofore underrepresented?) portion of the community wants us to.
Off the top of my head, the obvious ways we could do better are:
-
Have a stricter policy on what changes epochs/checkpoints can be used for. See @SimonSapin's comment RFC: Evolving Rust through Epochs by aturon ¡ Pull Request #2052 ¡ rust-lang/rfcs ¡ GitHub. I suspect the easiest way to specify this is by doing #2 and saying "only changes that
rustfix
can do flawlessly are allowed". -
Make a firm commitment to automating whatever changes epochs/checkpoints get used for. For instance, we could introduce dyn Trait syntax tomorrow, but we could refuse to deprecate bare trait syntax until a
rustfix
tool is developed and polished to the point that every production user of Rust can simply runcargo fix
to wipe out whatever deprecation warnings they get afterrustup update
, or runcargo modernize
to both fix deprecations and update to the latest checkpoint. Bikesheds abound here, but you get the idea. In my opinion, this would be the best possible story for "breaking changes" that a language could possibly have, short of stagnating completely and refusing to ever change anything. -
Commit to not making any more "breaking changes" until the next epoch has actually happened and we've experienced the transition. Just stop at deprecating bare trait syntax and the one path-related deprecation in the latest modules proposal for now. As far as I know, there are no other compelling proposals for "breaking changes" at this time, so this seems like it's likely to happen regardless, but it might help our messaging if we formally agreed to not accept any more epoch/checkpoint-reliant proposals for the time being.
-
@glaebhoerl's suggestion that "before committing to any large-scale deprecations of existing syntax ... the relevant teams should proactively solicit feedback from the Friends of Rust and any other known potential stakeholders."
I'm making this post now because all of the epochs/checkpoints, modules, dyn Trait and lifetime elision proposals appear to be at the end of the road in terms of optimal design tradeoffs, except possibly for the migration stories, and none have been accepted yet, so we still have time to add stronger commitments on the migration stories if we do want them. So that's my question to everyone watching this forum: Should we commit to an even stronger "breaking changes story" by either specifying what changes are allowed, committing to implementing a seamless rustfix workflow, committing to no more epoch-using RFCs for a while, or something else I haven't thought of?
As you probably guessed from the title of the post, I'm most enthusiastic about #2, but I see no reason we couldn't do all of the above.