From 6a02b5afe93592ee62f502d512b3a79ea51eed35 Mon Sep 17 00:00:00 2001 From: rami3l Date: Sat, 12 Jul 2025 12:02:45 +0800 Subject: [PATCH] fix(toolchain/distributable): refine handling of known targets with no prebuilt artifacts --- Cargo.toml | 2 +- src/errors.rs | 10 ++++++++++ src/toolchain/distributable.rs | 12 +++++++++--- tests/suite/cli_v2.rs | 20 ++++++++++++++++++++ 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9e6d1c34a0..b187a7d2a0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,6 +66,7 @@ openssl = { version = "0.10", optional = true } opentelemetry = { version = "0.30", optional = true } opentelemetry-otlp = { version = "0.30", features = ["grpc-tonic"], optional = true } opentelemetry_sdk = { version = "0.30", features = ["rt-tokio"], optional = true } +platforms = "3.4" pulldown-cmark = { version = "0.13", default-features = false } rand = "0.9" regex = "1" @@ -135,7 +136,6 @@ enum-map = "2.5.0" http-body-util = "0.1.0" hyper = { version = "1.0", default-features = false, features = ["server", "http1"] } hyper-util = { version = "0.1.1", features = ["tokio"] } -platforms = "3.4" proptest = "1.1.0" trycmd = "0.15.0" diff --git a/src/errors.rs b/src/errors.rs index d46d3af602..d8273c1bac 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -7,6 +7,7 @@ use std::io; use std::io::Write; use std::path::PathBuf; +use platforms::Platform; use thiserror::Error as ThisError; use url::Url; @@ -125,6 +126,15 @@ pub enum RustupError { component: String, suggestion: Option, }, + #[error( + "toolchain '{desc}' has no prebuilt artifacts available for target '{platform}'\n\ + note: this may happen to a low-tier target as per https://doc.rust-lang.org/nightly/rustc/platform-support.html\n\ + note: you can find instructions on that page to build the target support from source" + )] + UnavailableTarget { + desc: ToolchainDesc, + platform: &'static Platform, + }, #[error("toolchain '{}' does not support target '{}'{}\n\ note: you can see a list of supported targets with `rustc --print=target-list`\n\ note: if you are adding support for a new target to rustc itself, see https://rustc-dev-guide.rust-lang.org/building/new-target.html", .desc, .target, diff --git a/src/toolchain/distributable.rs b/src/toolchain/distributable.rs index a1787f4faa..6441b5272f 100644 --- a/src/toolchain/distributable.rs +++ b/src/toolchain/distributable.rs @@ -5,6 +5,7 @@ use std::{convert::Infallible, env::consts::EXE_SUFFIX, ffi::OsStr, path::Path, #[cfg(windows)] use anyhow::Context; use anyhow::anyhow; +use platforms::Platform; use crate::{ RustupError, component_for_bin, @@ -76,21 +77,26 @@ impl<'a> DistributableToolchain<'a> { let config = manifestation.read_config()?.unwrap_or_default(); let suggestion = self.get_component_suggestion(&component, &config, &manifest, false); + let desc = self.desc.clone(); // Check if the target is supported. if !targ_pkg .components .iter() .any(|c| c.target() == component.target()) { + let target = component.target.expect("component target should be known"); + if let Some(platform) = Platform::find(&target) { + return Err(RustupError::UnavailableTarget { desc, platform }.into()); + }; return Err(RustupError::UnknownTarget { - desc: self.desc.clone(), - target: component.target.expect("component target should be known"), + desc, + target, suggestion, } .into()); } return Err(RustupError::UnknownComponent { - desc: self.desc.clone(), + desc, component: component.description(&manifest), suggestion, } diff --git a/tests/suite/cli_v2.rs b/tests/suite/cli_v2.rs index dabb41a590..83a9d7f269 100644 --- a/tests/suite/cli_v2.rs +++ b/tests/suite/cli_v2.rs @@ -1509,6 +1509,26 @@ note: if you are adding support for a new target to rustc itself, see https://ru .is_err(); } +#[tokio::test] +async fn add_target_unavailable() { + let cx = CliTestContext::new(Scenario::SimpleV2).await; + cx.config + .expect(["rustup", "default", "nightly"]) + .await + .is_ok(); + cx.config + .expect(["rustup", "target", "add", "mipsel-sony-psp"]) + .await + .with_stderr(snapbox::str![[r#" +... +error: toolchain 'nightly-[HOST_TRIPLE]' has no prebuilt artifacts available for target 'mipsel-sony-psp' +note: this may happen to a low-tier target as per https://doc.rust-lang.org/nightly/rustc/platform-support.html +note: you can find instructions on that page to build the target support from source + +"#]]) + .is_err(); +} + #[tokio::test] async fn add_target_v1_toolchain() { let cx = CliTestContext::new(Scenario::SimpleV1).await;