Downside to using rust nightly as a default toolchain?

This might be a stupid question to ask, but here it goes.

Is there any downside to using the nightly toolchain as default? It is my understanding that the nightly chain only has extra stuff in it, which means all the stable stuff should work the same.

I need the nightly chain in or order for rustfmt to have certain options that it doesn't without it. I find it quite annoying to switch to nightly and back every time I run cargo fmt. So I was wondering what happens if I leave it on by default?

Am I exposing myself to potential bugs / security issues down the line?

The extra stuff in nightly might be removed at any point.

2 Likes

Right, but assuming I'm not relying on it anywhere in my code except for cargo fmt, are there any problems that might happen down the line (besides fmt not working one day)?

If you're just running cargo commands, you can cargo +nightly fmt instead of switching the default toolchain.

I think it would be harder to "restrain" oneself to stable items if you're working with the nightly toolchain. And there may be some other breakage in your code between nightly compiler version I'm not thinking of, traits added or removed little things.

4 Likes

There are sometimes bugs in nightly that sneak through CI. We hopefully catch those before they make it to release, due to heavier testing with crater and such, but you're more exposed on nightly.

But if you're okay with that, you can also be a source of early feedback when things do break! :slight_smile:

6 Likes

If cargo +nightly doesn't do it for you, I would probably set it via rustup override or rust-toolchain file, rather than setting it default everywhere. There are a few options for controlling the version used: Overrides - The rustup book (rust-lang.github.io)

1 Like

For some projects we have been using nightly for over a year now. In production. Because the Rocket web framework required features from nightly. Nothing bad has happened.

The trick is that "nightly", which implies not stable, not totally tested and liable to change at anytime, requires that if you have a working system you have to be able to get back to that exact night that it worked if some new nightly breaks things. So that you can keep operating running. You have to be prepared dive in and "fix" your code if a new nightly does break anything.

2 Likes

If you're just using cargo fmt via cargo +nightly fmt, no, that would be the only downside (though I've never personally had it happen).

Since nobody else has mentioned this, note that there are actually two ways of using nightly:

1. Always-latest nightly (for dev-side stuff)

This is nice for fire-and-forget / dev-side stuff, such as documentation, macro expansion, debugging, and whatnot. That is, for stuff non-critical enough (i.e., which downstream users don't use) so that breakage there, whilst bad, is not catastrophic. In that case, the main codebase is actually not using nightly, and the dev-side of things uses cargo +nightly … to run this stuff.

Problem

Breakage. nightly can change at any point, it's definitely its key aspect. While efforts are often made to avoid unnecessary breakage, the key idea is that in order for the very unstable features being used to evolve (and hopefully improve :upside_down_face:), breakage is a de facto necessity.

One good example of all this was the external_doc unstable feature, with its corresponding #![doc(include = "../README.md")] quite pervasive usage.

Such feature made a change "overnight" to simply disappearing, since the extended_key_value_attributes feature enabled a direct usage of #![doc = include_str!("../README.md")] which rendered the narrower feature useless. This caused "breakage" on any workflow that relied on it, such as on my own "future-proofing" cron-scheduled CI runs:

  • (which I had and have setup to detect such instances and try to provide feedback upstream in case of an actual meaningful breakage, which, again, to clarify, this one instance was not, since it was just "breaking" a nightly-only feature)

2. Pinned nightly

This is a way more reasonable approach for "standalone" codebases which use Rust internally to generate some kind of Rust-agnostic output (such as binary releases), and which thus might want to use nightly Rust to enable specific features. I believe this is a quite realistic scenario for companies out there. By pinning the specific toolchain through a rust-toolchain.toml file at the root of the repository, "future" versions of nightly, which could break compilation of the codebase, are not accidentally used, providing a reliable compilation environment. Then, whenever the toolchain needs to be updated for whatever reason, it can be done in a controlled environment and accompanied with the necessary code changes / amends to soothe any breakage that would have otherwise appeared.

The problem

This approach is clearly less problematic than most-up-to-date nightly, even though it does require this extra effort of performing the toolchain updates manually and carefully (but, imho, this effort is unavoidable when dealing with an unstable tool!!).

It does have an issue, however, caused by some approaches in the codebase / the community out there. Mainly, some crates, rather than featuring an actual nightly Cargo feature through which downstream users can opt into its nightly capabilities, (or, even better, specific Cargo features named as the nightly features they allow), are quite clever and "auto-detect" whether they are being compiled with a compatible toolchain (example), and in which case they enable the nightly features (example). This induces breakage since this detection approach is unable to tell different nightlies apart, so it just assumes that any nightly toolchain is the latest one. Note that I am not criticizing this approach / strategy; it's just that it's one that doesn't fare well with this "pinned nightly" approach (also, regarding that example, yeah, it may sound a bit silly to use a nightly that ended up pinned to a version prior to a stable toolchain release; at that point one could have used a 1.53.0-pinned RUSTC_BOOTSTRAP=1-imbued toolchain)

6 Likes

I've been using nightly as default for a few years now. I update it every couple of weeks, and before running rustup update, I always take a quick look at the Rust issues, to see if there are some glaring problems or not.

In my experience, it rarely breaks, I've had issues maybe twice in around 3 to 4 years of nightly usage.

1 Like

I used to use nightly by default, but switched to stable except on a per-project basis. I now prefer this for two reasons:

  1. Even ignoring bugs and feature gates, certain behaviors can be different on nightly, lasting for multiple releases. A current example is incremental compilation which is enabled on nightly so users observe all the ICEs and can report new ones. A past example which bit me (and I never got to the bottom of) is differences in span parsing of return information from inside procedural macros.
  2. I wanted the full user toolchain, e.g. rustfmt. These seem to be broken for a week or two at a time, and especially break right after the "no breakage week" once a new release is cut. Because of this, I couldn't upgrade to a new nightly version half the time anyway.

If these things are not important to you, then I would say go for nightly. But if you are doing open source crates, I would very highly recommend having CI check beta, and preferably either stable or an MSRV (minimum supported Rust version) to guard against my point 1.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.