Repository: intellij-rust/intellij-rust
Issue: toolchain location not included in PATH passed to cargo

Hello! We are big fans of this plugin in [Fuchsia](https://fuchsia.dev).

In Fuchsia, we use self-contained rust toolchains, which means that our `cargo`, `rustc`, etc. are not usually in our PATH. This seems to be a problem for this plugin because `cargo` is executed with intellij's PATH, and is then unable to find `rustc`.

Would it be possible to execute cargo with the toolchain location (specified in the plugin's settings) appended to PATH?

cc @brunowonka

Changed files:
src/main/kotlin/org/rust/cargo/toolchain/Cargo.kt, src/test/kotlin/org/rust/cargo/toolchain/CargoTest.kt, src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt

diff --git a/src/main/kotlin/org/rust/cargo/toolchain/Cargo.kt b/src/main/kotlin/org/rust/cargo/toolchain/Cargo.kt
index 32d75c36a..2afcf632e 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/Cargo.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/Cargo.kt
@@ -57,7 +57,7 @@ import java.nio.file.Paths
  * It is impossible to guarantee that paths to the project or executables are valid,
  * because the user can always just `rm ~/.cargo/bin -rf`.
  */
-class Cargo(private val cargoExecutable: Path) {
+class Cargo(private val cargoExecutable: Path, private val rustcExecutable: Path) {
 
     data class BinaryCrate(val name: String, val version: SemVer? = null) {
         companion object {
@@ -301,7 +301,7 @@ class Cargo(private val cargoExecutable: Path) {
                 parameters,
                 emulateTerminal,
                 http
-            )
+            ).withEnvironment("RUSTC", rustcExecutable.toString())
         }
 
     @Throws(ExecutionException::class)
diff --git a/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt b/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt
index 4a8a9f564..9964217fd 100644
--- a/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt
+++ b/src/main/kotlin/org/rust/cargo/toolchain/RustToolchain.kt
@@ -61,12 +61,12 @@ data class RustToolchain(val location: Path) {
         return if (output?.isSuccess == true) output.stdoutLines else null
     }
 
-    fun rawCargo(): Cargo = Cargo(pathToExecutable(CARGO))
+    fun rawCargo(): Cargo = Cargo(pathToExecutable(CARGO), pathToExecutable(RUSTC))
 
     fun cargoOrWrapper(cargoProjectDirectory: Path?): Cargo {
         val hasXargoToml = cargoProjectDirectory?.resolve(XARGO_TOML)?.let { Files.isRegularFile(it) } == true
         val cargoWrapper = if (hasXargoToml && hasExecutable(XARGO)) XARGO else CARGO
-        return Cargo(pathToExecutable(cargoWrapper))
+        return Cargo(pathToExecutable(cargoWrapper), pathToExecutable(RUSTC))
     }
 
     fun rustup(cargoProjectDirectory: Path): Rustup? =
diff --git a/src/test/kotlin/org/rust/cargo/toolchain/CargoTest.kt b/src/test/kotlin/org/rust/cargo/toolchain/CargoTest.kt
index e5ea4f5d2..ec823a739 100644
--- a/src/test/kotlin/org/rust/cargo/toolchain/CargoTest.kt
+++ b/src/test/kotlin/org/rust/cargo/toolchain/CargoTest.kt
@@ -18,19 +18,19 @@ class CargoTest : RsTestBase() {
     fun `test run arguments preserved`() = checkCommandLine(
         cargo.toColoredCommandLine(project, CargoCommandLine("run", wd, listOf("--bin", "parity", "--", "--prune", "archive"))), """
         cmd: /usr/bin/cargo run --color=always --bin parity -- --prune archive
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
         """, """
         cmd: C:/usr/bin/cargo.exe run --color=always --bin parity -- --prune archive
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
     """)
 
     fun `test basic command`() = checkCommandLine(
         cargo.toGeneralCommandLine(project, CargoCommandLine("test", wd, listOf("--all"))), """
         cmd: /usr/bin/cargo test --all
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
         """, """
         cmd: C:/usr/bin/cargo.exe test --all
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
     """)
 
     fun `test propagates proxy settings`() {
@@ -46,48 +46,48 @@ class CargoTest : RsTestBase() {
         checkCommandLine(
             cargo.toGeneralCommandLine(project, CargoCommandLine("check", wd)), """
             cmd: /usr/bin/cargo check
-            env: RUST_BACKTRACE=short, TERM=ansi, http_proxy=http://user:pwd@host:3268/
+            env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi, http_proxy=http://user:pwd@host:3268/
             """, """
             cmd: C:/usr/bin/cargo.exe check
-            env: RUST_BACKTRACE=short, TERM=ansi, http_proxy=http://user:pwd@host:3268/
+            env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi, http_proxy=http://user:pwd@host:3268/
         """)
     }
 
     fun `test adds colors for common commands`() = checkCommandLine(
         cargo.toColoredCommandLine(project, CargoCommandLine("run", wd, listOf("--release", "--", "foo"))), """
         cmd: /usr/bin/cargo run --color=always --release -- foo
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
         """, """
         cmd: C:/usr/bin/cargo.exe run --color=always --release -- foo
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
     """)
 
     fun `test don't add color for unknown command`() = checkCommandLine(
         cargo.toColoredCommandLine(project, CargoCommandLine("tree", wd)), """
         cmd: /usr/bin/cargo tree
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
         """, """
         cmd: C:/usr/bin/cargo.exe tree
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
     """)
 
     fun `test adds nightly channel`() = checkCommandLine(
         cargo.toColoredCommandLine(project, CargoCommandLine("run", wd, listOf("--release", "--", "foo"), channel = RustChannel.NIGHTLY)), """
         cmd: /usr/bin/cargo +nightly run --color=always --release -- foo
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
         """, """
         cmd: C:/usr/bin/cargo.exe +nightly run --color=always --release -- foo
-        env: RUST_BACKTRACE=short, TERM=ansi
+        env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
     """)
 
     @MockRustcVersion("1.36.0")
     fun `test adds --offline option`() = withOfflineMode {
         checkCommandLine(cargo.toColoredCommandLine(project, CargoCommandLine("run", wd, listOf("--release", "--", "foo"))), """
             cmd: /usr/bin/cargo --offline run --color=always --release -- foo
-            env: RUST_BACKTRACE=short, TERM=ansi
+            env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
             """, """
             cmd: C:/usr/bin/cargo.exe --offline run --color=always --release -- foo
-            env: RUST_BACKTRACE=short, TERM=ansi
+            env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
         """)
     }
 
@@ -95,10 +95,10 @@ class CargoTest : RsTestBase() {
     fun `test adds -Zoffline`() = withOfflineMode {
         checkCommandLine(cargo.toColoredCommandLine(project, CargoCommandLine("run", wd, listOf("--release", "--", "foo"))), """
             cmd: /usr/bin/cargo -Zoffline run --color=always --release -- foo
-            env: RUST_BACKTRACE=short, TERM=ansi
+            env: RUSTC=/usr/bin/rustc, RUST_BACKTRACE=short, TERM=ansi
             """, """
             cmd: C:/usr/bin/cargo.exe -Zoffline run --color=always --release -- foo
-            env: RUST_BACKTRACE=short, TERM=ansi
+            env: RUSTC=C:/usr/bin/rustc.exe, RUST_BACKTRACE=short, TERM=ansi
         """)
     }