rust-lang / cargo

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

Bad .rustc_info.json caused nightly cargo to use beta rustc #9500

Open CAD97 opened 3 years ago

CAD97 commented 3 years ago

Problem

With a stale .rustc_info.json, I observed that D:\.rust\rustup\toolchains\nightly-x86_64-pc-windows-msvc\bin\cargo.exe build --release --target-dir D:\path\to\target\dir failed, reporting error[E0554]: `#![feature]` may not be used on the beta release channel. Omitting the --target-dir allows the project to compile cleanly in the default target directory. Additionally, deleting the .rustc_info.json allowed compilation to succeed.

Steps

Original information I have no idea whether this will reproduce on another machine. Building with the bad `.rustc_info.json` in place on my machine consistently produces the error if (and only if) the build isn't fresh.
Bad .rustc_info.json ```json { "rustc_fingerprint": 3894061304317293000, "outputs": { "2797684049618456168": { "success": false, "status": "exit code: 1", "code": 1, "stdout": "", "stderr": "error: `-Csplit-debuginfo` is unstable on this platform\n\n" }, "931469667778813386": { "success": true, "status": "", "code": 0, "stdout": "___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nD:\\.rust\\rustup\\toolchains\\beta-x86_64-pc-windows-msvc\ndebug_assertions\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"pc\"\nwindows\n", "stderr": "" }, "17598535894874457435": { "success": true, "status": "", "code": 0, "stdout": "rustc 1.54.0-nightly (79e50bf77 2021-05-10)\nbinary: rustc\ncommit-hash: 79e50bf77928f374921a6bcafee3fcff1915f062\ncommit-date: 2021-05-10\nhost: x86_64-pc-windows-msvc\nrelease: 1.54.0-nightly\nLLVM version: 12.0.1\n", "stderr": "" } }, "successes": {} } ```
Clean generated .rustc_info.json ```json { "rustc_fingerprint": 3894061304317293000, "outputs": { "17598535894874457435": { "success": true, "status": "", "code": 0, "stdout": "rustc 1.54.0-nightly (79e50bf77 2021-05-10)\nbinary: rustc\ncommit-hash: 79e50bf77928f374921a6bcafee3fcff1915f062\ncommit-date: 2021-05-10\nhost: x86_64-pc-windows-msvc\nrelease: 1.54.0-nightly\nLLVM version: 12.0.1\n", "stderr": "" }, "2797684049618456168": { "success": false, "status": "exit code: 1", "code": 1, "stdout": "", "stderr": "error: `-Csplit-debuginfo` is unstable on this platform\n\n" }, "931469667778813386": { "success": true, "status": "", "code": 0, "stdout": "___.exe\nlib___.rlib\n___.dll\n___.dll\n___.lib\n___.dll\nD:\\.rust\\rustup\\toolchains\\nightly-x86_64-pc-windows-msvc\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"msvc\"\ntarget_family=\"windows\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_has_atomic_equal_alignment=\"16\"\ntarget_has_atomic_equal_alignment=\"32\"\ntarget_has_atomic_equal_alignment=\"64\"\ntarget_has_atomic_equal_alignment=\"8\"\ntarget_has_atomic_equal_alignment=\"ptr\"\ntarget_has_atomic_load_store=\"16\"\ntarget_has_atomic_load_store=\"32\"\ntarget_has_atomic_load_store=\"64\"\ntarget_has_atomic_load_store=\"8\"\ntarget_has_atomic_load_store=\"ptr\"\ntarget_os=\"windows\"\ntarget_pointer_width=\"64\"\ntarget_thread_local\ntarget_vendor=\"pc\"\nwindows\n", "stderr": "" } }, "successes": {} } ```

Notes

No rustup override is present in either the working nor the target directory. Beta is my default toolchain. (I'm attempting to integrate Rust into a larger C++ compilation environment, thus I'm not sure the exact sequence of cargo/rustc versions that got used while hacking on this.)

