From c5b4606d2a2070f1e7d79622d6be83138b54de31 Mon Sep 17 00:00:00 2001 From: apiraino Date: Mon, 28 Jul 2025 15:16:00 +0200 Subject: [PATCH 01/13] Enable t-compiler backport nomination --- triagebot.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 894f56df74196..e1b4983adf7b6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -50,6 +50,21 @@ remove_labels = ["S-waiting-on-author"] # Those labels are added when PR author requests a review from an assignee add_labels = ["S-waiting-on-review"] +# [backport.*] sections autonominate pull requests for a backport +# see: https://forge.rust-lang.org/triagebot/backport.html + +[backport.t-compiler-beta-backport] +# The pull request MUST have one of these labels +required-pr-labels = ["T-compiler"] +# The regression MUST have this label +required-issue-label = "regression-from-stable-to-beta" +# if the above conditions matches, the PR will receive these labels +add-labels = ["beta-nominated"] + +[backport.t-compiler-stable-backport] +required-pr-labels = ["T-compiler"] +required-issue-label = "regression-from-stable-to-stable" +add-labels = ["stable-nominated"] # ------------------------------------------------------------------------------ # Ping groups From 56d9ed74452c8e19c532e98294d5d01925822e94 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 22 Jul 2025 14:18:46 +0200 Subject: [PATCH 02/13] Fix nvptx-safe-naming.rs test on LLVM 21 This is now printed on the same line. Use NEXT/SAME depending on the LLVM version. --- tests/assembly-llvm/nvptx-safe-naming.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/assembly-llvm/nvptx-safe-naming.rs b/tests/assembly-llvm/nvptx-safe-naming.rs index d7b46aadd9cc1..6a6659a4e3047 100644 --- a/tests/assembly-llvm/nvptx-safe-naming.rs +++ b/tests/assembly-llvm/nvptx-safe-naming.rs @@ -1,6 +1,9 @@ //@ assembly-output: ptx-linker //@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc //@ only-nvptx64 +//@ revisions: LLVM20 LLVM21 +//@ [LLVM21] min-llvm-version: 21 +//@ [LLVM20] max-llvm-major-version: 20 #![feature(abi_ptx)] #![no_std] @@ -15,7 +18,8 @@ extern crate breakpoint_panic_handler; #[no_mangle] pub unsafe extern "ptx-kernel" fn top_kernel(a: *const u32, b: *mut u32) { // CHECK: call.uni (retval0), - // CHECK-NEXT: [[IMPL_FN]] + // LLVM20-NEXT: [[IMPL_FN]] + // LLVM21-SAME: [[IMPL_FN]] *b = deep::private::MyStruct::new(*a).square(); } From d50b4f10f18b2f84be72692e39dd5de7e8dde949 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 29 Jul 2025 12:05:36 +0200 Subject: [PATCH 03/13] Adjust enum-discriminant-eq.rs for LLVM 21 The two xors get folded into the select. --- tests/codegen-llvm/enum/enum-discriminant-eq.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/codegen-llvm/enum/enum-discriminant-eq.rs b/tests/codegen-llvm/enum/enum-discriminant-eq.rs index 0494c5f551b33..d599685c2e51b 100644 --- a/tests/codegen-llvm/enum/enum-discriminant-eq.rs +++ b/tests/codegen-llvm/enum/enum-discriminant-eq.rs @@ -1,6 +1,9 @@ //@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled //@ min-llvm-version: 20 //@ only-64bit +//@ revisions: LLVM20 LLVM21 +//@ [LLVM21] min-llvm-version: 21 +//@ [LLVM20] max-llvm-major-version: 20 // The `derive(PartialEq)` on enums with field-less variants compares discriminants, // so make sure we emit that in some reasonable way. @@ -137,17 +140,20 @@ pub fn mid_nz32_eq_discr(a: Mid>, b: Mid>) -> bool { pub fn mid_ac_eq_discr(a: Mid, b: Mid) -> bool { // CHECK-LABEL: @mid_ac_eq_discr( - // CHECK: %[[A_REL_DISCR:.+]] = xor i8 %a, -128 + // LLVM20: %[[A_REL_DISCR:.+]] = xor i8 %a, -128 // CHECK: %[[A_IS_NICHE:.+]] = icmp slt i8 %a, 0 // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %a, -127 // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]]) - // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1 + // LLVM20: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1 - // CHECK: %[[B_REL_DISCR:.+]] = xor i8 %b, -128 + // LLVM20: %[[B_REL_DISCR:.+]] = xor i8 %b, -128 // CHECK: %[[B_IS_NICHE:.+]] = icmp slt i8 %b, 0 // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %b, -127 // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]]) - // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1 + // LLVM20: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1 + + // LLVM21: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %a, i8 -127 + // LLVM21: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %b, i8 -127 // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]] // CHECK: ret i1 %[[R]] From 652b9eb98b3dc5be8b2b65954e252e9e272c3447 Mon Sep 17 00:00:00 2001 From: FractalFir Date: Tue, 29 Jul 2025 12:42:48 +0200 Subject: [PATCH 04/13] Add support for the m68k architecture in 'object_architecture' --- compiler/rustc_target/src/spec/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c64cd9a51b7d2..033590e01a67d 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -3598,6 +3598,7 @@ impl Target { ), "x86" => (Architecture::I386, None), "s390x" => (Architecture::S390x, None), + "m68k" => (Architecture::M68k, None), "mips" | "mips32r6" => (Architecture::Mips, None), "mips64" | "mips64r6" => ( // While there are currently no builtin targets From ccf660f855eec84f976ed07190d9e8a8b93e2c1f Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Tue, 29 Jul 2025 14:07:27 +0200 Subject: [PATCH 05/13] Relax check lines in x86-return-float.rs On LLVM 21 additional %esp adjustments are generated. Don't use NEXT to allow these. --- tests/assembly-llvm/x86-return-float.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/assembly-llvm/x86-return-float.rs b/tests/assembly-llvm/x86-return-float.rs index 165c11d228011..4db93f68485a3 100644 --- a/tests/assembly-llvm/x86-return-float.rs +++ b/tests/assembly-llvm/x86-return-float.rs @@ -334,9 +334,9 @@ pub fn return_f128(x: f128) -> f128 { // linux-NEXT: .cfi_offset // CHECK-NEXT: movl %esp, %ebp // linux-NEXT: .cfi_def_cfa_register - // linux-NEXT: movaps 8(%ebp), %xmm0 - // win-NEXT: movups 8(%ebp), %xmm0 - // CHECK-NEXT: popl %ebp + // linux: movaps 8(%ebp), %xmm0 + // win: movups 8(%ebp), %xmm0 + // CHECK: popl %ebp // linux-NEXT: .cfi_def_cfa // CHECK-NEXT: retl x From c39b4479ce6f33604000b9ffdc91d2e8e115cb41 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Mon, 28 Jul 2025 21:21:59 +0200 Subject: [PATCH 06/13] "Cachify" `ExternPreludeEntry.binding` through a `Cell`. --- compiler/rustc_resolve/src/build_reduced_graph.rs | 11 +++++------ compiler/rustc_resolve/src/lib.rs | 12 ++++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index b15b478a6be9f..7912345ec56ac 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -984,18 +984,17 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> { // more details: https://github.com/rust-lang/rust/pull/111761 return; } - let entry = self - .r - .extern_prelude - .entry(ident) - .or_insert(ExternPreludeEntry { binding: None, introduced_by_item: true }); + let entry = self.r.extern_prelude.entry(ident).or_insert(ExternPreludeEntry { + binding: Cell::new(None), + introduced_by_item: true, + }); if orig_name.is_some() { entry.introduced_by_item = true; } // Binding from `extern crate` item in source code can replace // a binding from `--extern` on command line here. if !entry.is_import() { - entry.binding = Some(imported_binding) + entry.binding.set(Some(imported_binding)); } else if ident.name != kw::Underscore { self.r.dcx().span_delayed_bug( item.span, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 8115b87dcae06..88dfb50b47dd7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1009,13 +1009,13 @@ impl<'ra> NameBindingData<'ra> { #[derive(Default, Clone)] struct ExternPreludeEntry<'ra> { - binding: Option>, + binding: Cell>>, introduced_by_item: bool, } impl ExternPreludeEntry<'_> { fn is_import(&self) -> bool { - self.binding.is_some_and(|binding| binding.is_import()) + self.binding.get().is_some_and(|binding| binding.is_import()) } } @@ -2006,7 +2006,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // but not introduce it, as used if they are accessed from lexical scope. if used == Used::Scope { if let Some(entry) = self.extern_prelude.get(&ident.normalize_to_macros_2_0()) { - if !entry.introduced_by_item && entry.binding == Some(used_binding) { + if !entry.introduced_by_item && entry.binding.get() == Some(used_binding) { return; } } @@ -2170,7 +2170,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let norm_ident = ident.normalize_to_macros_2_0(); let binding = self.extern_prelude.get(&norm_ident).cloned().and_then(|entry| { - Some(if let Some(binding) = entry.binding { + Some(if let Some(binding) = entry.binding.get() { if finalize { if !entry.is_import() { self.cstore_mut().process_path_extern(self.tcx, ident.name, ident.span); @@ -2195,8 +2195,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }) }); - if let Some(entry) = self.extern_prelude.get_mut(&norm_ident) { - entry.binding = binding; + if let Some(entry) = self.extern_prelude.get(&norm_ident) { + entry.binding.set(binding); } binding From 0b807fc1afafb52a97f596c3ba3d926aabe6a1ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 29 Jul 2025 16:18:52 +0200 Subject: [PATCH 07/13] Update rustc-perf submodule --- src/tools/rustc-perf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustc-perf b/src/tools/rustc-perf index 6a70166b92a1b..dde879cf1087c 160000 --- a/src/tools/rustc-perf +++ b/src/tools/rustc-perf @@ -1 +1 @@ -Subproject commit 6a70166b92a1b1560cb3cf056427b011b2a1f2bf +Subproject commit dde879cf1087cb34a32287bd8ccc4d545bb9fee5 From d1a877aac268c6bd6cb66f8c7bc5152a080439a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 29 Jul 2025 16:36:48 +0200 Subject: [PATCH 08/13] Improve tidy error on dependency license exceptions --- src/tools/tidy/src/deps.rs | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8e2a796106f47..b9ad8b1404fc4 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -599,7 +599,7 @@ pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) { .other_options(vec!["--locked".to_owned()]); let metadata = t!(cmd.exec()); - check_license_exceptions(&metadata, exceptions, bad); + check_license_exceptions(&metadata, workspace, exceptions, bad); if let Some((crates, permitted_deps)) = permitted_deps { check_permitted_dependencies(&metadata, workspace, permitted_deps, crates, bad); } @@ -730,14 +730,19 @@ fn check_runtime_license_exceptions(metadata: &Metadata, bad: &mut bool) { /// Check that all licenses of tool dependencies are in the valid list in `LICENSES`. /// /// Packages listed in `exceptions` are allowed for tools. -fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], bad: &mut bool) { +fn check_license_exceptions( + metadata: &Metadata, + workspace: &str, + exceptions: &[(&str, &str)], + bad: &mut bool, +) { // Validate the EXCEPTIONS list hasn't changed. for (name, license) in exceptions { // Check that the package actually exists. if !metadata.packages.iter().any(|p| *p.name == *name) { tidy_error!( bad, - "could not find exception package `{}`\n\ + "could not find exception package `{}` in workspace `{workspace}`\n\ Remove from EXCEPTIONS list if it is no longer used.", name ); @@ -753,13 +758,15 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba } tidy_error!( bad, - "dependency exception `{}` does not declare a license expression", + "dependency exception `{}` in workspace `{workspace}` does not declare a license expression", pkg.id ); } Some(pkg_license) => { if pkg_license.as_str() != *license { - println!("dependency exception `{name}` license has changed"); + println!( + "dependency exception `{name}` license in workspace `{workspace}` has changed" + ); println!(" previously `{license}` now `{pkg_license}`"); println!(" update EXCEPTIONS for the new license"); *bad = true; @@ -783,12 +790,21 @@ fn check_license_exceptions(metadata: &Metadata, exceptions: &[(&str, &str)], ba let license = match &pkg.license { Some(license) => license, None => { - tidy_error!(bad, "dependency `{}` does not define a license expression", pkg.id); + tidy_error!( + bad, + "dependency `{}` in workspace `{workspace}` does not define a license expression", + pkg.id + ); continue; } }; if !LICENSES.contains(&license.as_str()) { - tidy_error!(bad, "invalid license `{}` in `{}`", license, pkg.id); + tidy_error!( + bad, + "invalid license `{}` for package `{}` in workspace `{workspace}`", + license, + pkg.id + ); } } } From ab4024eb31bf341cb92e1acb1db78e6cab6c434a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 29 Jul 2025 16:41:10 +0200 Subject: [PATCH 09/13] Update license exceptions for rustc-perf --- src/tools/tidy/src/deps.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b9ad8b1404fc4..1ff0349cc1ebb 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -167,7 +167,7 @@ const EXCEPTIONS_RUSTC_PERF: ExceptionList = &[ ("brotli-decompressor", "BSD-3-Clause/MIT"), ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("inferno", "CDDL-1.0"), - ("ring", NON_STANDARD_LICENSE), // see EXCEPTIONS_NON_STANDARD_LICENSE_DEPS for more. + ("option-ext", "MPL-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), ("snap", "BSD-3-Clause"), ("subtle", "BSD-3-Clause"), From b60026ab4277a8b37aa0a812baf977b3766520aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 29 Jul 2025 16:41:44 +0200 Subject: [PATCH 10/13] Remove no longer needed handling of nonstandard licenses --- src/tools/tidy/src/deps.rs | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 1ff0349cc1ebb..858b058cb7d05 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -226,20 +226,6 @@ const EXCEPTIONS_UEFI_QEMU_TEST: ExceptionList = &[ ("r-efi", "MIT OR Apache-2.0 OR LGPL-2.1-or-later"), // LGPL is not acceptable, but we use it under MIT OR Apache-2.0 ]; -/// Placeholder for non-standard license file. -const NON_STANDARD_LICENSE: &str = "NON_STANDARD_LICENSE"; - -/// These dependencies have non-standard licenses but are genenrally permitted. -const EXCEPTIONS_NON_STANDARD_LICENSE_DEPS: &[&str] = &[ - // `ring` is included because it is an optional dependency of `hyper`, - // which is a training data in rustc-perf for optimized build. - // The license of it is generally `ISC AND MIT AND OpenSSL`, - // though the `package.license` field is not set. - // - // See https://github.com/briansmith/ring/issues/902 - "ring", -]; - const PERMITTED_DEPS_LOCATION: &str = concat!(file!(), ":", line!()); /// Crates rustc is allowed to depend on. Avoid adding to the list if possible. @@ -751,11 +737,6 @@ fn check_license_exceptions( for pkg in metadata.packages.iter().filter(|p| *p.name == *name) { match &pkg.license { None => { - if *license == NON_STANDARD_LICENSE - && EXCEPTIONS_NON_STANDARD_LICENSE_DEPS.contains(&pkg.name.as_str()) - { - continue; - } tidy_error!( bad, "dependency exception `{}` in workspace `{workspace}` does not declare a license expression", From 77fc593a6a372d6d8adc3f1b96416f93c3d1aa8d Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Jul 2025 07:22:56 -0700 Subject: [PATCH 11/13] Update wasi-sdk to 27.0 in CI This updates the wasi-sdk used in CI to build release binaries and run CI with. No major motivation beyond keeping things up-to-date and following the development of wasi-sdk. --- src/ci/docker/host-x86_64/dist-various-2/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/test-various/Dockerfile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile index e1d83d360872c..0855ea222a36d 100644 --- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile @@ -81,9 +81,9 @@ RUN /tmp/build-fuchsia-toolchain.sh COPY host-x86_64/dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/ RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/tmp/wasi-sdk-25.0-x86_64-linux +ENV WASI_SDK_PATH=/tmp/wasi-sdk-27.0-x86_64-linux COPY scripts/freebsd-toolchain.sh /tmp/ RUN /tmp/freebsd-toolchain.sh i686 diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile index 662a26400ce9d..82a820c859dc7 100644 --- a/src/ci/docker/host-x86_64/test-various/Dockerfile +++ b/src/ci/docker/host-x86_64/test-various/Dockerfile @@ -40,9 +40,9 @@ WORKDIR / COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh -RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-25/wasi-sdk-25.0-x86_64-linux.tar.gz | \ +RUN curl -L https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-27/wasi-sdk-27.0-x86_64-linux.tar.gz | \ tar -xz -ENV WASI_SDK_PATH=/wasi-sdk-25.0-x86_64-linux +ENV WASI_SDK_PATH=/wasi-sdk-27.0-x86_64-linux ENV RUST_CONFIGURE_ARGS \ --musl-root-x86_64=/usr/local/x86_64-linux-musl \ From 307fd41123bd9ce4ff9e4e9767f3f7771d91d789 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Wed, 16 Jul 2025 19:42:23 +0200 Subject: [PATCH 12/13] tests: Test line number in debuginfo for diverging function calls --- .../diverging-function-call-debuginfo.rs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 tests/codegen-llvm/diverging-function-call-debuginfo.rs diff --git a/tests/codegen-llvm/diverging-function-call-debuginfo.rs b/tests/codegen-llvm/diverging-function-call-debuginfo.rs new file mode 100644 index 0000000000000..1a80fe1643dea --- /dev/null +++ b/tests/codegen-llvm/diverging-function-call-debuginfo.rs @@ -0,0 +1,38 @@ +/// Make sure that line debuginfo is correct for diverging calls under certain +/// conditions. In particular we want to ensure that the line number is never +/// 0, but we check the absence of 0 by looking for the expected exact line +/// numbers. Regression test for . + +//@ compile-flags: -g -Clto -Copt-level=0 +//@ no-prefer-dynamic + +// First find the scope of both diverge() calls, namely this main() function. +// CHECK-DAG: [[MAIN_SCOPE:![0-9]+]] = distinct !DISubprogram(name: "main", linkageName: {{.*}}diverging_function_call_debuginfo{{.*}}main{{.*}} +fn main() { + if True == False { + // unreachable + // Then find the DILocation with the correct line number for this call ... + // CHECK-DAG: [[UNREACHABLE_CALL_DBG:![0-9]+]] = !DILocation(line: [[@LINE+1]], {{.*}}scope: [[MAIN_SCOPE]] + diverge(); + } + + // ... and this call. + // CHECK-DAG: [[LAST_CALL_DBG:![0-9]+]] = !DILocation(line: [[@LINE+1]], {{.*}}scope: [[MAIN_SCOPE]] + diverge(); +} + +#[derive(PartialEq)] +pub enum MyBool { + True, + False, +} + +use MyBool::*; + +fn diverge() -> ! { + panic!(); +} + +// Finally make sure both DILocations belong to each the respective diverge() call. +// CHECK-DAG: call void {{.*}}diverging_function_call_debuginfo{{.*}}diverge{{.*}} !dbg [[LAST_CALL_DBG]] +// CHECK-DAG: call void {{.*}}diverging_function_call_debuginfo{{.*}}diverge{{.*}} !dbg [[UNREACHABLE_CALL_DBG]] From 05da623016f7bfed812261f2793b4b589631a6b0 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 26 Jul 2025 20:13:07 +0200 Subject: [PATCH 13/13] Fix Ord, Eq and Hash implementation of panic::Location Faster equality compare Add tests Add missing files for tests --- library/core/src/panic/location.rs | 42 +++++++++++++++++- library/coretests/tests/panic/location.rs | 43 ++++++++++++++++++- .../coretests/tests/panic/location/file_a.rs | 15 +++++++ .../coretests/tests/panic/location/file_b.rs | 15 +++++++ .../coretests/tests/panic/location/file_c.rs | 11 +++++ 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 library/coretests/tests/panic/location/file_a.rs create mode 100644 library/coretests/tests/panic/location/file_b.rs create mode 100644 library/coretests/tests/panic/location/file_c.rs diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index 972270208852a..6ef7d5a22a30f 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -1,5 +1,7 @@ +use crate::cmp::Ordering; use crate::ffi::CStr; use crate::fmt; +use crate::hash::{Hash, Hasher}; use crate::marker::PhantomData; use crate::ptr::NonNull; @@ -32,7 +34,7 @@ use crate::ptr::NonNull; /// Files are compared as strings, not `Path`, which could be unexpected. /// See [`Location::file`]'s documentation for more discussion. #[lang = "panic_location"] -#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)] +#[derive(Copy, Clone)] #[stable(feature = "panic_hooks", since = "1.10.0")] pub struct Location<'a> { // A raw pointer is used rather than a reference because the pointer is valid for one more byte @@ -44,6 +46,44 @@ pub struct Location<'a> { _filename: PhantomData<&'a str>, } +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl PartialEq for Location<'_> { + fn eq(&self, other: &Self) -> bool { + // Compare col / line first as they're cheaper to compare and more likely to differ, + // while not impacting the result. + self.col == other.col && self.line == other.line && self.file() == other.file() + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Eq for Location<'_> {} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Ord for Location<'_> { + fn cmp(&self, other: &Self) -> Ordering { + self.file() + .cmp(other.file()) + .then_with(|| self.line.cmp(&other.line)) + .then_with(|| self.col.cmp(&other.col)) + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl PartialOrd for Location<'_> { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +#[stable(feature = "panic_hooks", since = "1.10.0")] +impl Hash for Location<'_> { + fn hash(&self, state: &mut H) { + self.file().hash(state); + self.line.hash(state); + self.col.hash(state); + } +} + #[stable(feature = "panic_hooks", since = "1.10.0")] impl fmt::Debug for Location<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/library/coretests/tests/panic/location.rs b/library/coretests/tests/panic/location.rs index 5ce0b06e90e1a..910001bcc1c58 100644 --- a/library/coretests/tests/panic/location.rs +++ b/library/coretests/tests/panic/location.rs @@ -3,6 +3,23 @@ use core::panic::Location; // Note: Some of the following tests depend on the source location, // so please be careful when editing this file. +mod file_a; +mod file_b; +mod file_c; + +// A small shuffled set of locations for testing, along with their true order. +const LOCATIONS: [(usize, &'static Location<'_>); 9] = [ + (7, file_c::two()), + (0, file_a::one()), + (3, file_b::one()), + (5, file_b::three()), + (8, file_c::three()), + (6, file_c::one()), + (2, file_a::three()), + (4, file_b::two()), + (1, file_a::two()), +]; + #[test] fn location_const_caller() { const _CALLER_REFERENCE: &Location<'static> = Location::caller(); @@ -20,7 +37,7 @@ fn location_const_file() { fn location_const_line() { const CALLER: &Location<'static> = Location::caller(); const LINE: u32 = CALLER.line(); - assert_eq!(LINE, 21); + assert_eq!(LINE, 38); } #[test] @@ -34,6 +51,28 @@ fn location_const_column() { fn location_debug() { let f = format!("{:?}", Location::caller()); assert!(f.contains(&format!("{:?}", file!()))); - assert!(f.contains("35")); + assert!(f.contains("52")); assert!(f.contains("29")); } + +#[test] +fn location_eq() { + for (i, a) in LOCATIONS { + for (j, b) in LOCATIONS { + if i == j { + assert_eq!(a, b); + } else { + assert_ne!(a, b); + } + } + } +} + +#[test] +fn location_ord() { + let mut locations = LOCATIONS.clone(); + locations.sort_by_key(|(_o, l)| **l); + for (correct, (order, _l)) in locations.iter().enumerate() { + assert_eq!(correct, *order); + } +} diff --git a/library/coretests/tests/panic/location/file_a.rs b/library/coretests/tests/panic/location/file_a.rs new file mode 100644 index 0000000000000..1ceb225ee9c39 --- /dev/null +++ b/library/coretests/tests/panic/location/file_a.rs @@ -0,0 +1,15 @@ +use core::panic::Location; + +// Used for test super::location_{ord, eq}. Must be in a dedicated file. + +pub const fn one() -> &'static Location<'static> { + Location::caller() +} + +pub const fn two() -> &'static Location<'static> { + Location::caller() +} + +pub const fn three() -> &'static Location<'static> { + Location::caller() +} diff --git a/library/coretests/tests/panic/location/file_b.rs b/library/coretests/tests/panic/location/file_b.rs new file mode 100644 index 0000000000000..1ceb225ee9c39 --- /dev/null +++ b/library/coretests/tests/panic/location/file_b.rs @@ -0,0 +1,15 @@ +use core::panic::Location; + +// Used for test super::location_{ord, eq}. Must be in a dedicated file. + +pub const fn one() -> &'static Location<'static> { + Location::caller() +} + +pub const fn two() -> &'static Location<'static> { + Location::caller() +} + +pub const fn three() -> &'static Location<'static> { + Location::caller() +} diff --git a/library/coretests/tests/panic/location/file_c.rs b/library/coretests/tests/panic/location/file_c.rs new file mode 100644 index 0000000000000..2ac416c19cf48 --- /dev/null +++ b/library/coretests/tests/panic/location/file_c.rs @@ -0,0 +1,11 @@ +// Used for test super::location_{ord, eq}. Must be in a dedicated file. + +// This is used for testing column ordering of Location, hence this ugly one-liner. +// We must fmt skip the entire containing module or else tidy will still complain. +#[rustfmt::skip] +mod no_fmt { + use core::panic::Location; + pub const fn one() -> &'static Location<'static> { Location::caller() } pub const fn two() -> &'static Location<'static> { Location::caller() } pub const fn three() -> &'static Location<'static> { Location::caller() } +} + +pub use no_fmt::*;