diff --git a/Cargo.lock b/Cargo.lock index 7f1cf4850c8a..45020437fd90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4121,6 +4121,7 @@ version = "0.0.0" dependencies = [ "cc", "libc", + "shell-words", ] [[package]] @@ -5115,6 +5116,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_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 8b1dad9a6547..25911d3e9e46 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 @@ fn lower_const_arg_array( ) -> 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 @@ fn lower_const_arg_tup( ) -> 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/compiler/rustc_llvm/Cargo.toml b/compiler/rustc_llvm/Cargo.toml index ad93c7453813..b618bc199d88 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 c58dd64cca5f..7a1c95da29ea 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/library/core/src/ops/control_flow.rs b/library/core/src/ops/control_flow.rs index 1b1444042335..fc3c0c8b1017 100644 --- a/library/core/src/ops/control_flow.rs +++ b/library/core/src/ops/control_flow.rs @@ -203,8 +203,6 @@ pub const fn break_value(self) -> Option /// # Examples /// /// ``` - /// #![feature(control_flow_ok)] - /// /// use std::ops::ControlFlow; /// /// struct TreeNode { @@ -263,8 +261,9 @@ pub const fn break_value(self) -> Option /// 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")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] pub const fn break_ok(self) -> Result { match self { ControlFlow::Continue(c) => Err(c), @@ -317,8 +316,6 @@ pub const fn continue_value(self) -> Option /// # Examples /// /// ``` - /// #![feature(control_flow_ok)] - /// /// use std::ops::ControlFlow; /// /// struct TreeNode { @@ -376,8 +373,9 @@ pub const fn continue_value(self) -> Option /// 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")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] 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 7cd946dc9a03..efd5123055fe 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -32,7 +32,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)] 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 095624d6fb71..5dbca7e7b675 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 4b61fd94a6cf..87bfc0766fbd 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 9691d4b099b3..750cafaca0b2 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" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 9e9d463acdb3..220eadfdb9ed 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -425,6 +425,7 @@ pub(crate) struct WorkspaceInfo<'a> { "sha1", "sha2", "sharded-slab", + "shell-words", "shlex", "simd-adler32", "smallvec", 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 000000000000..18898069c145 --- /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 000000000000..ede7b1b3e0a5 --- /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`.