Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 78 additions & 1 deletion src/cargo/ops/cargo_install.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::{env, fs};
use std::{env, fmt, fs};

use crate::core::compiler::{CompileKind, DefaultExecutor, Executor, UnitOutput};
use crate::core::{Dependency, Edition, Package, PackageId, SourceId, Target, Workspace};
Expand All @@ -14,12 +14,14 @@ use crate::util::errors::CargoResult;
use crate::util::{Filesystem, GlobalContext, Rustc};
use crate::{drop_println, ops};

use annotate_snippets::Level;
use anyhow::{Context as _, bail};
use cargo_util::paths;
use cargo_util_schemas::core::PartialVersion;
use itertools::Itertools;
use semver::VersionReq;
use tempfile::Builder as TempFileBuilder;
use tracing::debug;

struct Transaction {
bins: Vec<PathBuf>,
Expand All @@ -39,6 +41,42 @@ impl Drop for Transaction {
}
}

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?

Default,
Environment,
CommandLine,
OverrideDB,
ToolchainFile,
Other(String),
}

#[allow(dead_code)]
impl RustupToolchainSource {
fn is_implicit_override(&self) -> Option<bool> {
match self {
Self::Default => Some(false),
Self::Environment => Some(true),
Self::CommandLine => Some(false),
Self::OverrideDB => Some(true),
Self::ToolchainFile => Some(true),
Self::Other(_) => None,
}
}
}

impl fmt::Display for RustupToolchainSource {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Self::Default => "default",
Self::Environment => "environment variable",
Self::CommandLine => "command line",
Self::OverrideDB => "rustup directory override",
Self::ToolchainFile => "rustup toolchain file",
Self::Other(other) => other,
})
}
}

struct InstallablePackage<'gctx> {
gctx: &'gctx GlobalContext,
opts: ops::CompileOptions,
Expand Down Expand Up @@ -316,6 +354,31 @@ impl<'gctx> InstallablePackage<'gctx> {
fn install_one(mut self, dry_run: bool) -> CargoResult<bool> {
self.gctx.shell().status("Installing", &self.pkg)?;

if let Some(source) = get_rustup_toolchain_source()
&& source.is_implicit_override().unwrap_or_else(|| {
debug!("ignoring unrecognized rustup toolchain source `{source}`");
false
})
{
#[expect(clippy::disallowed_methods, reason = "consistency with rustup")]
let maybe_toolchain = env::var("RUSTUP_TOOLCHAIN")
.ok()
.map(|toolchain| format!(" with `{toolchain}`"))
.unwrap_or_default();
let report = &[Level::WARNING
.secondary_title(format!(
"default toolchain implicitly overridden{maybe_toolchain} by {source}"
))
.element(Level::HELP.message(format!(
"use `cargo +stable install` if you meant to use the stable toolchain"
)))
.element(Level::NOTE.message(format!(
"rustup selects the toolchain based on the parent environment and not the \
environment of the package being installed"
)))];
self.gctx.shell().print_report(report, false)?;
}

// Normalize to absolute path for consistency throughout.
// See: https://github.com/rust-lang/cargo/issues/16023
let dst = self.root.join("bin").into_path_unlocked();
Expand Down Expand Up @@ -611,6 +674,20 @@ impl<'gctx> InstallablePackage<'gctx> {
}
}

fn get_rustup_toolchain_source() -> Option<RustupToolchainSource> {
#[expect(clippy::disallowed_methods, reason = "consistency with rustup")]
let source = std::env::var("RUSTUP_TOOLCHAIN_SOURCE").ok()?;
let source = match source.as_str() {
"default" => RustupToolchainSource::Default,
"env" => RustupToolchainSource::Environment,
"cli" => RustupToolchainSource::CommandLine,
"path-override" => RustupToolchainSource::OverrideDB,
"toolchain-file" => RustupToolchainSource::ToolchainFile,
other => RustupToolchainSource::Other(other.to_owned()),
};
Some(source)
}

fn make_warning_about_missing_features(binaries: &[&Target]) -> String {
let max_targets_listed = 7;
let target_features_message = binaries
Expand Down
Loading