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
8 changes: 4 additions & 4 deletions src/cli/rustup_mode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -881,13 +881,13 @@ async fn default_(
cfg.set_default(Some(&toolchain_name.into()))?;
}
MaybeResolvableToolchainName::Some(ResolvableToolchainName::Official(toolchain)) => {
let desc = toolchain.resolve(&cfg.default_host_tuple()?)?;
let desc = toolchain.clone().resolve(&cfg.default_host_tuple()?)?;
let status = cfg
.ensure_installed(&desc, vec![], vec![], None, force_non_host, true)
.await?
.status;

cfg.set_default(Some(&desc.clone().into()))?;
cfg.set_default(Some(&toolchain.into()))?;

writeln!(cfg.process.stdout().lock())?;

Expand Down Expand Up @@ -1085,7 +1085,7 @@ async fn update(
force_non_host,
)?;
}
let desc = name.resolve(&cfg.default_host_tuple()?)?;
let desc = name.clone().resolve(&cfg.default_host_tuple()?)?;

let components = opts.component.iter().map(|s| &**s).collect::<Vec<_>>();
let targets = opts.target.iter().map(|s| &**s).collect::<Vec<_>>();
Expand Down Expand Up @@ -1128,7 +1128,7 @@ async fn update(
if opts.default
|| (cfg.get_default()?.is_none() && matches!(status, UpdateStatus::Installed))
{
cfg.set_default(Some(&desc.into()))?;
cfg.set_default(Some(&name.into()))?;
}
}
exit_code &= self_update_mode.update(should_self_update, &dl_cfg).await?;
Expand Down
28 changes: 10 additions & 18 deletions src/cli/self_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ use crate::{
process::Process,
toolchain::{
DistributableToolchain, MaybeOfficialToolchainName, ResolvableToolchainName, Toolchain,
ToolchainName,
},
utils::{self, ExitCode},
};
Expand Down Expand Up @@ -252,7 +251,8 @@ impl InstallOpts<'_> {

