From 92196db86695bf4d666de5573b8f05ef698a5ff7 Mon Sep 17 00:00:00 2001 From: im-lunex Date: Mon, 10 Aug 2026 21:16:34 +0000 Subject: [PATCH 1/4] add regression tests for the fn sig ice * add regression tests for the fn sig ice * add issuelinks in on top of the tests * regenerate stderr snapshots --- .../ice-missing-field-fn-sig-closure.rs | 16 ++++ .../ice-missing-field-fn-sig-closure.stderr | 78 +++++++++++++++++++ .../ice-missing-field-fn-sig-method.rs | 14 ++++ .../ice-missing-field-fn-sig-method.stderr | 22 ++++++ 4 files changed, 130 insertions(+) create mode 100644 tests/ui/structs/ice-missing-field-fn-sig-closure.rs create mode 100644 tests/ui/structs/ice-missing-field-fn-sig-closure.stderr create mode 100644 tests/ui/structs/ice-missing-field-fn-sig-method.rs create mode 100644 tests/ui/structs/ice-missing-field-fn-sig-method.stderr diff --git a/tests/ui/structs/ice-missing-field-fn-sig-closure.rs b/tests/ui/structs/ice-missing-field-fn-sig-closure.rs new file mode 100644 index 0000000000000..6878dd85ff847 --- /dev/null +++ b/tests/ui/structs/ice-missing-field-fn-sig-closure.rs @@ -0,0 +1,16 @@ +// issue-link: https://github.com/rust-lang/rust/issues/160591 +// A closure call with a struct literal missing a field shouldn't ICE when checking the fn sig. + +trait Context {} +struct Wrapper { + container: &'static C, +} + +fn main() { + let c = |_: Wrapper<()>| {}; //~ ERROR the trait bound `(): Context` is not satisfied + c(Wrapper { /* missing */ }); + //~^ ERROR the trait bound `(): Context` is not satisfied + //~^^ ERROR missing field `container` in initializer of `Wrapper<_>` + //~^^^ ERROR the trait bound `(): Context` is not satisfied + //~^^^^ ERROR the trait bound `(): Context` is not satisfied +} diff --git a/tests/ui/structs/ice-missing-field-fn-sig-closure.stderr b/tests/ui/structs/ice-missing-field-fn-sig-closure.stderr new file mode 100644 index 0000000000000..8e5b2fa931e4f --- /dev/null +++ b/tests/ui/structs/ice-missing-field-fn-sig-closure.stderr @@ -0,0 +1,78 @@ +error[E0277]: the trait bound `(): Context` is not satisfied + --> $DIR/ice-missing-field-fn-sig-closure.rs:10:17 + | +LL | let c = |_: Wrapper<()>| {}; + | ^^^^^^^^^^^ the trait `Context` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/ice-missing-field-fn-sig-closure.rs:4:1 + | +LL | trait Context {} + | ^^^^^^^^^^^^^ +note: required by a bound in `Wrapper` + --> $DIR/ice-missing-field-fn-sig-closure.rs:5:19 + | +LL | struct Wrapper { + | ^^^^^^^ required by this bound in `Wrapper` + +error[E0277]: the trait bound `(): Context` is not satisfied + --> $DIR/ice-missing-field-fn-sig-closure.rs:11:7 + | +LL | c(Wrapper { /* missing */ }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Context` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/ice-missing-field-fn-sig-closure.rs:4:1 + | +LL | trait Context {} + | ^^^^^^^^^^^^^ +note: required by a bound in `Wrapper` + --> $DIR/ice-missing-field-fn-sig-closure.rs:5:19 + | +LL | struct Wrapper { + | ^^^^^^^ required by this bound in `Wrapper` + +error[E0063]: missing field `container` in initializer of `Wrapper<_>` + --> $DIR/ice-missing-field-fn-sig-closure.rs:11:7 + | +LL | c(Wrapper { /* missing */ }); + | ^^^^^^^ missing `container` + +error[E0277]: the trait bound `(): Context` is not satisfied + --> $DIR/ice-missing-field-fn-sig-closure.rs:11:7 + | +LL | c(Wrapper { /* missing */ }); + | ^^^^^^^ the trait `Context` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/ice-missing-field-fn-sig-closure.rs:4:1 + | +LL | trait Context {} + | ^^^^^^^^^^^^^ +note: required by a bound in `Wrapper` + --> $DIR/ice-missing-field-fn-sig-closure.rs:5:19 + | +LL | struct Wrapper { + | ^^^^^^^ required by this bound in `Wrapper` + +error[E0277]: the trait bound `(): Context` is not satisfied + --> $DIR/ice-missing-field-fn-sig-closure.rs:11:5 + | +LL | c(Wrapper { /* missing */ }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Context` is not implemented for `()` + | +help: this trait has no implementations, consider adding one + --> $DIR/ice-missing-field-fn-sig-closure.rs:4:1 + | +LL | trait Context {} + | ^^^^^^^^^^^^^ +note: required by a bound in `Wrapper` + --> $DIR/ice-missing-field-fn-sig-closure.rs:5:19 + | +LL | struct Wrapper { + | ^^^^^^^ required by this bound in `Wrapper` + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0063, E0277. +For more information about an error, try `rustc --explain E0063`. diff --git a/tests/ui/structs/ice-missing-field-fn-sig-method.rs b/tests/ui/structs/ice-missing-field-fn-sig-method.rs new file mode 100644 index 0000000000000..9578dbc60c8e8 --- /dev/null +++ b/tests/ui/structs/ice-missing-field-fn-sig-method.rs @@ -0,0 +1,14 @@ +// issue-link: https://github.com/rust-lang/rust/issues/160591 +// A method call whose where-clause fails shouldn't ICE when checking the fn sig. + +trait Context {} +struct Foo; +impl Foo { + fn take(&self, _: T) {} +} + +fn main() { + let f = Foo; + f.take(()); + //~^ ERROR the trait bound `(): Context` is not satisfied +} diff --git a/tests/ui/structs/ice-missing-field-fn-sig-method.stderr b/tests/ui/structs/ice-missing-field-fn-sig-method.stderr new file mode 100644 index 0000000000000..d652dd9537935 --- /dev/null +++ b/tests/ui/structs/ice-missing-field-fn-sig-method.stderr @@ -0,0 +1,22 @@ +error[E0277]: the trait bound `(): Context` is not satisfied + --> $DIR/ice-missing-field-fn-sig-method.rs:12:12 + | +LL | f.take(()); + | ---- ^^ the trait `Context` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/ice-missing-field-fn-sig-method.rs:4:1 + | +LL | trait Context {} + | ^^^^^^^^^^^^^ +note: required by a bound in `Foo::take` + --> $DIR/ice-missing-field-fn-sig-method.rs:7:16 + | +LL | fn take(&self, _: T) {} + | ^^^^^^^ required by this bound in `Foo::take` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 4f7b53704e6004ff8dd2f99f604db63d7cee462b Mon Sep 17 00:00:00 2001 From: sgasho Date: Sat, 8 Aug 2026 09:08:52 +0000 Subject: [PATCH 2/4] Dist offload in x86 linux CI --- src/bootstrap/src/core/build_steps/compile.rs | 11 ++-- src/bootstrap/src/core/build_steps/dist.rs | 56 +++++++++++++++++++ src/bootstrap/src/core/build_steps/llvm.rs | 56 ++++++++++++++++++- src/bootstrap/src/core/builder/mod.rs | 1 + src/bootstrap/src/utils/tarball.rs | 5 ++ .../host-x86_64/dist-x86_64-linux/Dockerfile | 3 +- .../host-x86_64/dist-x86_64-linux/dist.sh | 1 + 7 files changed, 122 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index cf0862f7741cd..fd8bf473ca921 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -2281,9 +2281,9 @@ impl CommandLineStep for Assemble { if builder.config.llvm_offload && !builder.config.dry_run() { debug!("`llvm_offload` requested"); - let rust_offload = builder.ensure(llvm::RustOffload { target: build_compiler.host }); - let offload_install = builder.ensure(llvm::OmpOffload { target: build_compiler.host }); if let Some(_llvm_config) = builder.llvm_config(builder.config.host_target) { + let rust_offload = + builder.ensure(llvm::RustOffload { target: build_compiler.host }); let target_libdir = builder.sysroot_target_libdir(target_compiler, target_compiler.host); let rust_offload_dst_lib = target_libdir.join(rust_offload.rust_offload_filename()); @@ -2293,15 +2293,12 @@ impl CommandLineStep for Assemble { FileType::NativeLibrary, ); - for p in offload_install.offload_paths() { + let omp_offload = builder.ensure(llvm::OmpOffload { target: build_compiler.host }); + for p in omp_offload.artifact_paths_with_symlink_targets() { let libname = p.file_name().unwrap(); let dst_lib = target_libdir.join(libname); builder.resolve_symlink_and_copy(&p, &dst_lib); } - // FIXME(offload): Add amdgcn-amd-amdhsa and nvptx64-nvidia-cuda folder - // This one is slightly more tricky, since we have the same file twice, in two - // subfolders for amdgcn and nvptx64. We'll likely find two more in the future, once - // Intel and Spir-V support lands in offload. } } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 3d0a1ca07fb50..43ac42a8158ba 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -2813,6 +2813,62 @@ impl CommandLineStep for Enzyme { } } +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct Offload { + pub target: TargetSelection, +} + +impl CommandLineStep for Offload { + type Output = Option; + const IS_HOST: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("offload") + } + + fn is_default_step(builder: &Builder<'_>) -> bool { + builder.config.llvm_offload + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Offload { target: run.target }); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + if !builder.unstable_features() { + return None; + } + + let target = self.target; + + let omp_offload = builder.ensure(llvm::OmpOffload { target }); + let rust_offload = builder.ensure(llvm::RustOffload { target }); + + if builder.config.dry_run() { + return None; + } + + let target_libdir = PathBuf::from(format!("lib/rustlib/{}/lib", target.triple)); + + let mut tarball = Tarball::new(builder, "offload", &target.triple); + tarball.set_overlay(OverlayKind::Offload); + tarball.is_preview(true); + + let omp_offload_libdir = builder.out.join(target).join("offload").join("lib"); + + for path in omp_offload.artifact_paths_with_symlink_targets() { + let relative = t!(path.strip_prefix(&omp_offload_libdir)); + let destdir = target_libdir.join(relative.parent().unwrap()); + + tarball.add_file(path, destdir, FileType::NativeLibrary); + } + + tarball.add_file(rust_offload.rust_offload_path(), target_libdir, FileType::NativeLibrary); + + Some(tarball.generate()) + } +} + /// Tarball intended for internal consumption to ease rustc/std development. /// /// Should not be considered stable by end users. diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 88a39682cd507..a402092e7d0e2 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1046,8 +1046,25 @@ pub struct BuiltOmpOffload { } impl BuiltOmpOffload { - pub fn offload_paths(&self) -> Vec { - self.offload.clone() + pub fn artifact_paths_with_symlink_targets(&self) -> Vec { + let mut paths = self.offload.clone(); + + for path in &self.offload { + let mut current = path.clone(); + + while t!(fs::symlink_metadata(¤t)).file_type().is_symlink() { + let target = t!(fs::read_link(¤t)); + current = current.parent().unwrap().join(target); + + if paths.contains(¤t) { + break; + } + + paths.push(current.clone()); + } + } + + paths } } @@ -1101,6 +1118,30 @@ impl CommandLineStep for OmpOffload { files.push(out_dir.join("lib").join("libLLVMOffload").with_extension(lib_ext)); files.push(out_dir.join("lib").join("libomp").with_extension(lib_ext)); files.push(out_dir.join("lib").join("libomptarget").with_extension(lib_ext)); + files.push( + out_dir.join("lib").join("amdgcn-amd-amdhsa").join("libompdevice").with_extension("a"), + ); + files.push( + out_dir + .join("lib") + .join("amdgcn-amd-amdhsa") + .join("libomptarget-amdgpu") + .with_extension("bc"), + ); + files.push( + out_dir + .join("lib") + .join("nvptx64-nvidia-cuda") + .join("libompdevice") + .with_extension("a"), + ); + files.push( + out_dir + .join("lib") + .join("nvptx64-nvidia-cuda") + .join("libomptarget-nvptx") + .with_extension("bc"), + ); // Offload/OpenMP are just subfolders of LLVM, so we can use the LLVM sha. static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); @@ -1167,7 +1208,15 @@ impl CommandLineStep for OmpOffload { cflags.push_all(format!(" -I {inc_dir}")); } - configure_cmake(builder, target, &mut cfg, true, LdFlags::default(), cflags, &[]); + // Logic copied from `configure_llvm` + // ThinLTO is only available when building with LLVM, enabling LLD is required. + // Apple's linker ld64 supports ThinLTO out of the box though, so don't use LLD on Darwin. + let mut ldflags = LdFlags::default(); + if builder.config.llvm_thin_lto && !target.contains("apple") { + ldflags.push_all("-fuse-ld=lld"); + } + + configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]); // Re-use the same flags as llvm to control the level of debug information // generated for offload. @@ -1196,6 +1245,7 @@ impl CommandLineStep for OmpOffload { cfg.define("LLVM_ENABLE_RUNTIMES", "openmp;offload"); } else { // OpenMP provides some device libraries, so we also compile it for all gpu targets. + cfg.define("OPENMP_INSTALL_LIBDIR", Path::new("lib").join(omp_target)); cfg.define("LLVM_USE_LINKER", "lld"); cfg.define("LLVM_ENABLE_RUNTIMES", "openmp"); cfg.define("CMAKE_C_COMPILER_TARGET", omp_target); diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 6aba8da8a0bac..ffe99e3de6738 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -1018,6 +1018,7 @@ impl<'a> Builder<'a> { dist::LlvmBitcodeLinker, dist::RustDev, dist::Enzyme, + dist::Offload, dist::Bootstrap, dist::Extended, // It seems that PlainSourceTarball somehow changes how some of the tools diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index 17d75e83daeac..87e975e8dfad9 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -29,6 +29,7 @@ pub(crate) enum OverlayKind { Gcc, LlvmBitcodeLinker, Enzyme, + Offload, } impl OverlayKind { @@ -39,6 +40,9 @@ impl OverlayKind { &["src/llvm-project/llvm/LICENSE.TXT", "src/llvm-project/llvm/README.txt"] } OverlayKind::Enzyme => &["src/tools/enzyme/LICENSE", "src/tools/enzyme/Readme.md"], + OverlayKind::Offload => { + &["src/llvm-project/openmp/LICENSE.TXT", "src/llvm-project/offload/README.md"] + } OverlayKind::Cargo => &[ "src/tools/cargo/README.md", "src/tools/cargo/LICENSE-MIT", @@ -114,6 +118,7 @@ impl OverlayKind { OverlayKind::LlvmBitcodeLinker => builder.rust_version(), OverlayKind::Gcc => builder.rust_version(), OverlayKind::Enzyme => builder.rust_version(), + OverlayKind::Offload => builder.rust_version(), } } } diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 2db64b8f5c7c1..6a5bdf05157bb 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -65,7 +65,7 @@ RUN ./cmake.sh # Now build LLVM+Clang, afterwards configuring further compilations to use the # clang/clang++ compilers. COPY scripts/build-clang.sh /tmp/ -ENV LLVM_BUILD_TARGETS=X86 +ENV LLVM_BUILD_TARGETS="X86;AMDGPU;NVPTX" RUN ./build-clang.sh ENV CC=clang CXX=clang++ @@ -91,6 +91,7 @@ ENV RUST_CONFIGURE_ARGS="--enable-full-tools \ --set llvm.ninja=false \ --set llvm.libzstd=true \ --set build.allocator=jemalloc \ + --set llvm.offload-clang-dir="/rustroot/lib/cmake/clang" \ --set rust.bootstrap-override-lld=true \ --set rust.lto=thin \ --set rust.codegen-units=1" diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh index 46d34cd001a95..f2f78b04d7787 100755 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/dist.sh @@ -10,6 +10,7 @@ python3 ../x.py build --set rust.debug=true opt-dist build-manifest \ bootstrap \ enzyme \ + offload \ rustc_codegen_gcc # Use GCC for building GCC components, as it seems to behave badly when built with Clang From 3eda5ccb9868d8516a8fe1623dc550ba044ea4ab Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 11 Aug 2026 10:27:26 +0200 Subject: [PATCH 3/4] Put `{:#?}` into backticks For consistency with `{:?}` before it --- library/core/src/fmt/mod.rs | 2 +- tests/ui/fmt/format-args-argument-span.stderr | 4 ++-- tests/ui/fmt/non-source-literals.stderr | 4 ++-- tests/ui/macros/macro-expansion-empty-span-147255.stderr | 2 +- tests/ui/on-unimplemented/no-debug.stderr | 4 ++-- tests/ui/suggestions/issue-97760.stderr | 2 +- tests/ui/suggestions/path-display.stderr | 4 ++-- .../binding-assigned-block-without-tail-expression.stderr | 8 ++++---- .../type/recover-from-semicolon-trailing-undefined.stderr | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index a5896f3f863cf..085366ddd1ae0 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1176,7 +1176,7 @@ pub use macros::Debug; ), on( from_desugaring = "FormatLiteral", - note = "in format strings you may be able to use `{{:?}}` (or {{:#?}} for pretty-print) instead", + note = "in format strings you may be able to use `{{:?}}` (or `{{:#?}}` for pretty-print) instead", label = "`{Self}` cannot be formatted with the default formatter", ), message = "`{Self}` doesn't implement `{This}`" diff --git a/tests/ui/fmt/format-args-argument-span.stderr b/tests/ui/fmt/format-args-argument-span.stderr index 76fc178bb3d44..0a01fc93e60d0 100644 --- a/tests/ui/fmt/format-args-argument-span.stderr +++ b/tests/ui/fmt/format-args-argument-span.stderr @@ -5,7 +5,7 @@ LL | println!("{x:?} {x} {x:?}"); | ^^^ `Option<{integer}>` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `Option<{integer}>` doesn't implement `std::fmt::Display` --> $DIR/format-args-argument-span.rs:15:37 @@ -16,7 +16,7 @@ LL | println!("{x:?} {x} {x:?}", x = Some(1)); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Option<{integer}>` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `DisplayOnly` doesn't implement `Debug` --> $DIR/format-args-argument-span.rs:18:19 diff --git a/tests/ui/fmt/non-source-literals.stderr b/tests/ui/fmt/non-source-literals.stderr index 39dc35653618f..db5e3a680a357 100644 --- a/tests/ui/fmt/non-source-literals.stderr +++ b/tests/ui/fmt/non-source-literals.stderr @@ -9,7 +9,7 @@ help: the trait `std::fmt::Display` is not implemented for `NonDisplay` | LL | pub struct NonDisplay; | ^^^^^^^^^^^^^^^^^^^^^ - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `NonDisplay` doesn't implement `std::fmt::Display` --> $DIR/non-source-literals.rs:10:45 @@ -22,7 +22,7 @@ help: the trait `std::fmt::Display` is not implemented for `NonDisplay` | LL | pub struct NonDisplay; | ^^^^^^^^^^^^^^^^^^^^^ - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `NonDebug` doesn't implement `Debug` --> $DIR/non-source-literals.rs:11:42 diff --git a/tests/ui/macros/macro-expansion-empty-span-147255.stderr b/tests/ui/macros/macro-expansion-empty-span-147255.stderr index cea691679988e..aac96d7b5db79 100644 --- a/tests/ui/macros/macro-expansion-empty-span-147255.stderr +++ b/tests/ui/macros/macro-expansion-empty-span-147255.stderr @@ -7,7 +7,7 @@ LL | println!("{}", x_str); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error: aborting due to 1 previous error diff --git a/tests/ui/on-unimplemented/no-debug.stderr b/tests/ui/on-unimplemented/no-debug.stderr index c078e0fd42531..645a1fe1d4bc3 100644 --- a/tests/ui/on-unimplemented/no-debug.stderr +++ b/tests/ui/on-unimplemented/no-debug.stderr @@ -36,7 +36,7 @@ help: the trait `std::fmt::Display` is not implemented for `Foo` | LL | struct Foo; | ^^^^^^^^^^ - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `Bar` doesn't implement `std::fmt::Display` --> $DIR/no-debug.rs:11:28 @@ -47,7 +47,7 @@ LL | println!("{} {}", Foo, Bar); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `Bar` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error: aborting due to 4 previous errors diff --git a/tests/ui/suggestions/issue-97760.stderr b/tests/ui/suggestions/issue-97760.stderr index f3dc3f74efe85..ddde573f50fd2 100644 --- a/tests/ui/suggestions/issue-97760.stderr +++ b/tests/ui/suggestions/issue-97760.stderr @@ -5,7 +5,7 @@ LL | println!("{x}"); | ^^^ `::Item` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `::Item` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead help: introduce a type parameter with a trait bound instead of using `impl Trait` | LL ~ pub fn print_values(values: &I) diff --git a/tests/ui/suggestions/path-display.stderr b/tests/ui/suggestions/path-display.stderr index 3594be2efcc47..c391093ecff38 100644 --- a/tests/ui/suggestions/path-display.stderr +++ b/tests/ui/suggestions/path-display.stderr @@ -8,7 +8,7 @@ LL | println!("{}", path); | = help: the trait `std::fmt::Display` is not implemented for `Path` = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead = note: required for `&Path` to implement `std::fmt::Display` error[E0277]: `PathBuf` doesn't implement `std::fmt::Display` @@ -21,7 +21,7 @@ LL | println!("{}", path); | = help: the trait `std::fmt::Display` is not implemented for `PathBuf` = note: call `.display()` or `.to_string_lossy()` to safely print paths, as they may contain non-Unicode data - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error: aborting due to 2 previous errors diff --git a/tests/ui/type/binding-assigned-block-without-tail-expression.stderr b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr index ed7ff22e501c0..5ddf34ebba2a9 100644 --- a/tests/ui/type/binding-assigned-block-without-tail-expression.stderr +++ b/tests/ui/type/binding-assigned-block-without-tail-expression.stderr @@ -10,7 +10,7 @@ LL | println!("{}", x); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:15:20 @@ -24,7 +24,7 @@ LL | println!("{}", y); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:16:20 @@ -38,7 +38,7 @@ LL | println!("{}", z); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0277]: `()` doesn't implement `std::fmt::Display` --> $DIR/binding-assigned-block-without-tail-expression.rs:17:20 @@ -55,7 +55,7 @@ LL | println!("{}", s); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error[E0308]: mismatched types --> $DIR/binding-assigned-block-without-tail-expression.rs:18:18 diff --git a/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr b/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr index 6a8295d493380..602c8f41f08af 100644 --- a/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr +++ b/tests/ui/type/recover-from-semicolon-trailing-undefined.stderr @@ -19,7 +19,7 @@ LL | println!("{}", x_str); | required by this formatting parameter | = help: the trait `std::fmt::Display` is not implemented for `()` - = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead + = note: in format strings you may be able to use `{:?}` (or `{:#?}` for pretty-print) instead error: aborting due to 2 previous errors From b531faf77541637815b44821d69475ffda567769 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 8 Aug 2026 17:45:44 +1000 Subject: [PATCH 4/4] Simplify absolute path handling The existing code takes a command-line argument (that might not even be a path), glues it to the repository path, makes it absolute relative to the working directory, then tries to strip the repository path off again. That all seems needlessly complicated. The new approach is much simpler: If an argument is an absolute path that exists, try to strip the repository path from it, or otherwise change nothing. That should hopefully give the same results in every useful case. --- src/bootstrap/src/core/builder/cli_paths.rs | 53 ++++++++++----------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/src/bootstrap/src/core/builder/cli_paths.rs b/src/bootstrap/src/core/builder/cli_paths.rs index 29daf64db49c7..5efbea64463fe 100644 --- a/src/bootstrap/src/core/builder/cli_paths.rs +++ b/src/bootstrap/src/core/builder/cli_paths.rs @@ -76,37 +76,34 @@ pub(crate) fn match_paths_to_steps_and_run( } } - // Attempt to resolve paths to be relative to the builder source directory. - let mut paths: Vec = paths + // Command-line paths are interpreted relative to the repository root + // (not the current working directory). + // + // If the user or shell passed an absolute path, try to strip off the + // repository root, to match the paths registered by command-line steps. + // + // E.g. `/home/ferris/rust/tests/ui/asm/cfg.rs` => `tests/ui/asm/cfg.rs` + let mut paths = paths .iter() - .map(|original_path| { - let mut path = original_path.clone(); - - // Someone could run `x ` from a different repository than the source - // directory. - // In that case, we should not try to resolve the paths relative to the working - // directory, but rather relative to the source directory. - // So we forcefully "relocate" the path to the source directory here. - if !path.is_absolute() { - path = builder.src.join(path); - } - - // If the path does not exist, it may represent the name of a Step, such as `tidy` in `x test tidy` - if !path.exists() { - // Use the original path here - return original_path.clone(); - } - - // Make the path absolute, strip the prefix, and convert to a PathBuf. - match std::path::absolute(&path) { - Ok(p) => p.strip_prefix(&builder.src).unwrap_or(&p).to_path_buf(), - Err(e) => { - eprintln!("ERROR: {e:?}"); - panic!("Due to the above error, failed to resolve path: {path:?}"); - } + .map(|path| { + if path.is_absolute() + && path.exists() + && let Ok(relative) = path.strip_prefix(&builder.src) + { + relative + } else { + path } }) - .collect(); + .map(|p| p.to_owned()) + .collect::>(); + + // If any absolute paths couldn't be made relative, stop now and report them. + let bad_abs_paths = paths.iter().filter(|path| path.is_absolute()).collect::>(); + if !bad_abs_paths.is_empty() { + eprintln!("ERROR: failed to resolve absolute paths: {bad_abs_paths:#?}"); + crate::exit!(1); + } // Handle all test suite paths. // (This is separate from the loop below to avoid having to handle multiple paths in `is_suite_path` somehow.)