h1
Rust 2020
-
2019-11-30
One month ago the Rust team put out a call for blogs 2020. I quite like these posts because it provides an occasion to provide perspective on all of Rust, by everyone. In this post I’ll look back at Rust’s development over 2019, and cover topics that seem important for Rust 2020.
The state of Rust
According to the 2019 StackOverflow survey, 8 out of 10 people that have tried Rust like it. But only 3% of developers are actually using Rust. Compared to a language such as JavaScript that has almost 2 out of 3 devs know and use, it seems we still have a long way to go.
Rust is uniquely positioned in that it provides a good story for front-end (30% of roles), back-end (50% of roles), and embedded (9% of roles) (src). These numbers overlap slightly as a single developer can fulfill multiple roles, but Rust has a remarkably wide range of potential applications.
Rust is currently heading in the right direction to address the market’s needs.
Polonius, Chalk, and improved diagnostics are chipping away at some of the
rough edges of working with the compiler. The WebAssembly WG has made Rust the
single best choice for use with WASM. And with async/.await
finally on stable
it seems we’re well on track to improve our presence in the web space as well.
The current path seems to be one that leads us to increased industry adoption,
which is a key component for Rust’s growth and success.
Editions
The core team has asked: “Should we have a Rust 2021 edition?” and the short answer is: “Yes we should, even if we don’t intend to change much.”
Despite only having had a single edition so far, 3 years seems to be a healthy pacing for editions. We had a release in 2015, another in 2018, and having another release in 2021 would be in line with that. Just like we don’t expect every 6-week release to be equally exciting, we shouldn’t expect each edition to introduce groundbreaking new changes either.
Having a regular cadence at which we release changes makes Rust predictable. This allows upstream vendors to anticipate toolchain upgrades. And allows enterprise users (whose number is steadily growing) to become accustomed to the 6-week stable, 3-year edition cycle. This provides much needed stability in a space that can feel like it’s moving at a high pace.
Timeline
Like Rust 2018, we’ll likely aim to release Rust 2021 in Q3 of the same year. If the last last 12 months of pacing are an indication of the pacing for next year, we should account for 6 weeks per year where the Rust project operates at a reduced pace (due to time off, travel, etc).
We should ensure all desired changes have completed their design + implementation well before the deadline. The 2018 edition had its deadline moved once last year, and even then ended up seeing some stressful last-minute backports. I don’t think anyone is keen on going through that again.
It seems wise to plan conservatively for the next edition, and aim to have all
planned edition changes on nightly for about 3 cycles, and in beta for 1 or 2
cycles. This roughly correlates to the progression async/await
had through the
release pipeline, and feature-wise shipping the next edition will likely be of
comparable scope. This amounts to a period of roughly 24-30 weeks.
All together that leaves us with about 12 months total to plan and prepare the next edition release, starting January 2020. This should be enough time to successfully plan and draft a new edition, with some slack to work with.
Organization
Management, community, and governance seem to be the difficult topics for many organizations. And we’re no different. Last year Boat’s laid out some of Rust’s challenges in this area in their organizational debt post. In 2019 work has been made to address some of these issues, so let’s review how we’ve done since:
- GitHub isn’t a great fit for lang design: This still rings true, but some steps are being taken.
- Project coordination isn’t smooth: There is now a bi-weekly cross-team meeting for all team leads. This is a good step, but alignment on vision still seems like something to improve on (more on the importance of that later).
- Teams are experiencing growing pains: This may have progressed the most. I’ve been seeing regular announcements of co-leads introduced in teams, and new sub-teams being split off to tackle specific issues.
- Working groups need a toolkit: The overarching idea is to provide more guidance with setting up teams. Given more sub-teams have been spun up recently I’m assuming some progress has been made.
- Community management is emotionally exhausting: It still is, and it seems little progress has been made in 2019. We’ve lost good people because of this, and we will continue to do so unless things change. It’s not good enough to onboard new people, we must also ensure we’re able to retain them.1
- It’s time to talk about pay: Contributors to Rust are still mostly unpaid. If we want people to see things through to completion they need to have the bandwidth to. And that means being paid.
Even if we’re leaving 2019 better than we started it, there seems to be a lot of work left to be done here. Organizational work is at the core of everything else that happens in the project, and above all else this seems to be the one thing we should keep improving. We’re growing fast, and our organization needs to grow with it.
Almost everybody involved in Rust I speak with regularly seems exhausted. Too few people have too much on their plate, and that’s not a good sign. What can we do about it though? My guess is somewhere between improving processes, and better support infrastructure.
Language
Lang Team
Over the past year I’ve been involved with the Lang Meta WG, whose goal it was to identify the friction points the lang team has, and how to fix them. Practical challenges with practical solutions. Niko wrote about some of the challenges lang design faces, and some of the steps that are being taken to help solve it.
Looking back at 2018, one of the biggest feats of the lang team getting Futures
and async/.await
to stable. But this process wasn’t pleasant, and ended up
taking a toll on many.
The lang team has taken the right steps in identifying what caused these issues, and proposing solutions to help solve them. There are many language features on the team’s backlog (GATs, specialization, etc.) and the main blocker right now seems to be the bandwidth to see them through to completion.
The lang team is doing the right thing with the Shepherds design, ensuring people are responsible for features, and creating a space of focus – rather then a place where it can feel like everyone needs to react to everything, all the time.
It would be great if the language team would write more beyond the space of RFCs and internal threads. Classics such as “borrowing in async code”, “async await VI: 6 weeks of great progress”, and “stacked borrows 2.0” have done a great job at looping the wider Rust community in on important developments.
Quantitatively speaking a small group of people produce the majority of these posts, and despite their clear value writing writing posts is not an expected part of the design process. We now have the inside Rust blog so even the unblogged have a venue they can publish their writing2. I’d love to see more people write more over the next year; as the amount of Rust users is projected to grow, and we’ll need to continue improving our communication.
e.g. people without blogs. Like me prior to 2019.
Language Features
In terms of language features I don’t really have priorities. I’m not on the lang team, and don’t quite know the dependency tree for my fave features.
The only thing I would add is that since this would be the time to ramp-up the efforts for a 2021 edition, it’d be good to look at which keywords may want to be reserved in anticipation for this.3 I don’t suspect we’ll have changes that are quite as large as, say, changing how imports work. But it’s something that probably needs to be covered. Extra good if this could be done in a structured way, say, as an artifact of a shepherding effort.
Syntax for delegation would be pretty amazing. This would’ve been fantastic to have for the last few project’s I’ve worked on. It came up in the last edition, but was put on hold.
Compiler
I know little about the compiler, so I guess the best I can do is share that as an onlooker: It seems that things keep progressing steadily and overall quite good.
Whether it’s if/else/match
in const
contexts.
Excellent
diagnostics.
Or implementing
async/.await
. It
seems a lot of care and thought goes into building the compiler; and it’s really
nice to see it improve. Not just in features, but in performance as well!
Similarly I feel the infra and release teams are doing a great job, and like, I’m thankful for all the work they’re doing so folks like myself get to try out all of our weird experiments on a platform that feels incredibly reliable.
Libraries
The standard library is the shared core that underpins all of Rust. It’s arguably on par with the language itself in defining how we structure our programs.
Stable, Popular, Small
In the past 4 years the Rust ecosystem has seen some impressive developments. We now have a rich ecosystem of stable modules. And it seems the time is right to start looking into whether we can include some of that into the stdlib. Boats formulated a great heuristic for what to include:
“stable, popular, and small is std’s bread and butter”
Applying this label some obvious candidates for inclusion in stdlib are:
matches
, num_cpus
, and crossbeam::scope
. There’s probably many
more, and in 2020 I would like to see the libs team move to include some of
these.
Errors
Additionally there seem to be some steps we could take to improve Rust’s error handling story, solidifying existing patterns. I’ve recently written about this, but the conclusion was there is rough ecosystem consensus we need:
- Some kind of replacement for
Box<dyn Error + Send + Sync + 'static>
- Some way of wrapping
Results
in.context
. - Some way to conveniently define new error types.
- Some way to iterate over error causes (#58520).
- Support for backtraces (#53487).
Communication
Similar to the lang team, I would love to see the libs team blog more in 2020. External communication is a key factor in growing Rust while preserving our identity. And given the importance of the standard library, contextualizing design decisions is something we could use more of.4
For an example of what a “libs team post” looks like: global executors.
Tooling
Rust is as a tool that enables the wider software industry to write software that’s both correct and performant, even under deadlines. The fact that Rust is a programming language is somewhat incidental; it just happens to be the best way to achieve those goals.
Tooling in Rust is crucial. They make up a large part of “Rust, the product” together with the docs, crates.io, and the compiler.5 As such an effective way to talk about tooling is to talk about Rust as a whole, and the experience we provide for users of Rust.
Calling rust a “product” might sound odd at first. But if we look beyond the price tag (free), it has all the hallmarks of a product. We’ve got a value proposition, competition, design, and product positioning. Viewing Rust as a product seems like a useful lens to think of how we could improve.
Onboarding
I recently drafted a small guide to onboard JavaScript people onto Rust.
However the Quick Start section isn’t very quick. It starts off by explaining
how to install rustup
, only to proceed to explain cargo-edit
,
cargo-fmt
, cargo-clippy
, and cargo-watch
, and how to install them.
Some of these are rustup components, others are regular crates. And put together
getting started isn’t exactly frictionless.
And that’s not even explaining how to setup editors. Or use cases Rust promotes
such as embedded development and WebAssembly. Installing rustup
and rustc
only installs a part of “Rust, the product”. Core pieces such as cargo fmt
or
cargo add
are not mentioned anywhere, and people either need to actively
search for them or find out about them from others.
Onboarding Rust shouldn’t be an 8 step process. It should match what people expect on their respective platforms. And even better: we should explore ways we can explain the different tools to people so their first experience isn’t one of trial-and-error.
Continuous Integration
Running Rust as part of CI builds is not without issues. The most common way people seem to be integrating Rust these days seems to be to copy and paste a template from somewhere else.
This is not great for many reasons. But not in the least because libraries are often not tested for multiple platforms, checking if a library compiles on WebAssembly is often skipped, and cache management often has much to be desired.
Continuous Integration is a huge part of real-world Rust usage, yet we don’t provide much guidance. Community projects such as actions-rs have sprung up to fill the gap, but even though they’re often of excellent quality, this feels like a core workflow of “Rust, the product” that should be considered.
There are many steps we could take from here, and which is best depends on the willingness of people involved, and overall bandwidth. But I wanted to put this on the map as something we should be thinking about, but traditionally haven’t much.
Consistency
As “Rust, the product” is a single entity, the tools it’s made up of should be consistent between each other. This means using the same names for the same things across projects. But also using similar flags, a similar tone of voice, and feel.
But Rust’s components should not just be consistent with each other. They should
also be approachable for people coming from other ecosystems. For example cargo clippy
is a reference to a meme from
the 90s, and if you’re not in the joke the command makes no sense. As it’s being
considered to become a cargo
built-in, people are rightly
asking whether using a more conventional term might better match people’s
expectations.
Both internal and external consistency are crucial considerations in Rust’s design. Rust as a language has a limited strangeness budget. But so does Rust as a product.
WebAssembly
WASM on the server
WebAssembly on the server has been seeing huge leaps forward over the past year. WASI, the system interface for WebAssembly6, has seen great development. And with the announcement of the bytecode alliance it seems some major players have become stakeholders in WASM’s success.
If you’re confused by what WASI is; I like to think of it as: “What if POSIX worked on every platform, and also had versioning and permissions built in? And also wasn’t restricted just to filesystem APIs, but could include high-level things as well.” It almost sounds too good to be true, but the people working on this are incredible so I’m somewhat optimistic they’ll actually be able to pull this off.
Rust currently has one of the most mature WASM/WASI toolchains of any language. This has been greatly beneficial, as it allows Rust implementations to influence specs, and in turn specs help guide the implementations. This seems like a mutually beneficial relationship for both Rust and WASM, which would be great to continue into the next year.
However in terms of production use I haven’t seen WASM being used much on the server. Both Fastly and CloudFlare have products available, but it seems like it’s still early days. Either way, this is just a long way of saying that the direction Rust is currently on regarding WASM/WASI seems right, and is something we should continue into the next year.
WASM in the browser
WASM in the browser is an interesting one. While it feels that WASM on the
server is seeing a lot of active development, WASM in the browser seems to have
taken more of a backseat. However this year did see the release of the
js-sys
and web-sys
crates which provide the ability to bind to the full
range of APIs the browsers have to offer.
What I’d like to see in 2020 is to allow people to start building projects in the browser. Rust could have a similar value proposition as Elm for browser development; stable, type-checked applications that don’t crash and are a joy to write. But unlike Elm, Rust covers a much wider range of applications, which brings it closer to JavaScript’s value proposition of writing “isomorphic code” 7.
“isomorphism” is a term used a lot in JavaScript: it describes code that works in both the browser and on the server. I have long suspected “isomorphic Rust” could also be a thing, and having implemented an HTTP client that works in both browser and server this seems likely to be true.
I don’t think there’s a lot of work required here for people to get started.
Now that async/.await
has landed on stable, and {js,web}-sys
exist, the main
things we need to do are:
- Create an ergonomic Rust interface to the DOM.
- Add a
serve
command towasm-pack
. - Write a short guide on how to do DOM-related tasks.
Much of this work has already in some form of another. But it doesn’t feel whole yet; there’s still a lot left to do, and I hope people will find the time in the next 12 months to do so.
Async
The async/.await
MVP was stabilized in Rust 1.39 three weeks ago. This has
marked a major milestone in Rust’s development, and has set us to start
exploring fields we’ve traditionally not had a strong presence in such as web
services and user interfaces.
I hope in 2020 we can continue the work that was done over the past year, and continue to encourage innovation, but also standardize the things we have consensus on. The async interviews seem like an excellent first step in finding what those are, and what should be prioritized8.
From my work on async-std
async closures seem like a high priority, followed
by async traits.
I like the interviews approach a lot: gathering input from stakeholders and summarizing it to prioritize feature development. I wish we would do more of this.
Conclusion
In this post I’ve covered whether we should have a new edition, a rough timeline for a new edition, and the different aspects of the Rust language. To summarize what we’ve covered:
- Yes, we should have a 2021 edition because operating on a predictable timeline is good for vendors, community, and enterprise alike.
- The bulk of the work for the 2021 release should be done during the calendar year of 2020. This includes reserving keywords.
- The language team has made great steps by acknowledging it has an issue of unbounded queues, and has taken steps towards shepherding. This should be continued next year.
- Thinking about Rust as a product is a useful lens, and among other things we might want to think about our onboarding and CI flows.
- WASM on the server seems to be progressing steadily, and with a bit of attention we can improve our experience in the browser too.
I feel Rust 2020 will be a continuation of the work done in 2019. Which in turn was a continuation of the work of 2018. And I suspect 2021 will be much the same. I don’t think this is an accident: Rust knows what it’s trying to be, and much of the work left to do is about polish, finishing things we’ve started, and making things easier.
I’m very excited about where the Rust project is headed, and keen to see how it’ll evolve as fields such as Async Rust and WebAssembly continue to expand.