let (components, targets) = (self.components, self.targets);
let toolchain = self.select_toolchain(cfg)?;
if let Some(desc) = toolchain {
if let Some(partial_desc) = toolchain {
let desc = partial_desc.clone().resolve(&cfg.default_host_tuple()?)?;
let options =
DistOptions::new(components, targets, &desc, cfg.get_profile()?, true, cfg)?;
let status = if Toolchain::exists(cfg, &desc.clone().into())? {
Expand All @@ -272,7 +272,7 @@ impl InstallOpts<'_> {

check_proxy_sanity(cfg.process, components, &desc)?;

cfg.set_default(Some(&desc.clone().into()))?;
cfg.set_default(Some(&partial_desc.into()))?;

@rami3l rami3l Jul 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Note: Add a test case for #3651 (comment).

View changes since the review

writeln!(cfg.process.stdout().lock())?;
common::show_channel_update(cfg, PackageUpdate::Toolchain(desc), Ok(status))?;
}
Expand All @@ -284,7 +284,7 @@ impl InstallOpts<'_> {
/// This function first initializes the default profile and default host tuple in the
/// configuration, then returns the toolchain that should be installed, or `None` if none is
/// specified by the user.
fn select_toolchain(self, cfg: &mut Cfg<'_>) -> Result<Option<ToolchainDesc>> {
fn select_toolchain(self, cfg: &mut Cfg<'_>) -> Result<Option<PartialToolchainDesc>> {
let Self {
default_host_tuple,
default_toolchain,
Expand Down Expand Up @@ -342,18 +342,14 @@ impl InstallOpts<'_> {
MaybeOfficialToolchainName::None => unreachable!(),
MaybeOfficialToolchainName::Some(n) => n,
};
Some(toolchain_name.resolve(&cfg.default_host_tuple()?)?)
Some(toolchain_name)
}
None => match cfg.get_default()? {
None => match cfg.get_default_resolvable()? {
// Default is installable
Some(ToolchainName::Official(t)) => Some(t),
Some(ResolvableToolchainName::Official(t)) => Some(t),
// Default is custom, presumably from a prior install. Do nothing.
Some(ToolchainName::Custom(_)) => None,
None => Some(
"stable"
.parse::<PartialToolchainDesc>()?
.resolve(&cfg.default_host_tuple()?)?,
),
Some(ResolvableToolchainName::Custom(_)) => None,
None => Some(PartialToolchainDesc::from_str("stable")?),

@rami3l rami3l Jul 23, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

},
})
} else {
Expand Down Expand Up @@ -1376,11 +1372,7 @@ mod tests {
};

assert_eq!(
"stable"
.parse::<PartialToolchainDesc>()
.unwrap()
.resolve(&cfg.default_host_tuple().unwrap())
.unwrap(),
"stable".parse::<PartialToolchainDesc>().unwrap(),
opts.select_toolchain(&mut cfg)
.unwrap() // result
.unwrap() // option
Expand Down
21 changes: 15 additions & 6 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ impl<'a> Cfg<'a> {
Ok(cfg)
}

pub(crate) fn set_default(&self, toolchain: Option<&ToolchainName>) -> Result<()> {
pub(crate) fn set_default(&self, toolchain: Option<&ResolvableToolchainName>) -> Result<()> {
self.settings_file.with_mut(|s| {
s.default_toolchain = toolchain.map(|t| t.to_string());
Ok(())
Expand Down Expand Up @@ -904,6 +904,16 @@ impl<'a> Cfg<'a> {
/// If none is configured, returns None
/// If a bad toolchain name is configured, errors.
pub(crate) fn get_default(&self) -> Result<Option<ToolchainName>> {
let Some(toolchain) = self.get_default_resolvable()? else {
return Ok(None);
};
Ok(Some(toolchain.resolve(&self.default_host_tuple()?)?))
}

/// Gets the configured default toolchain.
/// If none is configured, returns None
/// If a bad toolchain name is configured, errors.
pub(crate) fn get_default_resolvable(&self) -> Result<Option<ResolvableToolchainName>> {
let user_opt = self.settings_file.with(|s| Ok(s.default_toolchain.clone()));
let toolchain_maybe_str = if let Some(fallback_settings) = &self.fallback_settings {
match user_opt {
Expand All @@ -913,11 +923,10 @@ impl<'a> Cfg<'a> {
} else {
user_opt
}?;
toolchain_maybe_str
.map(ResolvableToolchainName::try_from)
.transpose()?
.map(|t| t.resolve(&self.default_host_tuple()?))
.transpose()
let Some(toolchain) = toolchain_maybe_str else {
return Ok(None);
};
Ok(Some(ResolvableToolchainName::try_from(toolchain)?))
}

/// List all the installed toolchains: that is paths in the toolchain dir
Expand Down
11 changes: 11 additions & 0 deletions src/toolchain/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,17 @@ impl ResolvableLocalToolchainName {
}
}

from_variant!(
PartialToolchainDesc,
ResolvableToolchainName,
ResolvableToolchainName::Official
);
from_variant!(
CustomToolchainName,
ResolvableToolchainName,
ResolvableToolchainName::Custom
);

try_from_str!(ResolvableLocalToolchainName);

impl Display for ResolvableLocalToolchainName {
Expand Down
4 changes: 2 additions & 2 deletions tests/suite/cli_exact.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ async fn update_once() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]]);
cx.config
Expand Down Expand Up @@ -322,7 +322,7 @@ async fn default() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]]);
cx.config
Expand Down
6 changes: 3 additions & 3 deletions tests/suite/cli_rustup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ async fn default() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 4 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]])
.is_ok();
Expand Down Expand Up @@ -327,7 +327,7 @@ async fn default_override() {
.await
.with_stderr(snapbox::str![[r#"
info: using existing install for stable-[HOST_TUPLE]
info: default toolchain set to stable-[HOST_TUPLE]
info: default toolchain set to stable
info: note that the toolchain 'nightly-[HOST_TUPLE]' is currently in use (directory override for '[..]')

"#]])
Expand Down Expand Up @@ -4032,7 +4032,7 @@ async fn custom_toolchain_with_components_toolchains_profile_does_not_err() {
info: syncing channel updates for nightly-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.3.0 (hash-nightly-2)
info: downloading 2 components
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly

"#]])
.is_ok();
Expand Down
2 changes: 1 addition & 1 deletion tests/suite/cli_rustup_ui/rustup_default.stderr.term.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions tests/suite/cli_self_upd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ async fn install_bins_to_cargo_home() {
info: syncing channel updates for stable-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.1.0 (hash-stable-1.1.0)
info: downloading 4 components
info: default toolchain set to stable-[HOST_TUPLE]
info: default toolchain set to stable

"#]])
.is_ok();
Expand Down Expand Up @@ -118,7 +118,7 @@ async fn proxies_are_relative_symlinks() {
info: syncing channel updates for stable-[HOST_TUPLE]
info: latest update on 2015-01-02 for version 1.1.0 (hash-stable-1.1.0)
info: downloading 4 components
info: default toolchain set to stable-[HOST_TUPLE]
info: default toolchain set to stable
...
"#]])
.is_ok();
Expand Down Expand Up @@ -974,7 +974,7 @@ async fn reinstall_specifying_different_toolchain() {
.await
.with_stderr(snapbox::str![[r#"
...
info: default toolchain set to nightly-[HOST_TUPLE]
info: default toolchain set to nightly
...
"#]])
.is_ok();
Expand Down
Loading