Skip to content

Conversation

@smoelius
Copy link
Contributor

@smoelius smoelius commented Oct 18, 2025

This PR implements the cargo changes for #11036. The rustup changes were implemented in rust-lang/rustup#4518.

The PR is currently organized as four commits:

  • The first expands the rustup tests to set RUSTUP_TOOLCHAIN_SOURCE. This change is not strictly necessary, but it improves the rustup tests' fidelity.
  • The second moves the pkg function to a location where the next commit can use it.
  • The third implements a test to check the fourth commit's fix.
  • The fourth warns when cargo install is invoked with a non-default toolchain, as indicated by RUSTUP_TOOLCHAIN_SOURCE.

In the third commit, two significant changes were made to simulated_rustup_environment:

  • Previously, the constructed proxy would call an always-panicking executable whenever it was asked to run cargo. Now, the proxy can be made to run the cargo under test.
  • The proxy can now be made to set additional environment variables (e.g., RUSTUP_TOOLCHAIN_SOURCE) before calling the proxied tool.

The PR is currently marked as draft because rust-lang/rustup#4518 has not yet been released. Technically, this PR could be merged before then. But testing it with a fixed rustup would seem to make sense.

Nits are welcome.

cc: @epage

@rustbot rustbot added Command-install S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Oct 18, 2025
@rustbot
Copy link
Collaborator

rustbot commented Oct 18, 2025

r? @weihanglo

rustbot has assigned @weihanglo.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@smoelius smoelius marked this pull request as draft October 18, 2025 09:36
@rustbot rustbot removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Oct 18, 2025
@smoelius smoelius force-pushed the second-half-of-11036 branch from 2157847 to 9006944 Compare October 18, 2025 09:52
Copy link
Member

@weihanglo weihanglo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

EDIT: The force push was to make Clippy happy.

Feel free to force-push and re-organize your commits during the iterations.

/// Performs a `cargo install` with a non-default toolchain in a simulated
/// rustup environment. The purpose is to verify the warning that is emitted.
#[cargo_test]
fn cargo_install_with_non_default_toolchain() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should likely have cargo install tests for

  • Rustup that doesn't set RUSTUP_TOOLCHAIN_SOURCE
  • For each value of RUSTUP_TOOLCHAIN_SOURCE
  • For an unknown value of RUSTUP_TOOLCHAIN_SOURCE (handling future cases where new values are added)

