From c30e20a04910153b121a82c058948e18e09614da Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 16 Feb 2026 13:26:00 +0000 Subject: [PATCH 1/5] Use shell-words to parse output from llvm-config llvm-config might output paths that contain spaces, in which case the naive approach of splitting on whitespace breaks; instead we ask llvm-config to quote any paths and use the shell-words crate to parse the output. --- Cargo.lock | 7 +++ compiler/rustc_llvm/Cargo.toml | 1 + compiler/rustc_llvm/build.rs | 90 ++++++++++++++++++++++++++++------ src/tools/tidy/src/deps.rs | 1 + 4 files changed, 85 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 53cac09b7a7ab..34f66cc06d670 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4163,6 +4163,7 @@ version = "0.0.0" dependencies = [ "cc", "libc", + "shell-words", ] [[package]] @@ -5174,6 +5175,12 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shell-words" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" + [[package]] name = "shlex" version = "1.3.0" diff --git a/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index ad93c74538130..b618bc199d885 100644 --- a/compiler/rustc_llvm/Cargo.toml +++ b/compiler/rustc_llvm/Cargo.toml @@ -12,6 +12,7 @@ libc = "0.2.73" # tidy-alphabetical-start # `cc` updates often break things, so we pin it here. cc = "=1.2.16" +shell-words = "1.1.1" # tidy-alphabetical-end [features] diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index c58dd64cca5f7..7a1c95da29ea1 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -1,8 +1,11 @@ +use std::borrow::Cow; use std::env; use std::ffi::{OsStr, OsString}; use std::fmt::Display; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; +use std::process::{Command, Output, Stdio}; +use std::str::SplitWhitespace; +use std::vec::IntoIter; const OPTIONAL_COMPONENTS: &[&str] = &[ "x86", @@ -86,8 +89,8 @@ fn rerun_if_changed_anything_in_dir(dir: &Path) { } #[track_caller] -fn output(cmd: &mut Command) -> String { - let output = match cmd.stderr(Stdio::inherit()).output() { +fn execute(cmd: &mut Command) -> Output { + let output = match cmd.output() { Ok(status) => status, Err(e) => { println!("\n\nfailed to execute command: {cmd:?}\nerror: {e}\n\n"); @@ -101,7 +104,52 @@ fn output(cmd: &mut Command) -> String { cmd, output.status ); } - String::from_utf8(output.stdout).unwrap() + output +} + +#[track_caller] +fn output(cmd: &mut Command) -> String { + String::from_utf8(execute(cmd.stderr(Stdio::inherit())).stdout).unwrap() +} +#[track_caller] +fn stderr(cmd: &mut Command) -> String { + String::from_utf8(execute(cmd).stderr).unwrap() +} + +enum LlvmConfigOutput { + QuotedPaths(String), + UnquotedPaths(String), +} + +#[derive(Clone)] +enum SplitLlvmConfigOutput<'a> { + QuotedPaths(IntoIter), + UnquotedPaths(SplitWhitespace<'a>), +} + +impl<'a> Iterator for SplitLlvmConfigOutput<'a> { + type Item = Cow<'a, str>; + fn next(&mut self) -> Option> { + match self { + Self::QuotedPaths(iter) => iter.next().map(Cow::Owned), + Self::UnquotedPaths(iter) => iter.next().map(Cow::Borrowed), + } + } +} + +impl<'a> IntoIterator for &'a LlvmConfigOutput { + type Item = Cow<'a, str>; + type IntoIter = SplitLlvmConfigOutput<'a>; + fn into_iter(self) -> Self::IntoIter { + match self { + LlvmConfigOutput::QuotedPaths(output) => SplitLlvmConfigOutput::QuotedPaths( + shell_words::split(&output).expect("matched quotes").into_iter(), + ), + LlvmConfigOutput::UnquotedPaths(output) => { + SplitLlvmConfigOutput::UnquotedPaths(output.split_whitespace()) + } + } + } } fn main() { @@ -125,6 +173,19 @@ fn main() { println!("cargo:rerun-if-changed={}", llvm_config.display()); + // FIXME: `--quote-paths` was added to llvm-config in LLVM 22, so this test (and all its ensuing + // fallback paths) can be removed once we bump the minimum llvm_version >= (22, 0, 0). + let llvm_config_supports_quote_paths = + stderr(Command::new(&llvm_config).arg("--help")).contains("quote-paths"); + + let quoted_split = |mut cmd: Command| { + if llvm_config_supports_quote_paths { + LlvmConfigOutput::QuotedPaths(output(cmd.arg("--quote-paths"))) + } else { + LlvmConfigOutput::UnquotedPaths(output(&mut cmd)) + } + }; + // Test whether we're cross-compiling LLVM. This is a pretty rare case // currently where we're producing an LLVM for a different platform than // what this build script is currently running on. @@ -167,7 +228,8 @@ fn main() { // Link in our own LLVM shims, compiled with the same flags as LLVM let mut cmd = Command::new(&llvm_config); cmd.arg("--cxxflags"); - let cxxflags = output(&mut cmd); + let cxxflags = quoted_split(cmd); + let mut cxxflags_iter = cxxflags.into_iter(); let mut cfg = cc::Build::new(); cfg.warnings(false); @@ -180,7 +242,7 @@ fn main() { if std::env::var_os("CI").is_some() && !target.contains("msvc") { cfg.warnings_into_errors(true); } - for flag in cxxflags.split_whitespace() { + for flag in cxxflags_iter.clone() { // Ignore flags like `-m64` when we're doing a cross build if is_crossed && flag.starts_with("-m") { continue; @@ -201,7 +263,7 @@ fn main() { continue; } - cfg.flag(flag); + cfg.flag(&*flag); } for component in &components { @@ -289,13 +351,13 @@ fn main() { } cmd.args(&components); - for lib in output(&mut cmd).split_whitespace() { + for lib in "ed_split(cmd) { let mut is_static = false; let name = if let Some(stripped) = lib.strip_prefix("-l") { stripped } else if let Some(stripped) = lib.strip_prefix('-') { stripped - } else if Path::new(lib).exists() { + } else if Path::new(&*lib).exists() { // On MSVC llvm-config will print the full name to libraries, but // we're only interested in the name part // On Unix when we get a static library llvm-config will print the @@ -306,7 +368,7 @@ fn main() { // and we transform the zstd part into // cargo:rustc-link-search-native=/usr/local/lib // cargo:rustc-link-lib=static=zstd - let path = Path::new(lib); + let path = Path::new(&*lib); if lib.ends_with(".a") { is_static = true; println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); @@ -351,7 +413,7 @@ fn main() { // that those -L directories are the same! let mut cmd = Command::new(&llvm_config); cmd.arg(llvm_link_arg).arg("--ldflags"); - for lib in output(&mut cmd).split_whitespace() { + for lib in "ed_split(cmd) { if is_crossed { if let Some(stripped) = lib.strip_prefix("-LIBPATH:") { println!("cargo:rustc-link-search=native={}", stripped.replace(&host, &target)); @@ -373,7 +435,7 @@ fn main() { // dependencies. let llvm_linker_flags = tracked_env_var_os("LLVM_LINKER_FLAGS"); if let Some(s) = llvm_linker_flags { - for lib in s.into_string().unwrap().split_whitespace() { + for lib in shell_words::split(&s.into_string().unwrap()).expect("matched quotes") { if let Some(stripped) = lib.strip_prefix("-l") { println!("cargo:rustc-link-lib={stripped}"); } else if let Some(stripped) = lib.strip_prefix("-L") { @@ -414,7 +476,7 @@ fn main() { // C++ runtime library if !target.contains("msvc") { if let Some(s) = llvm_static_stdcpp { - assert!(!cxxflags.contains("stdlib=libc++")); + assert!(cxxflags_iter.all(|flag| flag != "stdlib=libc++")); let path = PathBuf::from(s); println!("cargo:rustc-link-search=native={}", path.parent().unwrap().display()); if target.contains("windows") { @@ -422,7 +484,7 @@ fn main() { } else { println!("cargo:rustc-link-lib=static={stdcppname}"); } - } else if cxxflags.contains("stdlib=libc++") { + } else if cxxflags_iter.any(|flag| flag == "stdlib=libc++") { println!("cargo:rustc-link-lib=c++"); } else { println!("cargo:rustc-link-lib={stdcppname}"); diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 24c610b41f3a4..551abeab6f6aa 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -426,6 +426,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[ "sha1", "sha2", "sharded-slab", + "shell-words", "shlex", "simd-adler32", "smallvec", From e9bf9291a7870bbe104397a1d537c82b8888cbbc Mon Sep 17 00:00:00 2001 From: nxsaken Date: Fri, 20 Feb 2026 18:18:34 +0400 Subject: [PATCH 2/5] Stabilize `control_flow_ok` --- library/core/src/ops/control_flow.rs | 12 ++++-------- library/coretests/tests/lib.rs | 1 - 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 84fc98cf73f1e..6adc6d4cdac3e 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -203,8 +203,6 @@ impl ControlFlow { /// # Examples /// /// ``` - /// #![feature(control_flow_ok)] - /// /// use std::ops::ControlFlow; /// /// struct TreeNode { @@ -263,8 +261,8 @@ impl ControlFlow { /// assert_eq!(res, Ok(&5)); /// ``` #[inline] - #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] + #[stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] pub const fn break_ok(self) -> Result { match self { ControlFlow::Continue(c) => Err(c), @@ -317,8 +315,6 @@ impl ControlFlow { /// # Examples /// /// ``` - /// #![feature(control_flow_ok)] - /// /// use std::ops::ControlFlow; /// /// struct TreeNode { @@ -376,8 +372,8 @@ impl ControlFlow { /// assert_eq!(res, Err("too big value detected")); /// ``` #[inline] - #[unstable(feature = "control_flow_ok", issue = "140266")] - #[rustc_const_unstable(feature = "control_flow_ok", issue = "140266")] + #[stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] pub const fn continue_ok(self) -> Result { match self { ControlFlow::Continue(c) => Ok(c), diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 85ee7cff68266..abbc58c4cbf0c 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -33,7 +33,6 @@ #![feature(const_select_unpredictable)] #![feature(const_trait_impl)] #![feature(const_unsigned_bigint_helpers)] -#![feature(control_flow_ok)] #![feature(core_intrinsics)] #![feature(core_intrinsics_fallbacks)] #![feature(core_io_borrowed_buf)] From c5da0e3ce2930f29ed0adb5bee6e55750501ad35 Mon Sep 17 00:00:00 2001 From: nxsaken Date: Fri, 20 Feb 2026 20:21:07 +0400 Subject: [PATCH 3/5] Allow unstable const_precise_live_drops in stable --- library/core/src/ops/control_flow.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 6adc6d4cdac3e..07741a9bad9a0 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -263,6 +263,7 @@ impl ControlFlow { #[inline] #[stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn break_ok(self) -> Result { match self { ControlFlow::Continue(c) => Err(c), @@ -374,6 +375,7 @@ impl ControlFlow { #[inline] #[stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_stable(feature = "control_flow_ok", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn continue_ok(self) -> Result { match self { ControlFlow::Continue(c) => Ok(c), From 797f06675afb89616e7fc99704e4869d012ea52c Mon Sep 17 00:00:00 2001 From: Guillaume Date: Sat, 28 Feb 2026 17:21:09 +0100 Subject: [PATCH 4/5] Fix LegacyKeyValueFormat report from docker build: host-aarch64 --- .../host-aarch64/aarch64-gnu-llvm-20/Dockerfile | 11 +++++------ src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile | 9 ++++----- .../host-aarch64/dist-aarch64-linux/Dockerfile | 13 ++++++------- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile index 095624d6fb714..5dbca7e7b675b 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu-llvm-20/Dockerfile @@ -37,20 +37,19 @@ RUN sh /scripts/sccache.sh # We are disabling CI LLVM since this builder is intentionally using a host # LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM 1 -ENV EXTERNAL_LLVM 1 +ENV NO_DOWNLOAD_CI_LLVM="1" +ENV EXTERNAL_LLVM="1" # Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS \ - --build=aarch64-unknown-linux-gnu \ +ENV RUST_CONFIGURE_ARGS="--build=aarch64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-20 \ --enable-llvm-link-shared \ --set rust.randomize-layout=true \ - --set rust.thin-lto-import-instr-limit=10 + --set rust.thin-lto-import-instr-limit=10" COPY scripts/shared.sh /scripts/ COPY scripts/stage_2_test_set1.sh /scripts/ COPY scripts/stage_2_test_set2.sh /scripts/ -ENV SCRIPT "Must specify DOCKER_SCRIPT for this image" +ENV SCRIPT="Must specify DOCKER_SCRIPT for this image" diff --git a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile index 4b61fd94a6cfa..87bfc0766fbd9 100644 --- a/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile +++ b/src/ci/docker/host-aarch64/aarch64-gnu/Dockerfile @@ -21,10 +21,9 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -ENV RUST_CONFIGURE_ARGS \ - --build=aarch64-unknown-linux-gnu \ +ENV RUST_CONFIGURE_ARGS="--build=aarch64-unknown-linux-gnu \ --enable-sanitizers \ --enable-profiler \ - --enable-compiler-docs -ENV SCRIPT python3 ../x.py --stage 2 test && \ - python3 ../x.py --stage 2 test src/tools/cargo + --enable-compiler-docs" +ENV SCRIPT="python3 ../x.py --stage 2 test && \ + python3 ../x.py --stage 2 test src/tools/cargo" diff --git a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile index 9691d4b099b3b..750cafaca0b2c 100644 --- a/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile +++ b/src/ci/docker/host-aarch64/dist-aarch64-linux/Dockerfile @@ -76,8 +76,7 @@ ENV HOSTS=aarch64-unknown-linux-gnu ENV CPATH=/usr/include/aarch64-linux-gnu/:$CPATH -ENV RUST_CONFIGURE_ARGS \ - --build=aarch64-unknown-linux-gnu \ +ENV RUST_CONFIGURE_ARGS="--build=aarch64-unknown-linux-gnu \ --enable-full-tools \ --enable-profiler \ --enable-sanitizers \ @@ -93,12 +92,12 @@ ENV RUST_CONFIGURE_ARGS \ --set rust.jemalloc \ --set rust.bootstrap-override-lld=true \ --set rust.lto=thin \ - --set rust.codegen-units=1 + --set rust.codegen-units=1" -ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \ +ENV SCRIPT="python3 ../x.py build --set rust.debug=true opt-dist && \ ./build/$HOSTS/stage1-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \ - --host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap enzyme + --host $HOSTS --target $HOSTS --include-default-paths build-manifest bootstrap enzyme" ENV CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=clang -ENV LIBCURL_NO_PKG_CONFIG 1 -ENV DIST_REQUIRE_ALL_TOOLS 1 +ENV LIBCURL_NO_PKG_CONFIG="1" +ENV DIST_REQUIRE_ALL_TOOLS="1" From ee1d0cfbe6b17fe77e1da569be33ac0ee7916be7 Mon Sep 17 00:00:00 2001 From: human9000 Date: Tue, 3 Mar 2026 17:08:26 +0500 Subject: [PATCH 5/5] MGCA: fix type error handling for array and tuple lowering logic --- .../src/hir_ty_lowering/mod.rs | 24 ++++++++++++------- .../mgca/syntactic-type-mismatch.rs | 13 ++++++++++ .../mgca/syntactic-type-mismatch.stderr | 20 ++++++++++++++++ 3 files changed, 49 insertions(+), 8 deletions(-) create mode 100644 tests/ui/const-generics/mgca/syntactic-type-mismatch.rs create mode 100644 tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 8b1dad9a65471..25911d3e9e462 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2416,11 +2416,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Const<'tcx> { let tcx = self.tcx(); - let ty::Array(elem_ty, _) = ty.kind() else { - let e = tcx - .dcx() - .span_err(array_expr.span, format!("expected `{}`, found const array", ty)); - return Const::new_error(tcx, e); + let elem_ty = match ty.kind() { + ty::Array(elem_ty, _) => elem_ty, + ty::Error(e) => return Const::new_error(tcx, *e), + _ => { + let e = tcx + .dcx() + .span_err(array_expr.span, format!("expected `{}`, found const array", ty)); + return Const::new_error(tcx, e); + } }; let elems = array_expr @@ -2539,9 +2543,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Const<'tcx> { let tcx = self.tcx(); - let ty::Tuple(tys) = ty.kind() else { - let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty)); - return Const::new_error(tcx, e); + let tys = match ty.kind() { + ty::Tuple(tys) => tys, + ty::Error(e) => return Const::new_error(tcx, *e), + _ => { + let e = tcx.dcx().span_err(span, format!("expected `{}`, found const tuple", ty)); + return Const::new_error(tcx, e); + } }; let exprs = exprs diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs new file mode 100644 index 0000000000000..18898069c1452 --- /dev/null +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -0,0 +1,13 @@ +// This test ensures proper diagnostics emission during HIR ty lowering +// See https://github.com/rust-lang/rust/issues/153254 + +#![feature(min_generic_const_args)] +#![expect(incomplete_features)] + +type const T0: _ = (); +//~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants [E0121] + +type const T1 = [0]; +//~^ ERROR: missing type for `const` item + +fn main() {} diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr new file mode 100644 index 0000000000000..ede7b1b3e0a5b --- /dev/null +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr @@ -0,0 +1,20 @@ +error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants + --> $DIR/syntactic-type-mismatch.rs:7:16 + | +LL | type const T0: _ = (); + | ^ not allowed in type signatures + +error: missing type for `const` item + --> $DIR/syntactic-type-mismatch.rs:10:14 + | +LL | type const T1 = [0]; + | ^ + | +help: provide a type for the item + | +LL | type const T1: = [0]; + | ++++++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0121`.