rust-lang/cargo

Specify supported Rust versions?

SimonSapin opened this issue · 13 comments

TL;DR: building Servo with the wrong Rust version is a terrible experience and easy to do by mistake, please help us make it harder.


Servo uses its own Rust snapshot, with each Servo commit targeting a specific commit. mach build in Servo downloads a snapshot if necessary, then calls cargo build with the PATH and LD_LIBRARY_PATH environment variables set so that Cargo uses the Rust snapshot.

However, people (myself included) regularly just type cargo build out of habit. Cargo will then use the Rust version installed system-wide if there is one, which might be a nigthly or a release, but is probably incompatible with Servo’s snapshot. Cargo will then start re-building everything (since we’ve changed Rust versions) before (probably) hitting a build error several minutes later. Even if the mistake it caught early and the developer is not utterly confused about what’s going on, the target directory has already been wiped and the developer is punished by having the next mach build do a full build from scratch, which takes a while.

We’ve filed servo/servo#3957 to do something about this, but I believe this requires some help from Cargo. Would it make sense for libraries to specify in Cargo.toml a range of Rust versions they support?

@Manishearth also suggests

Cargo.lock should probably store the rustc version it was compiled with (autogenerated, yay), Cargo.toml can store how fuzzy the rustc version is allowed to be.

This will probably become quite relevant post-1.0 when many devs will be maintaining 1.0 and nightly versions of their libraries (or at least be actively using both compilers on one machine). Since cargo itself lets you use whatever rustc you want, we could probably have a way to tell cargo where to find binaries for different versions, and it will pick the rustc it thinks will work best.

-----Original Message-----
From: "Simon Sapin" notifications@github.com
Sent: ‎11/‎11/‎2014 1:48 PM
To: "rust-lang/cargo" cargo@noreply.github.com
Cc: "Manish Goregaokar" manishsmail@gmail.com
Subject: [cargo] Specify supported Rust versions? (#837)

TL;DR: building Servo with the wrong Rust version is a terrible experience and easy to do by mistake, please help us make it harder.

Servo uses its own Rust snapshot, with each Servo commit targeting a specific commit. mach build in Servo downloads a snapshot if necessary, then calls cargo build with the PATH and LD_LIBRARY_PATH environment variables set so that Cargo uses the Rust snapshot.
However, people (myself included) regularly just type cargo build out of habit. Cargo will then use the Rust version installed system-wide if there is one, which might be a nigthly or a release, but is probably incompatible with Servo’s snapshot. Cargo will then start re-building everything (since we’ve changed Rust versions) before (probably) hitting a build error several minutes later. Even if the mistake it caught early and the developer is not utterly confused about what’s going on, the target directory has already been wiped and the developer is punished by having the next mach build do a full build from scratch, which takes a while.
We’ve filed servo/servo#3957 to do something about this, but I believe this requires some help from Cargo. Would it make sense for libraries to specify in Cargo.toml a range of Rust versions they support?
@Manishearth also suggests
Cargo.lock should probably store the rustc version it was compiled with (autogenerated, yay), Cargo.toml can store how fuzzy the rustc version is allowed to be.

Reply to this email directly or view it on GitHub.=

This is something that the Elixir project does with their build tool, Mix, and it seems to work pretty well. Pre-1.0, it did cause some headaches when a dependency was not updated regularly, but Rust users are pretty used to pre-1.0 headaches :)

I'm not sure that there's really anything that we can do about this now. The "Rust version" is primarily just a SHA, and no two versions have any relation to one another unless you have the actual repository lying around to connect the dots. We can't really specify a range of commits because you'd have to list each one individually, and you can't really predict a future version.

It's definitely unfortunate for now, but it's part of the pain of using a language that's still rapidly making breaking changes to the language and the libraries. After 1.0 we may want to add version markers, but they should actually have semantic meaning to ensure that they're comparable without a git repository on the side.

@alexcrichton you can use the commit hash, version, and date.

In the Cargo.toml you can specify if

  • Any rust version is allowed
  • Any rust version post the date in Cargo.lock is allowed
  • Only the rust hash specified in Cargo.lock is allowed
  • Any prerelease rust version with the same version number is allowed

or something like that

While in principle these are definitely constraints that we could implement, they may not semantically make a whole lot of sense:

Any rust version post the date in Cargo.lock is allowed

This isn't really what one would intend though, right? This is basically encoding that the rust nightlies at this specified date worked, and you're just predicting that every nightly into the future will still work. You can't really say at what point in the future a commit will land which will break your code, and once one does the rust requirement isn't so useful any more.

Only the rust hash specified in Cargo.lock is allowed

This is probably the most plausibly useful flavor of the requirements, but it's also super duper specific and I think that Servo is the only project that would use this for now. Although we just started archiving nightlies, I don't think that anyone else maintains a system to download an exact revision of a compiler.

Any prerelease rust version with the same version number is allowed

Semantically this makes sense, but practically I don't think we want to do this. The 0.12 series of compilers (anything with 0.12 in the version) are all wildly incompatible with one another and there's no way you could write some Rust which is compatible with the entire release.

In general this is just the hazards of working in an unstable language. Cargo will prevent all these problems by locking versions of dependencies and always downloading the same source, but this fundamentally doesn't work if the foundations of Cargo are themselves unstable. The rust compiler and standard library, some of the most basic foundations, are changing quite rapidly right now, and it's not really part of Cargo's mission to help out with that breakage right now I believe.

Well, what about the following granularity:

  • Nightly: Try to compile with the latest rustc
  • Pinned: Try to compile with a rustc of a given commit hash or release version

That seems like it would actually be useful post-1.0 (and it solves Servo's problem)

Cargo isn't responsible for downloading these, it's the user's responsibility to maintain multiple rustcs and tell Cargo where to find them.

I would personally rather not look into pinning to a specific hash or release version for now (for reasons above). Servo could get around this for now by not putting Cargo.toml in the root directory but perhaps in a subdirectory, and even after 1.0 it's unclear whether the ability to pin a compiler version will be desirable or not.

I think that for now there's not a lot actionable in this ticket, I agree that we'll definitely want to re-evaluate post-1.0, but for now I don't think cargo is going to enter the business of supporting various Rust versions as it's just too unstable to track currently.

@alexcrichton now that we're post 1.0, can we reopen this?

Nowadays discussion for this seems best suited at rust-lang/rfcs#1953 perhaps?

So you have to use nightly to really use Rust. And nightly breaks things. It would be really nice to specify "known working with 10.22.2017". otherwise a user who pulls a project never knows if it will build.

@shaleh You can now have a rust-toolchain file that contains nightly-2017-10-22. Servo does this. It’s a bit stronger than just “known to work”, though: it’ll make rustup select that exact version and download it if necessary, unless overridden.

@SimonSapin thank you. That works.