Comment on lines +341 to +343
&& !matches!(
source,
RustupToolchainSource::Default | RustupToolchainSource::CommandLine
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Downside to matches! is we can miss it if new values are added. For now, that is not likely to happen as this is all for one feature. That might not always be the case.

I would

  • Move the &str -> RustupToolchainSource to a function on get_rustup_toolchain_source (shouldn't touch gctx)
  • Have a function on RustupToolchainSource that lts is ask the question we are asking here and uses a match with every case enumerated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I follow what you're asking for.

Could you give me some pseudo-code? Or could you point to a function that uses this pattern?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move the &str -> RustupToolchainSource to a function on get_rustup_toolchain_source (shouldn't touch gctx)

That has happened

Have a function on RustupToolchainSource that lts is ask the question we are asking here and uses a match with every case enumerated

impl RustupToolchainSource {
    fn is_current_dir_override(&self) -> bool {
        match self {
        }
    }
}

(name is not prescriptive, just the first thing I could think of for what might describe what we care about)


fn get_rustup_toolchain_source(&self) -> Option<RustupToolchainSource> {
self.gctx
.get_env("RUSTUP_TOOLCHAIN_SOURCE")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My gut reaction is we should make an exception and read from std::env. That seems matched with

// ALLOWED: `RUSTUP_HOME` should only be read from process env, otherwise
// other tools may point to executables from incompatible distributions.
#[allow(clippy::disallowed_methods)]
std::env::var_os("RUSTUP_HOME").is_some()

but then we have this

gctx.get_env("RUSTUP_HOME"),
gctx.get_env("RUSTUP_TOOLCHAIN"),

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My gut reaction is we should make an exception and read from std::env. That seems matched with...but then we have this...

I'm not seeing the rationale for using std::env or gctx.get_env(..).

Regardless, I will do whichever you prefer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gctx.get_env is to allow us to read from .cargo/config.tomls [env] table which should not be setting RUSTUP variables.

@rustbot

This comment has been minimized.

@rustbot rustbot added the S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author. label Nov 6, 2025
@smoelius smoelius force-pushed the second-half-of-11036 branch from c64e01a to f0f222f Compare November 6, 2025 23:07
@smoelius
Copy link
Contributor Author

smoelius commented Nov 6, 2025

Just FYI, I know it looks like only some of the comments have been addressed. I am still hoping to get feedback on #16131 (comment) and #16131 (comment).

@rustbot rustbot added A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. A-testing-cargo-itself Area: cargo's tests labels Dec 28, 2025
@smoelius smoelius force-pushed the second-half-of-11036 branch from f75ccb8 to a386ddd Compare December 28, 2025 21:21
@smoelius
Copy link
Contributor Author

smoelius commented Dec 28, 2025

I resolved comments that I thought I implemented uncontroversially. I hope that was okay.

EDIT: I also hid a few of my own comments that were old.

@epage
Copy link
Contributor

epage commented Dec 30, 2025

Please clean up your commits for how they should be reviewed and merged, rather than for how it was developed.

Comment on lines 1452 to 1454
.env_remove("RUSTUP_HOME")
.env_remove("RUSTUP_TOOLCHAIN")
.env_remove("RUSTUP_TOOLCHAIN_SOURCE")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we loop over all RUSTUP_* like we do for cargo?

p.process(make)
.env("PATH", path)
.env("CARGO", cargo_exe())
.env("RUSTUP_HOME", env!("REAL_RUSTUP_HOME"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need REAL_RUSTUP_HOME rather than just reading RUSTUP_HOME?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some of the tests seem to require something in the real rustup installation. I haven't tried to figure out what, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can understand forwarding RUSTUP_HOME. What I'm wondering about is REAL_RUSTUP_HOME. We should be able to read RUSTUP_HOME (ideally at runtime, not compile time) and forward that to the test. The p.process call is stripping RUSTUP_HOME but the process we are currently running in should still have it set if it is set (it isn't always)

@smoelius smoelius force-pushed the second-half-of-11036 branch from a386ddd to 989ec0e Compare December 31, 2025 00:15
@smoelius smoelius force-pushed the second-half-of-11036 branch from 989ec0e to 71b7a8f Compare December 31, 2025 00:24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Can we have some explanation in the commit message, so the commit standalone tells why we need this? It is hard to tell whether this is a refactor or a bugfix for the testsuite.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you asking for one comment per commit? Or one comment describing the entire PR in one of the commits? Either way, I am happy to oblige.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the code commit by commit, so was specifically asking the first commit. Not a blocker though. Thanks!

cargo_install_with_toolchain_source(Some("invalid"), false);
}

fn cargo_install_with_toolchain_source(source: Option<&str>, should_warn: bool) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of passing boolean we can make the argument impl snapbox::IntoData so that every test has its own snapshot. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would the impl snapbox::IntoData be? Could you give me an example?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

He's asking to pass in stderr rather than creating it within the test

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For more context:

  • it makes the test easier to evaluate what it does
  • we prefer using snapshots (str![]), rather than hard coded values, wherever possible so we can easily update all tests when unrelated formatting changes

}
}

enum RustupToolchainSource {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, rustup hasn't yet claimed those values are stable. At least the doc doesn't say anything more than the environment key https://github.com/rust-lang/rustup/blob/de2b979bd4569cacfabf501bb58464c9139b0d6d/doc/user-guide/src/environment-variables.md?plain=1#L75.

  • Could we have a link to the rustup source code if we want to make an assumption on that?
  • Should we check with the rustup team to ensure these value strings are stable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy to get confirmation from the Rustup team that the five values are stable, but would you feel more comfortable if they were listed directly in the documentation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, thanks. But actually if we have #16131 (comment) maybe it is not really necessary?

"cli" => Some(RustupToolchainSource::CommandLine),
"path-override" => Some(RustupToolchainSource::OverrideDB),
"toolchain-file" => Some(RustupToolchainSource::ToolchainFile),
_ => None,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For forward compatibility, should we have RustupToolchainSource::Other(String) and render it verbatim?

Comment on lines +15 to +17
#[allow(clippy::disallowed_methods)]
let real_rustc = std::env::var("RUSTC").unwrap();
println!("cargo:rustc-env=REAL_RUSTC={real_rustc}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to REAL_RUSTUP_HOME, we shouldn't need a REAL_RUSTC because RUSTC (if it is set which it isn't guaranteed to be) is not cleared within the process that can also read REAL_RUSTC

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, cargo sets it on the build script and we are forwarding it along.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While a lot simpler of a solution, I'm not too thrilled with this because

  • say we could get rid of our build script for production reasons (which would be ideal), we'd then have production builds running a build script for tests
  • we have to use env! which I assume makes caching more difficult because it has an absolute path in it that can change, particularly for CI

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@weihanglo your thoughts?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add RustupEnvironmentBuilder

When doing a refactor commit, particularly when the diff is more difficult to read (indentation level, moving), please separate out any logical changes into a separate commit

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set RUSTUP_TOOLCHAIN_SOURCE in rustup tests

Why is this needed?

We need to be able to work with old rustup that doesn't set this, so it is probably good for us to have some existing tests that leave it unset

Comment on lines +18 to +22
fn pkg(name: &str, vers: &str) {
Package::new(name, vers)
.file("src/main.rs", "fn main() {{}}")
.publish();
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo this abstraction does not carry enough value to outweigh what it is hiding. We should instead just have these calls in the tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I had same the same thing before (#16131 (comment)) but it got resolved

Comment on lines +1386 to +1390
for (k, _v) in env::vars() {
if k.starts_with("RUSTUP_") {
self = self.env_remove(&k);
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like a change that is independent of implementing this warning and should be in a commit beforehand

Comment on lines +642 to +643
.ok()
.and_then(|val| match val {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel like the non-combinator approach would be much more readable here

let source = std::env::var_os("RUSTUP_TOOLCHAIN_SOURCE").ok()?;
let source = match source {
};
Some(source)

{
let maybe_toolchain = self
.gctx
.get_env("RUSTUP_TOOLCHAIN")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto for get_env

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-infrastructure Area: infrastructure around the cargo repo, ci, releases, etc. A-testing-cargo-itself Area: cargo's tests Command-install S-waiting-on-author Status: The marked PR is awaiting some action (such as code changes) from the PR author.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants