rust-lang / cargo

The Rust package manager
https://doc.rust-lang.org/cargo
Apache License 2.0
12.75k stars 2.42k forks source link

Cargo should set "rust-version" for me #11451

Open mcclure opened 1 year ago

mcclure commented 1 year ago

Problem

As of 1.56 Rust supports a "rust-version" key in Cargo.toml. I love this. I am always nervous about Rust upgrades breaking my code and just last week I hit a confusing error building a project from GitHub, which would have been easy to resolve if the project had used rust-version (but it didn't). I now want to use rust-version in every one of my projects.

However, checking my Rust version and typing it out in the Cargo.toml is a bit obnoxious, and maybe I, a fallable human, will forget the quotation marks or forget if it goes in [package] or some other section or... hm. Cargo does many things for me automatically, such as set the name, version and edition. Cargo should set rust-version for me.

Proposed Solution

In general, Cargo should probably not set rust-version because many programs will incidentally work on versions of Rust older than the one they were initially created with. However, for paranoid folk like me who are making software not for wide distribution, an option should exist to automatically set the rust-version to the current Rust version. This behavior is conservative (it will cause builds to fail on some versions of Rust that might in practice work) but accurate as it is setting the key to the earliest version known to work.

I would expose this in two ways:

Notes

Questions I don't have answers to:

Could this be a Cargo plugin?

I find many Cargo plugins in the package registry. If this could be implemented as a Cargo plugin, I would be happy to implement and release that myself. However, looking at the Cargo docs, my understanding is Cargo plugins can only add new cargo commands. Therefore cargo update-rust-version could be implemented by a Plugin, but the automatic behavior on cargo new— checking for the config key and adding to the package automatically, which is the more useful feature in the first place— could not. Am I missing something?

What about workspaces?

I dunno

Should there also be a cargo set-rust-version 1.65 command?

I guess??

Could cargo update-rust-version figure out the minimum working version automatically? (IE scan code to see which features are used?)

That sounds hard, and would catch compile errors but not logic/behavior bugs?

epage commented 1 year ago

Huh, for some reason I thought we had an issue for cargo new setting package.rust-version but all I found was #10870. I think that could make sense.

Overall, someone had suggested we collect all of the rust-version ideas to make sure we create a coherent story out of them. I've added it to the list at https://github.com/rust-lang/libs-team/issues/72#issuecomment-1308130499

Kixunil commented 1 year ago

For me it'd be nice to have a global configuration file to set default version. I often develop on higher versions of the compiler (mainly to get better error messages) but target lower versions.

epage commented 1 year ago

A per user setting seems off as people would likely set it for different projects for different needs but I could see pulling from a config file found near the projects as that is then more project focused. Of course, this both means the same thing implementation wise, just weighing the value of different use cases.

Granted, we also have #10870 which would help people have it actually set in their manifests within a workspace.

epage commented 1 year ago

Something I left out of my previous comment that we would need to consider for when sourcing the package.rust-version from an alternative source is the risks associated with it not being a visible, tracked value. The MSRV could capriciously go up or down, depending on which user published and what they are doing. I almost wonder if we should have a "published-rust-version` field in the index as a fallback with a different error message, if we do anything.

Kixunil commented 1 year ago

How about project config overrides the global default? Makes a lot of sense to me but maybe I'm missing something?

I'm not sure what do you mean by your second comment since the proposal is to put rust-version into Cargo.toml on cargo new which is visible and tracked.

epage commented 1 year ago

My bad, I got this mixed up with something else.

hhartzer commented 7 months ago

I'm not a direct Rust user/developer, just wanted to give my two cents.

I normally run into Rust through installing Python packages, where many Python packages are using Rust behind the scenes. Unfortunately for many of them, they set a rust-version that is too low while using new features, resulting in cryptic errors.

If there was some way to detect that new Rust features were being used and warn/error/update on publishing, I think that would be great. rust-version in Cargo.toml seems like a useful feature to have, just currently misused fairly often. I've run into this often enough to assume that if a Python/Rust package fails to build, it's probably because my Rust version is too old and the package hasn't set the rust-version argument appropriately.

I have no idea how hard it would be to do this, of course. May be much easier said than done, but I was hoping it was at least on the radar.

Edit:

Is this a thing already?

epage commented 7 months ago

Set a version too low or don't set it at all? I ask because there is a difference in expectation between the two.

Do you have examples of packages where this has been a problem? This isn't a call to shame them but to better understand decisions, workflows, etc.

We just approved an RFC that should make it easier to maintain an MSRV. For those not putting in that work, we included a "set to my toolchain version" opt-in feature that is opted-in by cargo new.

Verification on publish has some challenges. An external tool like cargo-msrv can assume rustup is available while cargo can't. A "guess" on publish runs into that as well and i worry about false positives. I also suspect these observationally picked MSRVs would be more frustrating for most of everyone involved. For the "upgrade grace period but I don't mind being behind" case it works. For most other cases, a predictable policy is needed. For more mature packages, there would also be a desire to limit MSRV bumps to minor versions to allow fixes to be backported.

Kixunil commented 3 months ago

A per user setting seems off as people would likely set it for different projects for different needs

One more note about this: I use separate VMs for different projects to improve security (Qubes OS) but I do put related crates in the same VM even if they don't share a workspace so having the option makes sense.