rust-lang / rust-analyzer

A Rust compiler front-end for IDEs
https://rust-analyzer.github.io/
Apache License 2.0
14.05k stars 1.56k forks source link

rust-analyzer prefers system rust over rustup rust #16661

Closed MabezDev closed 6 months ago

MabezDev commented 6 months ago

I know it is not recommended to have both rustup and system Rust installed. I would remove it if I could, but Gentoo requires it for building firefox etc. I still think r-a should be smart enough to use rustup's rustc (and tbh I'm really struggling to know how its finding it.).

Logs from r-a with log level set to "warn".

2024-02-24T16:09:48.416384Z  WARN project_model::target_data_layout: failed to run `cargo rustc --print target-spec-json`, falling back to invoking rustc directly: cd "/home/mabez/development/rust/embedded/util/embedded-fatfs" && RUSTC_BOOTSTRAP="1" RUSTUP_TOOLCHAIN="/opt/rust-bin-1.74.1" "cargo" "rustc" "--" "-Z" "unstable-options" "--print" "target-spec-json" failed, exit status: 101
stderr:
error: manifest path `/home/mabez/development/rust/embedded/util/embedded-fatfs/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace

2024-02-24T16:09:48.560416Z  WARN project_model::target_data_layout: failed to run `cargo rustc --print target-spec-json`, falling back to invoking rustc directly: cd "/home/mabez/development/rust/embedded/util/embedded-fatfs" && RUSTC_BOOTSTRAP="1" RUSTUP_TOOLCHAIN="/opt/rust-bin-1.74.1" "cargo" "rustc" "--" "-Z" "unstable-options" "--print" "target-spec-json" failed, exit status: 101
stderr:
error: manifest path `/home/mabez/development/rust/embedded/util/embedded-fatfs/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace

2024-02-24T16:09:48.690000Z  WARN project_model::target_data_layout: failed to run `cargo rustc --print target-spec-json`, falling back to invoking rustc directly: cd "/home/mabez/development/rust/embedded/util/embedded-fatfs" && RUSTC_BOOTSTRAP="1" RUSTUP_TOOLCHAIN="/opt/rust-bin-1.74.1" "cargo" "rustc" "--" "-Z" "unstable-options" "--print" "target-spec-json" failed, exit status: 101
stderr:
error: manifest path `/home/mabez/development/rust/embedded/util/embedded-fatfs/Cargo.toml` is a virtual manifest, but this command requires running against an actual package in this workspace

2024-02-24T16:09:48.798834Z ERROR rust_analyzer::main_loop: FetchBuildDataError:
error: package `embedded-fatfs v0.1.0 (/home/mabez/development/rust/embedded/util/embedded-fatfs/embedded-fatfs)` cannot be built because it requires rustc 1.75 or newer, while the currently active rustc version is 1.74.1

2024-02-24T16:09:48.897988Z ERROR flycheck: Flycheck failed to run the following command: CommandHandle { program: "cargo", arguments: ["check", "--workspace", "--message-format=json-diagnostic-rendered-ansi", "--manifest-path", "/home/mabez/development/rust/embedded/util/embedded-fatfs/Cargo.toml", "--all-targets"], current_dir: Some("/home/mabez/development/rust/embedded/util/embedded-fatfs") }

I'm using zsh, but all of my shells report the rustup rustc when running which rustc, e.g :

mabez at mGentoo ➜ mabez which rustc
/home/mabez/.cargo/bin/rustc
mabez at mGentoo ➜ mabez bash
[mabez@mGentoo ~]$ which rustc
/home/mabez/.cargo/bin/rustc
[mabez@mGentoo ~]$ sh
sh-5.1$ which rustc
/home/mabez/.cargo/bin/rustc
sh-5.1$

Any ideas?

rust-analyzer version: (eg. output of "rust-analyzer: Show RA Version" command, accessible in VSCode via Ctrl/⌘+Shift+P)

rust-analyzer version: 0.3.1850-standalone

rustc version: (eg. output of rustc -V)

From rustup: rustc 1.76.0 (07dca489a 2024-02-04) From system: rustc 1.74.1 (a28077b28 2023-12-04)

relevant settings: (eg. client settings, or environment variables like CARGO, RUSTC, RUSTUP_HOME or CARGO_HOME)

No other environment variables are set/modified from the default installation.

MabezDev commented 6 months ago

It looks like much of the toolchain discovery happens here: https://github.com/rust-lang/rust-analyzer/blob/4a8d0f7f565b6df45da5522dd7366a4df3460cd7/crates/toolchain/src/lib.rs#L62-L90.

I created a small demo depending on the unreleased toolchain crate:

fn main() {
    println!("Path to rustc => {}", toolchain::rustc().display());
    println!("Path to cargo => {}", toolchain::cargo().display());
}

Which outputs:

Path to rustc => rustc
Path to cargo => /home/mabez/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/cargo

Is this output expected? Wouldn't it better to output the absolute path here if we find it in the path? When it comes to executing rustc, do you know if r-a will take into account $PATH ordering? My $PATH has $HOME/.cargo/bin before /usr/bin.

MabezDev commented 6 months ago

I added some logging to the toolchain crate, and it looks like it is finding the correct rustc at /home/mabez/.cargo/bin/rustc in my path.

Veykril commented 6 months ago

The interesting part to look at should be here https://github.com/rust-lang/rust-analyzer/blob/4a8d0f7f565b6df45da5522dd7366a4df3460cd7/crates/project-model/src/workspace.rs#L231-L235

Basically what r-a does is it asks rustc where the sysroot is https://github.com/rust-lang/rust-analyzer/blob/4a8d0f7f565b6df45da5522dd7366a4df3460cd7/crates/project-model/src/sysroot.rs#L397-L407 from that point on, when we run any rust tool we set the RUST_TOOLCHAIN env var to the given sysroot and rely on the cargo home proxies to do the resolution through said env var. Obviously that fails should get_path_for_executable not resolve to a cargo proxy, but to your system rust install for some reason. This part of r-a is written with a rustup install in mind, so your setup here wasn't really considered (not to say that we wouldn't wanna support it)

Is this output expected?

Maybe? It entirely depends on your environment, given the function you've linked

MabezDev commented 6 months ago

Thanks for the pointers. I've built r-a locally and added some prints:

2024-02-24T20:43:00.499821Z  WARN project_model::sysroot: Discovering sysroot by cd "/home/mabez/development/rust/embedded/util/embedded-fatfs" && "rustc" "--print" "sysroot" with envs: {}
2024-02-24T20:43:00.508967Z  WARN project_model::sysroot: Found sysroot: /opt/rust-bin-1.74.1

and we can see it's found the wrong sysroot. However I can't for the life of me figure out why. In the test project from above, If I use Command to replicate the exact call r-a makes I still find the correct sysroot!

Any ideas?