Beta version: cargo 1.53.0-beta (4369396ce 2021-04-27) / rustc 1.54.0-nightly (79e50bf77 2021-05-10)
Nightly version: cargo 1.54.0-nightly (e51522ab3 2021-05-07) / rustc 1.54.0-nightly (79e50bf77 2021-05-10)

This was done with $env:CARGO_INCREMENTAL=0.

CAD97 commented 3 years ago

Observation: the bad .rustc_info.json has the same rustc_fingerprint but has a beta toolchain path in 931469667778813386.

Scary observation: deleting just the .rustc_info.json and not the build directory lead to a different build error that suggested a proc macro I'm using didn't get run, and cleaning the target directory fully then allowed the build to succeed. This suggests that we were using out-of-date compilation results and got bad results back 😬

alexcrichton commented 3 years ago

Without knowledge of how you got into this state or a way to reproduce this there's unfortunately not a ton that we can probably help out with here. My only other guess would be that you might have at some point had concurrent Cargo invocations and Cargo's file locking didn't work so there was no protection against this. (file locking is opportunistic in that if it fails we keep going)

Other than that though it seems like there might be a bug here, but this isn't too actionable if reproduction is unknown...

ehuss commented 3 years ago

I'm a bit confused on the point where you say the default toolchain is beta, but it looks like you are building with nightly. How are you selecting the nightly toolchain? Why is the default beta if it is running with nightly?

I would be very cautious about running cargo out of the rustup directory. This prevents the rustup env vars from being set properly and causes problems with overrides.

In looking, I did notice a bug. This line is not working as expected (it is comparing rustc to ~/.cargo/bin/rustc which is always false). It's unlikely to be related unless ~/.cargo/bin/rustc is not the rustup wrapper.

CAD97 commented 3 years ago

Without knowledge of how you got into this state or a way to reproduce this there's unfortunately not a ton that we can probably help out with here.

I figured out a reproducer from no preexisting target state, now in the OP. It's a build with an absoute path to beta cargo, then with an absolute path to nightly cargo.

But yeah, I understand there's not much actionable here; whatever sequence got me to this point involved multiple cargo versions and working around rustup rather than with it. My best guess looking at the symptom is that some parts are using $CARGO_HOME/rustc and some are using $EXE_DIR/rustc (or some other mismatch along those lines -- I have $CARGO_HOME and $RUSTUP_HOME globally set).

I'm a bit confused on the point where you say the default toolchain is beta, but it looks like you are building with nightly. How are you selecting the nightly toolchain? Why is the default beta if it is running with nightly?

My rustup default is set to beta, and no rustup overrides are set either for my working directory, the manifest directory, or the target directory. The intent is to from the orchestrating build system find nightly cargo via rustup which cargo --toolchain nightly and then use nightly cargo/rustc for Rust compilation. (For reasons out of my control, the orchestrating build system requires absolute paths to everything that it runs.)

I would be very cautious about running cargo out of the rustup directory. This prevents the rustup env vars from being set properly and causes problems with overrides.

If this is explicitly not a supported configuration (fair!) I can take a different approach. There are interesting constraints on my usage (the big one being absolute paths only, which I have to discover somehow, and rustup which was just very convenient) but I can try to work with rustup instead of against it; I'm still in early prototyping phase on the integration. I'm trying to avoid running rustc directly and abandoning cargo (I want to keep the crates ecosystem available), but other constraints (e.g. using the existing C++ linker, Rust build support is opt-in and rustup/cargo/rustc are not required to be installed if you're not building Rust) may make that my best approach.

In looking, I did notice a bug. This line is not working as expected (it is comparing rustc to ~/.cargo/bin/rustc which is always false). It's unlikely to be related unless ~/.cargo/bin/rustc is not the rustup wrapper.

Looking at that myself, it does look like it would have prevented me running into this issue, as the comparison probably should've been true, and I don't have $RUSTUP_TOOLCHAIN set, so it should've bailed as running rustup rustc but not under rustup environment.