From ef9eff9064d3d1ae024930d1a7792f77b4f9751e Mon Sep 17 00:00:00 2001 From: Karl Meakin Date: Sun, 3 May 2026 21:16:44 +0100 Subject: [PATCH 01/33] Further optimize `SliceIndex` impl for `Range` We can shave a further 2 `icmp`s by inlining `is_char_boundary` and rearranging the checks. --- library/core/src/str/traits.rs | 93 ++++++++++-------------- tests/codegen-llvm/str-range-indexing.rs | 13 ++-- 2 files changed, 46 insertions(+), 60 deletions(-) diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index 3b5cec22b69ea..21d1a5b907aa8 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -118,6 +118,35 @@ unsafe impl const SliceIndex for ops::RangeFull { } } +/// Check that a range is in bounds for slicing a string. +/// If this returns true, it is safe to call `slice.get_unchecked(range)` or +/// `slice.get_unchecked_mut(range)`. +#[inline(always)] +const fn check_range(slice: &str, range: crate::range::Range) -> bool { + let crate::range::Range { start, end } = range; + let bytes = slice.as_bytes(); + + if start > end || end > slice.len() { + return false; + } + + if start == slice.len() { + // If `start == slice.len()`, then `end == slice.len()` must also be true. + return true; + } + + // SAFETY: + // `start > end || end > slice.len()` is false, so `start <= end <= slice.len()` is true. + // `start == slice.len()` is false, so `start < slice.len()` is also true. + // + // No need to check for `end == 0`, because if `end == 0` is true then `start == slice.len()` + // would also be true, which is already handled above. + unsafe { + (start == 0 || bytes.as_ptr().add(start).read().is_utf8_char_boundary()) + && (end == slice.len() || bytes.as_ptr().add(end).read().is_utf8_char_boundary()) + } +} + /// Implements substring slicing with syntax `&self[begin .. end]` or `&mut /// self[begin .. end]`. /// @@ -159,30 +188,11 @@ unsafe impl const SliceIndex for ops::Range { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary, - // and we are passing in a safe reference, so the return value will also be one. - // We also checked char boundaries, so this is valid UTF-8. - Some(unsafe { &*self.get_unchecked(slice) }) - } else { - None - } + range::Range::from(self).get(slice) } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary. - // We know the pointer is unique because we got it from `slice`. - Some(unsafe { &mut *self.get_unchecked_mut(slice) }) - } else { - None - } + range::Range::from(self).get_mut(slice) } #[inline] #[track_caller] @@ -235,26 +245,11 @@ unsafe impl const SliceIndex for ops::Range { } #[inline] fn index(self, slice: &str) -> &Self::Output { - let (start, end) = (self.start, self.end); - match self.get(slice) { - Some(s) => s, - None => super::slice_error_fail(slice, start, end), - } + range::Range::from(self).index(slice) } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - // is_char_boundary checks that the index is in [0, .len()] - // cannot reuse `get` as above, because of NLL trouble - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary, - // and we are passing in a safe reference, so the return value will also be one. - unsafe { &mut *self.get_unchecked_mut(slice) } - } else { - super::slice_error_fail(slice, self.start, self.end) - } + range::Range::from(self).index_mut(slice) } } @@ -264,11 +259,8 @@ unsafe impl const SliceIndex for range::Range { type Output = str; #[inline] fn get(self, slice: &str) -> Option<&Self::Output> { - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary, + if check_range(slice, self) { + // SAFETY: just checked that `self` is in bounds, // and we are passing in a safe reference, so the return value will also be one. // We also checked char boundaries, so this is valid UTF-8. Some(unsafe { &*self.get_unchecked(slice) }) @@ -278,11 +270,8 @@ unsafe impl const SliceIndex for range::Range { } #[inline] fn get_mut(self, slice: &mut str) -> Option<&mut Self::Output> { - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary. + if check_range(slice, self) { + // SAFETY: just checked that `self` is in bounds. // We know the pointer is unique because we got it from `slice`. Some(unsafe { &mut *self.get_unchecked_mut(slice) }) } else { @@ -348,13 +337,9 @@ unsafe impl const SliceIndex for range::Range { } #[inline] fn index_mut(self, slice: &mut str) -> &mut Self::Output { - // is_char_boundary checks that the index is in [0, .len()] // cannot reuse `get` as above, because of NLL trouble - if self.start <= self.end - && slice.is_char_boundary(self.start) - && slice.is_char_boundary(self.end) - { - // SAFETY: just checked that `start` and `end` are on a char boundary, + if check_range(slice, self) { + // SAFETY: just checked that `self` is in bounds, // and we are passing in a safe reference, so the return value will also be one. unsafe { &mut *self.get_unchecked_mut(slice) } } else { diff --git a/tests/codegen-llvm/str-range-indexing.rs b/tests/codegen-llvm/str-range-indexing.rs index 5fa8e0dd17d3c..57fd886f9fc71 100644 --- a/tests/codegen-llvm/str-range-indexing.rs +++ b/tests/codegen-llvm/str-range-indexing.rs @@ -18,18 +18,19 @@ macro_rules! tests { }; } -// 9 comparisons required: -// start <= end -// && (start == 0 || (start >= len && start == len) || bytes[start] >= -0x40) -// && (end == 0 || (end >= len && end == len) || bytes[end] >= -0x40) +// 7 comparisons required: +// start <= end && end <= len +// && (start == len || +// ( (start == 0 || bytes[start] >= -0x40) +// && (end == len || bytes[end] >= -0x40))) // CHECK-LABEL: @get_range -// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-COUNT-7: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret // CHECK-LABEL: @index_range -// CHECK-COUNT-9: %{{.+}} = icmp +// CHECK-COUNT-7: %{{.+}} = icmp // CHECK-NOT: %{{.+}} = icmp // CHECK: ret tests!(Range, get_range, index_range); From d2c767fc1c48ca6269750a21865c56675c29c0da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Tue, 5 May 2026 13:46:38 +0200 Subject: [PATCH 02/33] rustc: riscv: promote d, e, and f target_features to CfgStableToggleUnstable --- compiler/rustc_target/src/target_features.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index e2bf1c48b7b47..632f9c5f25700 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -610,9 +610,9 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("a", Stable, &["zaamo", "zalrsc"]), ("b", Stable, &["zba", "zbb", "zbs"]), ("c", Stable, &["zca"]), - ("d", Unstable(sym::riscv_target_feature), &["f"]), - ("e", Unstable(sym::riscv_target_feature), &[]), - ("f", Unstable(sym::riscv_target_feature), &["zicsr"]), + ("d", CfgStableToggleUnstable(sym::riscv_target_feature), &["f"]), + ("e", CfgStableToggleUnstable(sym::riscv_target_feature), &[]), + ("f", CfgStableToggleUnstable(sym::riscv_target_feature), &["zicsr"]), ( "forced-atomics", Stability::Forbidden { reason: "unsound because it changes the ABI of atomic operations" }, From d396920b4ee9602542b9ee6282ff5a3c4c6e981f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 6 May 2026 08:13:37 +0200 Subject: [PATCH 03/33] rustc: riscv: adapt target_feature tests --- .../abi-incompatible-target-feature-flag-enable.riscv.stderr | 2 +- .../abi-required-target-feature-flag-disable.riscv.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr index 11ec86b1e6d85..2183513bf3b97 100644 --- a/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr +++ b/tests/ui/target-feature/abi-incompatible-target-feature-flag-enable.riscv.stderr @@ -1,6 +1,6 @@ warning: unstable feature specified for `-Ctarget-feature`: `d` | - = note: this feature is not stably supported; its behavior can change in the future + = note: this feature is allowed in cfg but unstable otherwise; its behavior can change in the future warning: target feature `d` must be disabled to ensure that the ABI of the current target can be implemented correctly | diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr index cc225b353df13..7fa1cc299b229 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.riscv.stderr @@ -1,6 +1,6 @@ warning: unstable feature specified for `-Ctarget-feature`: `d` | - = note: this feature is not stably supported; its behavior can change in the future + = note: this feature is allowed in cfg but unstable otherwise; its behavior can change in the future warning: target feature `d` must be enabled to ensure that the ABI of the current target can be implemented correctly | From 4e9a3ded2a63a567a21aa245cdd8e8a2e065d86c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 6 May 2026 11:47:21 +0200 Subject: [PATCH 04/33] rustc: riscv: add tests for cfg-only stable features --- ...unstable-target-feature-attribute-riscv.rs | 17 ++++++++++++++ ...able-target-feature-attribute-riscv.stderr | 23 +++++++++++++++++++ ...stable-target-feature-flag-enable-riscv.rs | 17 ++++++++++++++ ...le-target-feature-flag-enable-riscv.stderr | 10 ++++++++ 4 files changed, 67 insertions(+) create mode 100644 tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs create mode 100644 tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.stderr create mode 100644 tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.rs create mode 100644 tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.stderr diff --git a/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs new file mode 100644 index 0000000000000..24d42e3df44d3 --- /dev/null +++ b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs @@ -0,0 +1,17 @@ +//! Ensure cfg-only stable target_features trigger errors when enabled via attribute. +//@ compile-flags: --crate-type=lib +//@ compile-flags: --target=riscv64gc-unknown-none-elf +//@ needs-llvm-components: riscv +//@ add-minicore +//@ ignore-backends: gcc +#![feature(no_core)] +#![no_core] + +extern crate minicore; +use minicore::*; + +#[target_feature(enable = "v")] +//~^ERROR: the target feature `v` is currently unstable +#[target_feature(enable = "f")] +//~^ERROR: the target feature `f` is allowed in cfg but unstable otherwise +pub unsafe fn my_fun() {} diff --git a/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.stderr b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.stderr new file mode 100644 index 0000000000000..7f13c11798fcf --- /dev/null +++ b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-attribute-riscv.stderr @@ -0,0 +1,23 @@ +error[E0658]: the target feature `v` is currently unstable + --> $DIR/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs:13:18 + | +LL | #[target_feature(enable = "v")] + | ^^^^^^^^^^^^ + | + = note: see issue #150257 for more information + = help: add `#![feature(riscv_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: the target feature `f` is allowed in cfg but unstable otherwise + --> $DIR/cfg-stable-toggle-unstable-target-feature-attribute-riscv.rs:15:18 + | +LL | #[target_feature(enable = "f")] + | ^^^^^^^^^^^^ + | + = note: see issue #150257 for more information + = help: add `#![feature(riscv_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.rs b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.rs new file mode 100644 index 0000000000000..ab2b75ed5190f --- /dev/null +++ b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.rs @@ -0,0 +1,17 @@ +//! Ensure cfg-only stable target_features trigger warnings when enabled via compile flag. +//@ check-pass +//@ compile-flags: --crate-type=lib +//@ compile-flags: --target=riscv64gc-unknown-none-elf -Ctarget-feature=+v -Ctarget-feature=+f +// FIXME(#147881): *disable* the feature again for minicore as otherwise that will fail to build. +//@ minicore-compile-flags: -Ctarget-feature=-v -Ctarget-feature=-f +//@ needs-llvm-components: riscv +//@ ignore-backends: gcc +//@ add-minicore +#![feature(no_core)] +#![no_core] + +extern crate minicore; +use minicore::*; + +//~? WARN unstable feature specified for `-Ctarget-feature` +//~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.stderr b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.stderr new file mode 100644 index 0000000000000..b0167221aabaa --- /dev/null +++ b/tests/ui/target-feature/cfg-stable-toggle-unstable-target-feature-flag-enable-riscv.stderr @@ -0,0 +1,10 @@ +warning: unstable feature specified for `-Ctarget-feature`: `v` + | + = note: this feature is not stably supported; its behavior can change in the future + +warning: unstable feature specified for `-Ctarget-feature`: `f` + | + = note: this feature is allowed in cfg but unstable otherwise; its behavior can change in the future + +warning: 2 warnings emitted + From bfa646d8dfe0401ad095b71389cda1f5072527f0 Mon Sep 17 00:00:00 2001 From: Filiprogrammer <44641787+Filiprogrammer@users.noreply.github.com> Date: Thu, 28 May 2026 19:47:21 +0200 Subject: [PATCH 05/33] Document equivalence of `highest_one` and `ilog2` methods on integers Add notes to the primitive integer and `NonZero` types clarifying the equivalence between `highest_one` and the `ilog2`/`checked_ilog2` methods for non-negative values. --- library/core/src/num/int_macros.rs | 6 ++++++ library/core/src/num/nonzero.rs | 12 ++++++++++++ library/core/src/num/uint_macros.rs | 4 ++++ 3 files changed, 22 insertions(+) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 4e7be6f065c9b..2cb71b2ade080 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -210,6 +210,9 @@ macro_rules! int_impl { /// Returns the index of the highest bit set to one in `self`, or `None` /// if `self` is `0`. /// + /// Note that for non-negative numbers, this is equivalent to + /// [`checked_ilog2`](Self::checked_ilog2). + /// /// # Examples /// /// ``` @@ -3575,6 +3578,9 @@ macro_rules! int_impl { /// /// Returns `None` if the number is negative or zero. /// + /// Note that for non-negative numbers, this is equivalent to + /// [`highest_one`](Self::highest_one). + /// /// # Examples /// /// ``` diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 59c37a7ce9633..8c47c3e475431 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -708,6 +708,16 @@ macro_rules! nonzero_integer { /// Returns the index of the highest bit set to one in `self`. /// + #[doc = sign_dependent_expr!{ + $signedness ? + if signed { + "" + } + if unsigned { + "Note that this is equivalent to [`ilog2`](Self::ilog2)." + } + }] + /// /// # Examples /// /// ``` @@ -1774,6 +1784,8 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// except that it has no failure cases to worry about /// since this value can never be zero. /// + /// Note that this is equivalent to [`highest_one`](Self::highest_one). + /// /// # Examples /// /// ``` diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 9bf765f1c4ed9..3ae81fc78ab05 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -289,6 +289,8 @@ macro_rules! uint_impl { /// Returns the index of the highest bit set to one in `self`, or `None` /// if `self` is `0`. /// + /// Note that this is equivalent to [`checked_ilog2`](Self::checked_ilog2). + /// /// # Examples /// /// ``` @@ -1865,6 +1867,8 @@ macro_rules! uint_impl { /// /// Returns `None` if the number is zero. /// + /// Note that this is equivalent to [`highest_one`](Self::highest_one). + /// /// # Examples /// /// ``` From f201880f89a79d61adfa619cb1d0f99b3ba802c2 Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Fri, 29 May 2026 23:43:48 +0100 Subject: [PATCH 06/33] ci: update download-artifact action to v8 --- .github/workflows/dependencies.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dependencies.yml b/.github/workflows/dependencies.yml index 4d2e2989e834a..9512e74601784 100644 --- a/.github/workflows/dependencies.yml +++ b/.github/workflows/dependencies.yml @@ -94,11 +94,11 @@ jobs: uses: actions/checkout@v5 - name: download Cargo.lock from update job - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: Cargo-lock - name: download cargo-update log from update job - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 with: name: cargo-updates From a4672636bbbd4aa871c0d8186bb1723bd01d887c Mon Sep 17 00:00:00 2001 From: xtqqczze <45661989+xtqqczze@users.noreply.github.com> Date: Sat, 30 May 2026 19:54:54 +0100 Subject: [PATCH 07/33] triagebot: Update messages to direct changes to appropriate repositories --- triagebot.toml | 55 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 8c9702c407ea1..bc354f950d532 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -942,11 +942,21 @@ Issue #{number} "{title}" has been added. # ------------------------------------------------------------------------------ [mentions."compiler/rustc_codegen_cranelift"] -message = "The Cranelift subtree was changed" +message = """ +`rustc_codegen_cranelift` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rustc_codegen_cranelift](https://github.com/rust-lang/rustc_codegen_cranelift) \ +instead. +""" cc = ["@bjorn3"] [mentions."compiler/rustc_codegen_gcc"] -message = "The GCC codegen subtree was changed" +message = """ +`rustc_codegen_gcc` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rustc_codegen_gcc](https://github.com/rust-lang/rustc_codegen_gcc) \ +instead. +""" cc = ["@antoyo", "@GuillaumeGomez"] [mentions."compiler/rustc_const_eval/src/"] @@ -1100,8 +1110,9 @@ cc = ["@tgross35"] [mentions."library/portable-simd"] message = """ -Portable SIMD is developed in its own repository. If possible, consider \ -making this change to [rust-lang/portable-simd](https://github.com/rust-lang/portable-simd) \ +`portable-simd` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/portable-simd](https://github.com/rust-lang/portable-simd) \ instead. """ cc = ["@calebzulawski", "@programmerjake"] @@ -1144,7 +1155,12 @@ cc = [ cc = ["@ehuss"] [mentions."src/tools/clippy"] -message = "The Clippy subtree was changed" +message = """ +`clippy` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rust-clippy](https://github.com/rust-lang/rust-clippy) \ +instead. +""" cc = ["@rust-lang/clippy"] [mentions."src/tools/compiletest"] @@ -1157,7 +1173,12 @@ new or modified directive in `src/doc/rustc-dev-guide/`. """ [mentions."src/tools/miri"] -message = "The Miri subtree was changed" +message = """ +`miri` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/miri](https://github.com/rust-lang/miri) \ +instead. +""" cc = ["@rust-lang/miri"] [mentions."src/tools/run-make-support"] @@ -1166,15 +1187,20 @@ cc = ["@jieyouxu"] [mentions."src/tools/rust-analyzer"] message = """ -rust-analyzer is developed in its own repository. If possible, consider making \ -this change to [rust-lang/rust-analyzer] instead. - -[rust-lang/rust-analyzer]: https://github.com/rust-lang/rust-analyzer +`rust-analyzer` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rust-analyzer](https://github.com/rust-lang/rust-analyzer) \ +instead. """ cc = ["@rust-lang/rust-analyzer"] [mentions."src/tools/rustfmt"] -message = "The Rustfmt subtree was changed" +message = """ +`rustfmt` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rustfmt](https://github.com/rust-lang/rustfmt) \ +instead. +""" cc = ["@rust-lang/rustfmt"] [mentions."compiler/rustc_middle/src/mir/syntax.rs"] @@ -1386,7 +1412,12 @@ https://github.com/rust-lang/reference/blob/HEAD/src/identifiers.md. cc = ["@ehuss"] [mentions."src/doc/rustc-dev-guide"] -message = "The rustc-dev-guide subtree was changed. If this PR *only* touches the dev guide consider submitting a PR directly to [rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide/pulls) otherwise thank you for updating the dev guide with your changes." +message = """ +`rustc-dev-guide` is developed in its own repository. If possible, consider \ +making this change to \ +[rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide) \ +instead. +""" cc = ["@BoxyUwU", "@tshepang"] [mentions."compiler/rustc_passes/src/check_attr.rs"] From 355b5011532d35913ed3e942969974cf1bfcad60 Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Wed, 3 Jun 2026 00:15:19 +0800 Subject: [PATCH 08/33] Document Repeat::last panic behavior --- library/core/src/iter/sources/repeat.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index f578ae86a9fce..197b5f2124235 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -101,6 +101,11 @@ impl Iterator for Repeat { Some(self.element.clone()) } + /// Consumes the iterator and panics. + /// + /// # Panics + /// + /// This method always panics because `Repeat` is infinite. #[track_caller] fn last(self) -> Option { panic!("iterator is infinite"); From d3ef6e370af65111a9fc37ed32bbb90d60d14049 Mon Sep 17 00:00:00 2001 From: JinRudy <28995387+JinRudy@users.noreply.github.com> Date: Wed, 3 Jun 2026 17:16:50 +0800 Subject: [PATCH 09/33] =?UTF-8?q?docs(core):=20=E6=BE=84=E6=B8=85=20MaybeU?= =?UTF-8?q?ninit=20zeroed=20padding=20=E8=AF=AD=E4=B9=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整 MaybeUninit::zeroed 文档中的 padding 字节说明 - 对齐 mem::zeroed 中不保证 padding 为零的表述 --- library/core/src/mem/maybe_uninit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 7e2c6b9b3bcb2..9889f32c502ad 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -437,7 +437,8 @@ impl MaybeUninit { /// be null. /// /// Note that if `T` has padding bytes, those bytes are *not* preserved when the - /// `MaybeUninit` value is returned from this function, so those bytes will *not* be zeroed. + /// `MaybeUninit` value is returned from this function, so those bytes are not + /// guaranteed to be zeroed. /// /// Note that dropping a `MaybeUninit` will never call `T`'s drop code. /// It is your responsibility to make sure `T` gets dropped if it got initialized. From d434e47b802880bc9f0bfae2e8927618afff4179 Mon Sep 17 00:00:00 2001 From: kulst Date: Wed, 3 Jun 2026 20:59:17 +0200 Subject: [PATCH 10/33] Silence llbc's output by default to prevent rustc's linker output warning Make the linker quiet by default and add linker command line arguments for explicit verbosity control: - no flag: no tracing output is emitted during successful links - `-v`: emit informational linker diagnostics - `-vv`: emit tracing-level linker diagnostics Also adjust the tracing formatter to produce linker-style output by disabling ANSI color sequences and omitting timestamps, tracing levels, and tracing targets. --- .../src/bin/llvm-bitcode-linker.rs | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs index 608c6605304f4..9116b38ed0796 100644 --- a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs +++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs @@ -1,7 +1,9 @@ use std::path::PathBuf; -use clap::Parser; +use anyhow::anyhow; +use clap::{ArgAction, Parser}; use llvm_bitcode_linker::{Optimization, Session, Target}; +use tracing::level_filters::LevelFilter; #[derive(Debug, Parser)] /// Linker for embedded code without any system dependencies @@ -46,13 +48,29 @@ pub struct Args { /// The optimization level #[arg(short = 'O', value_enum, default_value = "0")] optimization: Optimization, + + /// Increase linker diagnostic verbosity (-v = info, -vv = debug) + #[arg(short = 'v', long = "verbose", action = ArgAction::Count)] + verbose: u8, } fn main() -> anyhow::Result<()> { - tracing_subscriber::FmtSubscriber::builder().with_max_level(tracing::Level::DEBUG).init(); - let args = Args::parse(); + let max_tracing_level = match args.verbose { + 0 => LevelFilter::OFF, + 1 => LevelFilter::INFO, + _ => LevelFilter::TRACE, + }; + + tracing_subscriber::FmtSubscriber::builder() + .with_max_level(max_tracing_level) + .with_target(false) + .without_time() + .with_level(false) + .with_ansi(false) + .init(); + let mut linker = Session::new(args.target, args.target_cpu, args.target_feature, args.output); linker.add_exported_symbols(args.export_symbol); @@ -61,5 +79,11 @@ fn main() -> anyhow::Result<()> { linker.add_file(rlib); } - linker.lto(args.optimization, args.debug) + let hint = if max_tracing_level < LevelFilter::ERROR { + "Pass `-v` to llvm-bitcode-linker for additional diagnostic output." + } else { + "" + }; + + linker.lto(args.optimization, args.debug).map_err(|err| anyhow!("{err}\n{hint}")) } From 0a6eef901f72ede19b1c5ba8ca69b7a9679a5f47 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Thu, 4 Jun 2026 00:53:16 +0200 Subject: [PATCH 11/33] Implement feature `integer_casts` --- library/core/src/convert/mod.rs | 2 + library/core/src/convert/num.rs | 122 +++++++++++++++++++++ library/core/src/num/imp/overflow_panic.rs | 2 +- library/core/src/num/int_macros.rs | 117 ++++++++++++++++++++ library/core/src/num/mod.rs | 1 + library/core/src/num/uint_macros.rs | 114 +++++++++++++++++++ 6 files changed, 357 insertions(+), 1 deletion(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 34cf9c5d0a5b2..ae8458c199503 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -43,6 +43,8 @@ mod num; #[unstable(feature = "convert_float_to_int", issue = "67057")] pub use num::FloatToInt; +#[unstable(feature = "integer_casts", issue = "157388")] +pub use num::{BoundedCastFromInt, CheckedCastFromInt}; /// The identity function. /// diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 7179512e126ed..9f6b6453cea94 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -1,5 +1,32 @@ use crate::num::{IntErrorKind, TryFromIntError}; +mod private { + /// This trait being unreachable from outside the crate prevents other + /// implementations of the integer cast traits. + #[unstable(feature = "integer_casts", issue = "157388")] + pub trait Sealed {} + + /// This trait being unreachable from outside the crate prevents other + /// implementations of the integer cast traits. + /// + /// `Cast : SealedCast` avoids the orphan rule, which would otherwise + /// allow e.g. implementing `Cast` for `u8`. + #[unstable(feature = "integer_casts", issue = "157388")] + pub trait SealedCast: Sealed {} + + #[unstable(feature = "integer_casts", issue = "157388")] + impl SealedCast for U {} + + macro_rules! impl_sealed_int { + ([$($T:ty),*]) => {$( + #[unstable(feature = "integer_casts", issue = "157388")] + impl Sealed for $T { } + )*}; + } + + impl_sealed_int!([u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); +} + /// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`. /// Typically doesn’t need to be used directly. #[unstable(feature = "convert_float_to_int", issue = "67057")] @@ -630,3 +657,98 @@ impl_nonzero_int_try_from_nonzero_int!(i32 => u8, u16, u32, u64, u128, usize); impl_nonzero_int_try_from_nonzero_int!(i64 => u8, u16, u32, u64, u128, usize); impl_nonzero_int_try_from_nonzero_int!(i128 => u8, u16, u32, u64, u128, usize); impl_nonzero_int_try_from_nonzero_int!(isize => u8, u16, u32, u64, u128, usize); + +/// Conversion between integers, wrapping around or saturating at the target type's boundaries. +#[unstable(feature = "integer_casts", issue = "157388")] +#[rustc_const_unstable(feature = "integer_casts", issue = "157388")] +pub const trait BoundedCastFromInt: private::SealedCast + Sized { + /// Converts `value` to this type, wrapping around at the boundary of the type. + #[unstable(feature = "integer_casts", issue = "157388")] + fn wrapping_cast_from(value: T) -> Self; + + /// Converts `value` to this type, saturating at the numeric bounds instead of overflowing. + #[unstable(feature = "integer_casts", issue = "157388")] + fn saturating_cast_from(value: T) -> Self; +} + +/// Fallible conversion between integers. +#[unstable(feature = "integer_casts", issue = "157388")] +#[rustc_const_unstable(feature = "integer_casts", issue = "157388")] +pub const trait CheckedCastFromInt: private::SealedCast + Sized { + /// Converts `value` to this type, returning `None` if overflow would have occurred. + #[unstable(feature = "integer_casts", issue = "157388")] + fn checked_cast_from(value: T) -> Option; + + /// Converts `value` to this type, assuming overflow cannot occur. + /// + /// # Safety + /// + /// This results in undefined behavior when `value` will overflow when + /// converted to this type. + #[unstable(feature = "integer_casts", issue = "157388")] + unsafe fn unchecked_cast_from(value: T) -> Self; + + /// Converts `value` to this type, panicking on overflow. + /// + /// # Panics + /// + /// This function will always panic on overflow, regardless of whether overflow checks are enabled. + #[unstable(feature = "integer_casts", issue = "157388")] + fn strict_cast_from(value: T) -> Self; +} + +macro_rules! impl_int_cast { + ($Src:ty as [$($Dst:ty),*]) => {$( + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + impl const CheckedCastFromInt<$Src> for $Dst { + #[inline] + fn checked_cast_from(value: $Src) -> Option { + value.try_into().ok() + } + + #[inline(always)] + unsafe fn unchecked_cast_from(value: $Src) -> Self { + // SAFETY: the safety contract must be upheld by the caller. + unsafe { value.try_into().unwrap_unchecked() } + } + + #[inline] + #[track_caller] + fn strict_cast_from(value: $Src) -> Self { + match value.try_into() { + Ok(x) => x, + Err(_) => core::num::imp::overflow_panic::cast_integer() + } + } + } + + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + impl const BoundedCastFromInt<$Src> for $Dst { + #[inline(always)] + fn wrapping_cast_from(value: $Src) -> Self { + value as Self + } + + #[inline] + #[allow(unused_comparisons)] + #[allow(irrefutable_let_patterns)] + fn saturating_cast_from(value: $Src) -> Self { + if let Ok(x) = value.try_into() { + return x; + } + + if value < 0 { <$Dst>::MIN } else { <$Dst>::MAX } + } + } + )*}; +} + +macro_rules! impl_all_int_casts { + ([$($Src:ty),*]) => {$( + impl_int_cast!($Src as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); + )*}; +} + +impl_all_int_casts!([u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); diff --git a/library/core/src/num/imp/overflow_panic.rs b/library/core/src/num/imp/overflow_panic.rs index 2b699fa61f871..ec5624f91fa28 100644 --- a/library/core/src/num/imp/overflow_panic.rs +++ b/library/core/src/num/imp/overflow_panic.rs @@ -52,6 +52,6 @@ pub(in crate::num) const fn shl() -> ! { #[cold] #[track_caller] -pub(in crate::num) const fn cast_integer() -> ! { +pub(crate) const fn cast_integer() -> ! { panic!("attempt to cast integer with overflow") } diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 01b846548547f..97f51f923f410 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -4068,5 +4068,122 @@ macro_rules! int_impl { { traits::WidenTarget::internal_widen(self) } + + + /// Converts `self` to the target integer type, saturating at the numeric + /// bounds instead of overflowing. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(i8::MAX, ", stringify!($SelfT), "::MAX.saturating_cast());")] + #[doc = concat!("assert_eq!(i8::MIN, ", stringify!($SelfT), "::MIN.saturating_cast());")] + #[doc = concat!("assert_eq!(42u8, 42", stringify!($SelfT), ".saturating_cast());")] + #[doc = concat!("assert_eq!(0u8, (-42", stringify!($SelfT), ").saturating_cast());")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn saturating_cast>(self) -> T { + T::saturating_cast_from(self) + } + + /// Converts `self` to the target integer type, wrapping around at the + /// boundary of the target type. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX as i8, ", stringify!($SelfT), "::MAX.wrapping_cast());")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN as i8, ", stringify!($SelfT), "::MIN.wrapping_cast());")] + #[doc = concat!("assert_eq!(42u8, 42", stringify!($SelfT), ".wrapping_cast());")] + #[doc = concat!("assert_eq!(u8::MAX - 41, (-42", stringify!($SelfT), ").wrapping_cast());")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn wrapping_cast>(self) -> T { + T::wrapping_cast_from(self) + } + + /// Converts `self` to the target integer type, returning `None` if the value + /// does not lie in the target type's domain. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(Some(42u8), 42", stringify!($SelfT), ".checked_cast());")] + #[doc = concat!("assert_eq!((-42", stringify!($SelfT), ").checked_cast::(), None);")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn checked_cast>(self) -> Option { + T::checked_cast_from(self) + } + + /// Converts `self` to the target integer type, panicking if the value + /// does not lie in the target type's domain. + /// + /// # Panics + /// + /// This function will panic if the value does not lie in the target type's domain. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(42u8, 42", stringify!($SelfT), ".strict_cast());")] + /// ``` + /// + /// The following will panic: + /// + /// ```should_panic + /// #![feature(integer_casts)] + #[doc = concat!("let _ = (-42", stringify!($SelfT), ").strict_cast::();")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + #[track_caller] + pub const fn strict_cast>(self) -> T { + T::strict_cast_from(self) + } + + /// Converts `self` to the target integer type, assuming the value lies in the target type's domain. + /// + /// # Safety + /// + /// This results in undefined behavior if the integer value of `self` is bigger than `T::MAX`, + /// or smaller than `T::MIN`, where `T` is the target type. + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const unsafe fn unchecked_cast>(self) -> T { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_cast must fit in the target type"), + ( + // Check has to be performed up-front because it depends on generic T. + in_bounds: bool = { + let cast_val = self.checked_cast::(); + let ret = cast_val.is_some(); + core::mem::forget(cast_val); // We don't have const Drop, but we know it's an int. + ret + }, + ) => in_bounds, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { T::unchecked_cast_from(self) } + } } } diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index ed91c1e6a4ff1..59c2b11470f4a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -2,6 +2,7 @@ #![stable(feature = "rust1", since = "1.0.0")] +use crate::convert::{BoundedCastFromInt, CheckedCastFromInt}; use crate::panic::const_panic; use crate::str::FromStr; use crate::ub_checks::assert_unsafe_precondition; diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 3170143da9b30..a4d2045a91d2e 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -4229,5 +4229,119 @@ macro_rules! uint_impl { { traits::WidenTarget::internal_widen(self) } + + /// Converts `self` to the target integer type, saturating at the numeric + /// bounds instead of overflowing. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(255u8, ", stringify!($SelfT), "::MAX.saturating_cast());")] + #[doc = concat!("assert_eq!(127i8, ", stringify!($SelfT), "::MAX.saturating_cast());")] + #[doc = concat!("assert_eq!(42i8, 42", stringify!($SelfT), ".saturating_cast());")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn saturating_cast>(self) -> T { + T::saturating_cast_from(self) + } + + /// Converts `self` to the target integer type, wrapping around at the + /// boundary of the target type. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(255u8, ", stringify!($SelfT), "::MAX.wrapping_cast());")] + #[doc = concat!("assert_eq!(42i8, 42", stringify!($SelfT), ".wrapping_cast());")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX as i8, ", stringify!($SelfT), "::MAX.wrapping_cast());")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn wrapping_cast>(self) -> T { + T::wrapping_cast_from(self) + } + + /// Converts `self` to the target integer type, returning `None` if the value + /// does not lie in the target type's domain. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(Some(42u8), 42", stringify!($SelfT), ".checked_cast());")] + #[doc = concat!("assert_eq!(128", stringify!($SelfT), ".checked_cast::(), None);")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const fn checked_cast>(self) -> Option { + T::checked_cast_from(self) + } + + /// Converts `self` to the target integer type, panicking if the value + /// does not lie in the target type's domain. + /// + /// # Panics + /// + /// This function will panic if the value does not lie in the target type's domain. + /// + /// # Examples + /// + /// ``` + /// #![feature(integer_casts)] + #[doc = concat!("assert_eq!(42u8, 42", stringify!($SelfT), ".strict_cast());")] + /// ``` + /// + /// The following will panic: + /// + /// ```should_panic + /// #![feature(integer_casts)] + #[doc = concat!("let _ = 128", stringify!($SelfT), ".strict_cast::();")] + /// ``` + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + #[track_caller] + pub const fn strict_cast>(self) -> T { + T::strict_cast_from(self) + } + + /// Converts `self` to the target integer type, assuming the value lies in the target type's domain. + /// + /// # Safety + /// + /// This results in undefined behavior if the integer value of `self` is bigger than `T::MAX`, + /// or smaller than `T::MIN`, where `T` is the target type. + #[must_use = "this returns the cast result and does not modify the original"] + #[unstable(feature = "integer_casts", issue = "157388")] + #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] + #[inline(always)] + pub const unsafe fn unchecked_cast>(self) -> T { + assert_unsafe_precondition!( + check_language_ub, + concat!(stringify!($SelfT), "::unchecked_cast must fit in the target type"), + ( + // Check has to be performed up-front because it depends on generic T. + in_bounds: bool = { + let cast_val = self.checked_cast::(); + let ret = cast_val.is_some(); + core::mem::forget(cast_val); // We don't have const Drop, but we know it's an int. + ret + }, + ) => in_bounds, + ); + + // SAFETY: this is guaranteed to be safe by the caller. + unsafe { T::unchecked_cast_from(self) } + } } } From 73e5b1d1b881cac24dfbb4dcd81d5cf3ac7d7ba7 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Fri, 5 Jun 2026 10:00:22 -0700 Subject: [PATCH 12/33] Improve documentation of `align_of` and `Alignment`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * The documentation for `align_of_val()` and `Alignment::of_val()` did not explain its use in interacting with `dyn` types, and even contained the false statement that “Every reference to a value of the type `T` must be a multiple of this number”. This change removes that statement from everything except `align_of()`, and adds a mention of, and example code for, getting the alignment of a `dyn` value. * The documentation for `align_of_val_raw()` did not explain how it relates to other functions in the family. Now it does. * Added a caveat that the alignment of `i32` is not always 4, despite the examples asserting this. --- library/core/src/mem/alignment.rs | 36 ++++++++++++++++++++++++++-- library/core/src/mem/mod.rs | 40 +++++++++++++++++++++++++++---- 2 files changed, 69 insertions(+), 7 deletions(-) diff --git a/library/core/src/mem/alignment.rs b/library/core/src/mem/alignment.rs index 08ce7fcd55523..8f453685a6f92 100644 --- a/library/core/src/mem/alignment.rs +++ b/library/core/src/mem/alignment.rs @@ -58,7 +58,13 @@ impl Alignment { /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. /// - /// Every reference to a value of the type `T` must be a multiple of this number. + /// This function is identical to [`Alignment::of::()`][Self::of] whenever + /// T: [Sized], + /// but also supports determining the alignment required by a `dyn Trait` value, which is the + /// alignment of the underlying concrete type. + /// + /// This provides the same numerical value as [`align_of_val`], + /// but in an `Alignment` instead of a `usize`. /// /// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface /// @@ -70,6 +76,25 @@ impl Alignment { /// /// assert_eq!(Alignment::of_val(&5i32).as_usize(), 4); /// ``` + /// + /// (Caution: [it is not guaranteed][type-layout] that the alignment of `i32` is `4`; + /// that is, the above assertion does not pass on all platforms.) + /// + /// `dyn` types may have different alignments for different values; + /// `Alignment::of_val()` can be used to learn those alignments: + /// + /// ``` + /// #![feature(ptr_alignment_type)] + /// use std::mem::Alignment; + /// + /// let a: &dyn ToString = &1234u16; + /// let b: &dyn ToString = &String::from("abcd"); + /// + /// assert_eq!(Alignment::of_val(a), Alignment::of::()); + /// assert_eq!(Alignment::of_val(b), Alignment::of::()); + /// ``` + /// + /// [type-layout]: ../../reference/type-layout.html#r-layout.primitive #[inline] #[must_use] #[unstable(feature = "ptr_alignment_type", issue = "102070")] @@ -81,7 +106,9 @@ impl Alignment { /// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to. /// - /// Every reference to a value of the type `T` must be a multiple of this number. + /// This function is identical to [`Alignment::of_val()`], except that it can be used with raw + /// pointers in situations where it would be unsound or undesirable to convert them to + /// [`&` references][primitive@reference] and impose the aliasing rules that come with that. /// /// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface /// @@ -117,6 +144,11 @@ impl Alignment { /// /// assert_eq!(unsafe { Alignment::of_val_raw(&5i32) }.as_usize(), 4); /// ``` + /// + /// (Caution: [it is not guaranteed][type-layout] that the alignment of `i32` is `4`; + /// that is, the above assertion does not pass on all platforms.) + /// + /// [type-layout]: ../../reference/type-layout.html#r-layout.primitive #[inline] #[must_use] #[unstable(feature = "ptr_alignment_type", issue = "102070")] diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 62c612e7ba2a6..9a54cfad40b1a 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -506,7 +506,7 @@ pub fn min_align_of_val(val: &T) -> usize { unsafe { intrinsics::align_of_val(val) } } -/// Returns the [ABI]-required minimum alignment of a type in bytes. +/// Returns the [ABI]-required minimum alignment of a type, in bytes. /// /// Every reference to a value of the type `T` must be a multiple of this number. /// @@ -519,6 +519,11 @@ pub fn min_align_of_val(val: &T) -> usize { /// ``` /// assert_eq!(4, align_of::()); /// ``` +/// +/// (Caution: [it is not guaranteed][type-layout] that the alignment of `i32` is `4`; +/// that is, the above assertion does not pass on all platforms.) +/// +/// [type-layout]: ../../reference/type-layout.html#r-layout.primitive #[inline(always)] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -529,10 +534,12 @@ pub const fn align_of() -> usize { ::ALIGN } -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to, in /// bytes. /// -/// Every reference to a value of the type `T` must be a multiple of this number. +/// This function is identical to [`align_of::()`][align_of] whenever T: [Sized], +/// but also supports determining the alignment required by a `dyn Trait` value, which is the +/// alignment of the underlying concrete type. /// /// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface /// @@ -541,6 +548,22 @@ pub const fn align_of() -> usize { /// ``` /// assert_eq!(4, align_of_val(&5i32)); /// ``` +/// +/// (Caution: [it is not guaranteed][type-layout] that the alignment of `i32` is `4`; +/// that is, this example assertion does not pass on all platforms.) +/// +/// `dyn` types may have different alignments for different values; +/// `align_of_val` can be used to learn those alignments: +/// +/// ``` +/// let a: &dyn ToString = &1234u16; +/// let b: &dyn ToString = &String::from("abcd"); +/// +/// assert_eq!(align_of_val(a), align_of::()); +/// assert_eq!(align_of_val(b), align_of::()); +/// ``` +/// +/// [type-layout]: ../../reference/type-layout.html#r-layout.primitive #[inline] #[must_use] #[stable(feature = "rust1", since = "1.0.0")] @@ -550,10 +573,12 @@ pub const fn align_of_val(val: &T) -> usize { unsafe { intrinsics::align_of_val(val) } } -/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to in +/// Returns the [ABI]-required minimum alignment of the type of the value that `val` points to, in /// bytes. /// -/// Every reference to a value of the type `T` must be a multiple of this number. +/// This function is identical to [`align_of_val()`], except that it can be used with raw pointers +/// in situations where it would be unsound or undesirable to convert them to +/// [`&` references][primitive@reference] and impose the aliasing rules that come with that. /// /// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface /// @@ -589,6 +614,11 @@ pub const fn align_of_val(val: &T) -> usize { /// /// assert_eq!(4, unsafe { mem::align_of_val_raw(&5i32) }); /// ``` +/// +/// (Caution: [it is not guaranteed][type-layout] that the alignment of `i32` is `4`; +/// that is, the above assertion does not pass on all platforms.) +/// +/// [type-layout]: ../../reference/type-layout.html#r-layout.primitive #[inline] #[must_use] #[unstable(feature = "layout_for_ptr", issue = "69835")] From 17ebb8f376e65c52bee1417988cea33948d66935 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Tue, 19 May 2026 12:39:35 +0100 Subject: [PATCH 13/33] move cross crate tests out of ui/issues --- .../auxiliary/const-fn-evaluated-cross-crate.rs} | 0 .../auxiliary/construct-extern-struct-with-destructor.rs} | 0 .../auxiliary/cross-crate-static-reference-and-field-access.rs} | 0 .../auxiliary/cross-crate-trait-inheritance-on-default-method.rs} | 0 .../auxiliary/cross-crate-type-alias-with-nested-destructors.rs} | 0 .../default-trait-method-reachable-through-trait-object.rs} | 0 .../auxiliary/extern-crate-and-impl-inside-method-body.rs} | 0 .../auxiliary/extern-generic-tuple-struct-construction.rs} | 0 .../auxiliary/extern-repr-enum-with-discriminant-cast.rs} | 0 .../auxiliary/extern-trait-bound-with-array-associated-type.rs} | 0 .../auxiliary/fn-declared-inside-closure-body-cross-crate.rs} | 0 .../auxiliary/fn-local-impl-returned-as-trait-object.rs} | 0 .../auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs} | 0 .../auxiliary/graceful-error-for-mistyped-assoc-const.rs} | 0 .../auxiliary/impl-extern-trait-with-associated-type.rs} | 0 .../auxiliary/imported-struct-not-confused-with-variant.rs} | 0 .../auxiliary/link-extern-crate-with-drop-type.rs} | 0 .../auxiliary/macro-generated-module-path-resolution.rs} | 0 .../auxiliary/method-call-on-extern-fn-return-value.rs} | 0 .../auxiliary/monomorphize-index-op-cross-crate.rs} | 0 .../auxiliary/mut-ref-write-visible-after-unwind.rs} | 0 .../auxiliary/nested-struct-in-polymorphic-impl-method.rs} | 0 .../no-duplicate-symbols-with-codegen-units-cgu-test-a.rs} | 0 .../no-duplicate-symbols-with-codegen-units-cgu-test-b.rs} | 0 .../no-duplicate-symbols-with-codegen-units-cgu-test.rs} | 0 .../auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs} | 0 .../auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs} | 0 .../auxiliary/stable-hash-for-trait-object-type.rs} | 0 .../trait-object-projection-bounds-with-interning-order.rs} | 0 .../auxiliary/transitive-crate-dependency-with-trait-impl-a.rs} | 0 .../auxiliary/transitive-crate-dependency-with-trait-impl-b.rs} | 0 .../type-default-applied-in-cross-crate-method-lookup.rs} | 0 .../const-fn-evaluated-cross-crate.rs} | 0 .../construct-extern-struct-with-destructor.rs} | 0 .../cross-crate-static-reference-and-field-access.rs} | 0 .../cross-crate-trait-inheritance-on-default-method.rs} | 0 .../cross-crate-type-alias-with-nested-destructors.rs} | 0 .../default-trait-method-reachable-through-trait-object.rs} | 0 .../extern-crate-and-impl-inside-method-body.rs} | 0 .../extern-generic-tuple-struct-construction.rs} | 0 .../extern-repr-enum-with-discriminant-cast.rs} | 0 .../extern-trait-bound-with-array-associated-type.rs} | 0 .../fn-declared-inside-closure-body-cross-crate.rs} | 0 .../fn-local-impl-returned-as-trait-object.rs} | 0 .../generic-fn-with-supertrait-bound-cross-crate.rs} | 0 .../graceful-error-for-mistyped-assoc-const.rs} | 0 .../graceful-error-for-mistyped-assoc-const.stderr} | 0 .../impl-extern-trait-with-associated-type.rs} | 0 .../imported-struct-not-confused-with-variant.rs} | 0 .../link-extern-crate-with-drop-type.rs} | 0 .../macro-generated-module-path-resolution.rs} | 0 .../method-call-on-extern-fn-return-value.rs} | 0 .../monomorphize-index-op-cross-crate.rs} | 0 .../mut-ref-write-visible-after-unwind.rs} | 0 .../nested-struct-in-polymorphic-impl-method.rs} | 0 .../no-duplicate-symbols-with-codegen-units.rs} | 0 .../optimized-closure-with-debug-info-cross-crate.rs} | 0 .../stable-hash-for-trait-object-type.rs} | 0 .../trait-object-projection-bounds-with-interning-order.rs} | 0 .../transitive-crate-dependency-with-trait-impl.rs} | 0 .../type-default-applied-in-cross-crate-method-lookup.rs} | 0 .../type-default-applied-in-cross-crate-method-lookup.stderr} | 0 62 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/auxiliary/issue-36954.rs => cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs} (100%) rename tests/ui/{issues/auxiliary/issue-3012-1.rs => cross-crate/auxiliary/construct-extern-struct-with-destructor.rs} (100%) rename tests/ui/{issues/auxiliary/issue-29265.rs => cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs} (100%) rename tests/ui/{issues/auxiliary/issue-3979-traits.rs => cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2526.rs => cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs} (100%) rename tests/ui/{issues/auxiliary/issue-38226-aux.rs => cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs} (100%) rename tests/ui/{issues/auxiliary/issue-41053.rs => cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs} (100%) rename tests/ui/{issues/auxiliary/issue-4545.rs => cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs} (100%) rename tests/ui/{issues/auxiliary/issue-42007-s.rs => cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs} (100%) rename tests/ui/{issues/auxiliary/issue-48984-aux.rs => cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2723-a.rs => cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2380.rs => cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs} (100%) rename tests/ui/{issues/auxiliary/issue-4208-cc.rs => cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs} (100%) rename tests/ui/{issues/auxiliary/issue-41549.rs => cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs} (100%) rename tests/ui/{issues/auxiliary/issue-20389.rs => cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs} (100%) rename tests/ui/{issues/auxiliary/issue-19293.rs => cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2170-lib.rs => cross-crate/auxiliary/link-extern-crate-with-drop-type.rs} (100%) rename tests/ui/{issues/auxiliary/issue-38190.rs => cross-crate/auxiliary/macro-generated-module-path-resolution.rs} (100%) rename tests/ui/{issues/auxiliary/issue-51798.rs => cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2631-a.rs => cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs} (100%) rename tests/ui/{issues/auxiliary/issue-29485.rs => cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs} (100%) rename tests/ui/{issues/auxiliary/issue-3136-a.rs => cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs} (100%) rename tests/ui/{issues/auxiliary/cgu_test_a.rs => cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs} (100%) rename tests/ui/{issues/auxiliary/cgu_test_b.rs => cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs} (100%) rename tests/ui/{issues/auxiliary/cgu_test.rs => cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs} (100%) rename tests/ui/{issues/auxiliary/issue-31702-1.rs => cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs} (100%) rename tests/ui/{issues/auxiliary/issue-31702-2.rs => cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs} (100%) rename tests/ui/{issues/auxiliary/issue-34796-aux.rs => cross-crate/auxiliary/stable-hash-for-trait-object-type.rs} (100%) rename tests/ui/{issues/auxiliary/issue-25467.rs => cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2414-a.rs => cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs} (100%) rename tests/ui/{issues/auxiliary/issue-2414-b.rs => cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs} (100%) rename tests/ui/{issues/auxiliary/issue-30123-aux.rs => cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs} (100%) rename tests/ui/{issues/issue-36954.rs => cross-crate/const-fn-evaluated-cross-crate.rs} (100%) rename tests/ui/{issues/issue-3012-2.rs => cross-crate/construct-extern-struct-with-destructor.rs} (100%) rename tests/ui/{issues/issue-29265.rs => cross-crate/cross-crate-static-reference-and-field-access.rs} (100%) rename tests/ui/{issues/issue-3979-xcrate.rs => cross-crate/cross-crate-trait-inheritance-on-default-method.rs} (100%) rename tests/ui/{issues/issue-2526-a.rs => cross-crate/cross-crate-type-alias-with-nested-destructors.rs} (100%) rename tests/ui/{issues/issue-38226.rs => cross-crate/default-trait-method-reachable-through-trait-object.rs} (100%) rename tests/ui/{issues/issue-41053.rs => cross-crate/extern-crate-and-impl-inside-method-body.rs} (100%) rename tests/ui/{issues/issue-4545.rs => cross-crate/extern-generic-tuple-struct-construction.rs} (100%) rename tests/ui/{issues/issue-42007.rs => cross-crate/extern-repr-enum-with-discriminant-cast.rs} (100%) rename tests/ui/{issues/issue-48984.rs => cross-crate/extern-trait-bound-with-array-associated-type.rs} (100%) rename tests/ui/{issues/issue-2723-b.rs => cross-crate/fn-declared-inside-closure-body-cross-crate.rs} (100%) rename tests/ui/{issues/issue-2380-b.rs => cross-crate/fn-local-impl-returned-as-trait-object.rs} (100%) rename tests/ui/{issues/issue-4208.rs => cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs} (100%) rename tests/ui/{issues/issue-41549.rs => cross-crate/graceful-error-for-mistyped-assoc-const.rs} (100%) rename tests/ui/{issues/issue-41549.stderr => cross-crate/graceful-error-for-mistyped-assoc-const.stderr} (100%) rename tests/ui/{issues/issue-20389.rs => cross-crate/impl-extern-trait-with-associated-type.rs} (100%) rename tests/ui/{issues/issue-19293.rs => cross-crate/imported-struct-not-confused-with-variant.rs} (100%) rename tests/ui/{issues/issue-2170-exe.rs => cross-crate/link-extern-crate-with-drop-type.rs} (100%) rename tests/ui/{issues/issue-38190.rs => cross-crate/macro-generated-module-path-resolution.rs} (100%) rename tests/ui/{issues/issue-51798.rs => cross-crate/method-call-on-extern-fn-return-value.rs} (100%) rename tests/ui/{issues/issue-2631-b.rs => cross-crate/monomorphize-index-op-cross-crate.rs} (100%) rename tests/ui/{issues/issue-29485.rs => cross-crate/mut-ref-write-visible-after-unwind.rs} (100%) rename tests/ui/{issues/issue-3136-b.rs => cross-crate/nested-struct-in-polymorphic-impl-method.rs} (100%) rename tests/ui/{issues/issue-32518.rs => cross-crate/no-duplicate-symbols-with-codegen-units.rs} (100%) rename tests/ui/{issues/issue-31702.rs => cross-crate/optimized-closure-with-debug-info-cross-crate.rs} (100%) rename tests/ui/{issues/issue-34796.rs => cross-crate/stable-hash-for-trait-object-type.rs} (100%) rename tests/ui/{issues/issue-25467.rs => cross-crate/trait-object-projection-bounds-with-interning-order.rs} (100%) rename tests/ui/{issues/issue-2414-c.rs => cross-crate/transitive-crate-dependency-with-trait-impl.rs} (100%) rename tests/ui/{issues/issue-30123.rs => cross-crate/type-default-applied-in-cross-crate-method-lookup.rs} (100%) rename tests/ui/{issues/issue-30123.stderr => cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr} (100%) diff --git a/tests/ui/issues/auxiliary/issue-36954.rs b/tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-36954.rs rename to tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs diff --git a/tests/ui/issues/auxiliary/issue-3012-1.rs b/tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-3012-1.rs rename to tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs diff --git a/tests/ui/issues/auxiliary/issue-29265.rs b/tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-29265.rs rename to tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs diff --git a/tests/ui/issues/auxiliary/issue-3979-traits.rs b/tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-3979-traits.rs rename to tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs diff --git a/tests/ui/issues/auxiliary/issue-2526.rs b/tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2526.rs rename to tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs diff --git a/tests/ui/issues/auxiliary/issue-38226-aux.rs b/tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-38226-aux.rs rename to tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs diff --git a/tests/ui/issues/auxiliary/issue-41053.rs b/tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-41053.rs rename to tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs diff --git a/tests/ui/issues/auxiliary/issue-4545.rs b/tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-4545.rs rename to tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs diff --git a/tests/ui/issues/auxiliary/issue-42007-s.rs b/tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-42007-s.rs rename to tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs diff --git a/tests/ui/issues/auxiliary/issue-48984-aux.rs b/tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-48984-aux.rs rename to tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs diff --git a/tests/ui/issues/auxiliary/issue-2723-a.rs b/tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2723-a.rs rename to tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs diff --git a/tests/ui/issues/auxiliary/issue-2380.rs b/tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2380.rs rename to tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs diff --git a/tests/ui/issues/auxiliary/issue-4208-cc.rs b/tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-4208-cc.rs rename to tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs diff --git a/tests/ui/issues/auxiliary/issue-41549.rs b/tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-41549.rs rename to tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs diff --git a/tests/ui/issues/auxiliary/issue-20389.rs b/tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-20389.rs rename to tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs diff --git a/tests/ui/issues/auxiliary/issue-19293.rs b/tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-19293.rs rename to tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs diff --git a/tests/ui/issues/auxiliary/issue-2170-lib.rs b/tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2170-lib.rs rename to tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs diff --git a/tests/ui/issues/auxiliary/issue-38190.rs b/tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-38190.rs rename to tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs diff --git a/tests/ui/issues/auxiliary/issue-51798.rs b/tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-51798.rs rename to tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs diff --git a/tests/ui/issues/auxiliary/issue-2631-a.rs b/tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2631-a.rs rename to tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs diff --git a/tests/ui/issues/auxiliary/issue-29485.rs b/tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-29485.rs rename to tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs diff --git a/tests/ui/issues/auxiliary/issue-3136-a.rs b/tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-3136-a.rs rename to tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs diff --git a/tests/ui/issues/auxiliary/cgu_test_a.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs similarity index 100% rename from tests/ui/issues/auxiliary/cgu_test_a.rs rename to tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs diff --git a/tests/ui/issues/auxiliary/cgu_test_b.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs similarity index 100% rename from tests/ui/issues/auxiliary/cgu_test_b.rs rename to tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs diff --git a/tests/ui/issues/auxiliary/cgu_test.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs similarity index 100% rename from tests/ui/issues/auxiliary/cgu_test.rs rename to tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs diff --git a/tests/ui/issues/auxiliary/issue-31702-1.rs b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-31702-1.rs rename to tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs diff --git a/tests/ui/issues/auxiliary/issue-31702-2.rs b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-31702-2.rs rename to tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs diff --git a/tests/ui/issues/auxiliary/issue-34796-aux.rs b/tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-34796-aux.rs rename to tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs diff --git a/tests/ui/issues/auxiliary/issue-25467.rs b/tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-25467.rs rename to tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs diff --git a/tests/ui/issues/auxiliary/issue-2414-a.rs b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2414-a.rs rename to tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs diff --git a/tests/ui/issues/auxiliary/issue-2414-b.rs b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-2414-b.rs rename to tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs diff --git a/tests/ui/issues/auxiliary/issue-30123-aux.rs b/tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs similarity index 100% rename from tests/ui/issues/auxiliary/issue-30123-aux.rs rename to tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs diff --git a/tests/ui/issues/issue-36954.rs b/tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs similarity index 100% rename from tests/ui/issues/issue-36954.rs rename to tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs diff --git a/tests/ui/issues/issue-3012-2.rs b/tests/ui/cross-crate/construct-extern-struct-with-destructor.rs similarity index 100% rename from tests/ui/issues/issue-3012-2.rs rename to tests/ui/cross-crate/construct-extern-struct-with-destructor.rs diff --git a/tests/ui/issues/issue-29265.rs b/tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs similarity index 100% rename from tests/ui/issues/issue-29265.rs rename to tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs diff --git a/tests/ui/issues/issue-3979-xcrate.rs b/tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs similarity index 100% rename from tests/ui/issues/issue-3979-xcrate.rs rename to tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs diff --git a/tests/ui/issues/issue-2526-a.rs b/tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs similarity index 100% rename from tests/ui/issues/issue-2526-a.rs rename to tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs diff --git a/tests/ui/issues/issue-38226.rs b/tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs similarity index 100% rename from tests/ui/issues/issue-38226.rs rename to tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs diff --git a/tests/ui/issues/issue-41053.rs b/tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs similarity index 100% rename from tests/ui/issues/issue-41053.rs rename to tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs diff --git a/tests/ui/issues/issue-4545.rs b/tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs similarity index 100% rename from tests/ui/issues/issue-4545.rs rename to tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs diff --git a/tests/ui/issues/issue-42007.rs b/tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs similarity index 100% rename from tests/ui/issues/issue-42007.rs rename to tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs diff --git a/tests/ui/issues/issue-48984.rs b/tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs similarity index 100% rename from tests/ui/issues/issue-48984.rs rename to tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs diff --git a/tests/ui/issues/issue-2723-b.rs b/tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs similarity index 100% rename from tests/ui/issues/issue-2723-b.rs rename to tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs diff --git a/tests/ui/issues/issue-2380-b.rs b/tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs similarity index 100% rename from tests/ui/issues/issue-2380-b.rs rename to tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs diff --git a/tests/ui/issues/issue-4208.rs b/tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs similarity index 100% rename from tests/ui/issues/issue-4208.rs rename to tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs diff --git a/tests/ui/issues/issue-41549.rs b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs similarity index 100% rename from tests/ui/issues/issue-41549.rs rename to tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs diff --git a/tests/ui/issues/issue-41549.stderr b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr similarity index 100% rename from tests/ui/issues/issue-41549.stderr rename to tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr diff --git a/tests/ui/issues/issue-20389.rs b/tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs similarity index 100% rename from tests/ui/issues/issue-20389.rs rename to tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs diff --git a/tests/ui/issues/issue-19293.rs b/tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs similarity index 100% rename from tests/ui/issues/issue-19293.rs rename to tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs diff --git a/tests/ui/issues/issue-2170-exe.rs b/tests/ui/cross-crate/link-extern-crate-with-drop-type.rs similarity index 100% rename from tests/ui/issues/issue-2170-exe.rs rename to tests/ui/cross-crate/link-extern-crate-with-drop-type.rs diff --git a/tests/ui/issues/issue-38190.rs b/tests/ui/cross-crate/macro-generated-module-path-resolution.rs similarity index 100% rename from tests/ui/issues/issue-38190.rs rename to tests/ui/cross-crate/macro-generated-module-path-resolution.rs diff --git a/tests/ui/issues/issue-51798.rs b/tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs similarity index 100% rename from tests/ui/issues/issue-51798.rs rename to tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs diff --git a/tests/ui/issues/issue-2631-b.rs b/tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs similarity index 100% rename from tests/ui/issues/issue-2631-b.rs rename to tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs diff --git a/tests/ui/issues/issue-29485.rs b/tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs similarity index 100% rename from tests/ui/issues/issue-29485.rs rename to tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs diff --git a/tests/ui/issues/issue-3136-b.rs b/tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs similarity index 100% rename from tests/ui/issues/issue-3136-b.rs rename to tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs diff --git a/tests/ui/issues/issue-32518.rs b/tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs similarity index 100% rename from tests/ui/issues/issue-32518.rs rename to tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs diff --git a/tests/ui/issues/issue-31702.rs b/tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs similarity index 100% rename from tests/ui/issues/issue-31702.rs rename to tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs diff --git a/tests/ui/issues/issue-34796.rs b/tests/ui/cross-crate/stable-hash-for-trait-object-type.rs similarity index 100% rename from tests/ui/issues/issue-34796.rs rename to tests/ui/cross-crate/stable-hash-for-trait-object-type.rs diff --git a/tests/ui/issues/issue-25467.rs b/tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs similarity index 100% rename from tests/ui/issues/issue-25467.rs rename to tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs diff --git a/tests/ui/issues/issue-2414-c.rs b/tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs similarity index 100% rename from tests/ui/issues/issue-2414-c.rs rename to tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs diff --git a/tests/ui/issues/issue-30123.rs b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs similarity index 100% rename from tests/ui/issues/issue-30123.rs rename to tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs diff --git a/tests/ui/issues/issue-30123.stderr b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr similarity index 100% rename from tests/ui/issues/issue-30123.stderr rename to tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr From 1e1560b5bef4b3fa74f419da6786caaa0d199bf7 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Thu, 4 Jun 2026 13:04:43 +0100 Subject: [PATCH 14/33] add issue links and bless --- .../auxiliary/const-fn-evaluated-cross-crate.rs | 1 + .../construct-extern-struct-with-destructor.rs | 3 ++- .../cross-crate-static-reference-and-field-access.rs | 1 + ...ross-crate-trait-inheritance-on-default-method.rs | 3 ++- ...cross-crate-type-alias-with-nested-destructors.rs | 3 ++- ...lt-trait-method-reachable-through-trait-object.rs | 1 + .../extern-crate-and-impl-inside-method-body.rs | 1 + .../extern-generic-tuple-struct-construction.rs | 1 + .../extern-repr-enum-with-discriminant-cast.rs | 1 + .../extern-trait-bound-with-array-associated-type.rs | 3 ++- .../fn-declared-inside-closure-body-cross-crate.rs | 1 + .../fn-local-impl-returned-as-trait-object.rs | 1 + .../auxiliary/for-loop-in-match-on-self.rs | 3 +-- .../generic-fn-with-supertrait-bound-cross-crate.rs | 3 ++- .../graceful-error-for-mistyped-assoc-const.rs | 1 + .../impl-extern-trait-with-associated-type.rs | 1 + .../imported-struct-not-confused-with-variant.rs | 1 + .../auxiliary/link-extern-crate-with-drop-type.rs | 1 + .../macro-generated-module-path-resolution.rs | 1 + .../method-call-on-extern-fn-return-value.rs | 1 + .../auxiliary/monomorphize-index-op-cross-crate.rs | 1 + .../auxiliary/mut-ref-write-visible-after-unwind.rs | 3 ++- .../nested-struct-in-polymorphic-impl-method.rs | 1 + ...uplicate-symbols-with-codegen-units-cgu-test-a.rs | 3 ++- ...uplicate-symbols-with-codegen-units-cgu-test-b.rs | 3 ++- ...-duplicate-symbols-with-codegen-units-cgu-test.rs | 1 + ...ptimized-closure-with-debug-info-cross-crate-1.rs | 1 + ...ptimized-closure-with-debug-info-cross-crate-2.rs | 5 +++-- .../auxiliary/stable-hash-for-trait-object-type.rs | 1 + ...-object-projection-bounds-with-interning-order.rs | 1 + .../transitive-crate-dependency-with-trait-impl-a.rs | 1 + .../transitive-crate-dependency-with-trait-impl-b.rs | 1 + ...e-default-applied-in-cross-crate-method-lookup.rs | 1 + .../ui/cross-crate/const-fn-evaluated-cross-crate.rs | 8 ++++++-- .../construct-extern-struct-with-destructor.rs | 6 ++++-- .../cross-crate-static-reference-and-field-access.rs | 8 ++++++-- ...ross-crate-trait-inheritance-on-default-method.rs | 6 ++++-- ...cross-crate-type-alias-with-nested-destructors.rs | 7 ++++--- ...lt-trait-method-reachable-through-trait-object.rs | 4 ++-- .../extern-crate-and-impl-inside-method-body.rs | 9 +++++++-- .../extern-generic-tuple-struct-construction.rs | 6 +++--- .../extern-repr-enum-with-discriminant-cast.rs | 10 +++++++--- .../extern-trait-bound-with-array-associated-type.rs | 10 ++++++++-- .../fn-declared-inside-closure-body-cross-crate.rs | 8 +++++--- .../fn-local-impl-returned-as-trait-object.rs | 7 +++++-- .../generic-fn-with-supertrait-bound-cross-crate.rs | 6 +++--- .../graceful-error-for-mistyped-assoc-const.rs | 9 +++++---- .../graceful-error-for-mistyped-assoc-const.stderr | 2 +- .../impl-extern-trait-with-associated-type.rs | 10 ++++++---- .../imported-struct-not-confused-with-variant.rs | 9 ++++++--- .../cross-crate/link-extern-crate-with-drop-type.rs | 7 +++++-- .../macro-generated-module-path-resolution.rs | 12 ++++++++---- .../method-call-on-extern-fn-return-value.rs | 8 ++++++-- .../cross-crate/monomorphize-index-op-cross-crate.rs | 4 +++- .../mut-ref-write-visible-after-unwind.rs | 8 +++++--- .../nested-struct-in-polymorphic-impl-method.rs | 5 +++-- .../no-duplicate-symbols-with-codegen-units.rs | 11 ++++++----- .../optimized-closure-with-debug-info-cross-crate.rs | 9 +++++---- .../cross-crate/stable-hash-for-trait-object-type.rs | 5 +++-- ...-object-projection-bounds-with-interning-order.rs | 6 ++++-- .../transitive-crate-dependency-with-trait-impl.rs | 5 +++-- ...e-default-applied-in-cross-crate-method-lookup.rs | 7 ++++--- ...fault-applied-in-cross-crate-method-lookup.stderr | 12 ++++++------ .../duplicate-rlib-crate-name-precedence-1.rs | 3 +-- .../duplicate-rlib-crate-name-precedence-2.rs | 3 +-- 65 files changed, 188 insertions(+), 97 deletions(-) diff --git a/tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs b/tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs index bc444a3817b88..9f0900809b18b 100644 --- a/tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs +++ b/tests/ui/cross-crate/auxiliary/const-fn-evaluated-cross-crate.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/36954 #![crate_type = "lib"] const fn foo(i: i32) -> i32 { diff --git a/tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs b/tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs index 509af2a8d7df3..e01835cce563a 100644 --- a/tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs +++ b/tests/ui/cross-crate/auxiliary/construct-extern-struct-with-destructor.rs @@ -1,4 +1,5 @@ -#![crate_name="socketlib"] +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/3012 +#![crate_name="construct_extern_struct_with_destructor"] #![crate_type = "lib"] pub mod socket { diff --git a/tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs b/tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs index 6d26002a2e707..5c50ee0d59ce6 100644 --- a/tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs +++ b/tests/ui/cross-crate/auxiliary/cross-crate-static-reference-and-field-access.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/29265 #![crate_type = "lib"] pub struct SomeType { diff --git a/tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs b/tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs index 5d03a0e9e9931..17796ae23d4e2 100644 --- a/tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs +++ b/tests/ui/cross-crate/auxiliary/cross-crate-trait-inheritance-on-default-method.rs @@ -1,4 +1,5 @@ -#![crate_name="issue_3979_traits"] +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/3979 +#![crate_name="cross_crate_trait_inheritance_on_default_method"] #![crate_type = "lib"] diff --git a/tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs b/tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs index 3b27f658cdae5..879f215b24f4e 100644 --- a/tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs +++ b/tests/ui/cross-crate/auxiliary/cross-crate-type-alias-with-nested-destructors.rs @@ -1,4 +1,5 @@ -#![crate_name="issue_2526"] +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2526 +#![crate_name="cross_crate_type_alias_with_nested_destructors"] #![crate_type = "lib"] use std::marker; diff --git a/tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs b/tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs index a8e964e016fd1..b14a140de18f5 100644 --- a/tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs +++ b/tests/ui/cross-crate/auxiliary/default-trait-method-reachable-through-trait-object.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/38226 #![crate_type="rlib"] #[inline(never)] diff --git a/tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs b/tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs index ae73c3e780fb3..cd011fc294c44 100644 --- a/tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs +++ b/tests/ui/cross-crate/auxiliary/extern-crate-and-impl-inside-method-body.rs @@ -1 +1,2 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/41053 pub struct Test; diff --git a/tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs b/tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs index 2f60947507541..1a27ca252a30e 100644 --- a/tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs +++ b/tests/ui/cross-crate/auxiliary/extern-generic-tuple-struct-construction.rs @@ -1,2 +1,3 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/4545 pub struct S(Option); pub fn mk() -> S { S(None) } diff --git a/tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs b/tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs index 95119a589c99d..85819006c78ae 100644 --- a/tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs +++ b/tests/ui/cross-crate/auxiliary/extern-repr-enum-with-discriminant-cast.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/42007 #[repr(u8)] pub enum E { B = 1 as u8, diff --git a/tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs b/tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs index 7cc888cd4cb29..d383b9ff64b80 100644 --- a/tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs +++ b/tests/ui/cross-crate/auxiliary/extern-trait-bound-with-array-associated-type.rs @@ -1,5 +1,6 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/48984 #![crate_type = "lib"] -#![crate_name = "issue48984aux"] +#![crate_name = "extern_trait_bound_with_array_associated_type"] pub trait Foo { type Item; } diff --git a/tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs b/tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs index 661b46d829dfe..6346ebfb54dd4 100644 --- a/tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs +++ b/tests/ui/cross-crate/auxiliary/fn-declared-inside-closure-body-cross-crate.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2723 pub unsafe fn f(xs: Vec ) { xs.iter().map(|_x| { unsafe fn q() { panic!(); } }).collect::>(); } diff --git a/tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs b/tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs index 9ec829b417f81..420792577cf04 100644 --- a/tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs +++ b/tests/ui/cross-crate/auxiliary/fn-local-impl-returned-as-trait-object.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2380 #![crate_name="a"] #![crate_type = "lib"] diff --git a/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs b/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs index 307f23c10e284..db1f5edb4507e 100644 --- a/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs +++ b/tests/ui/cross-crate/auxiliary/for-loop-in-match-on-self.rs @@ -1,5 +1,4 @@ -//! Auxiliary crate for . - +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/16643 #![crate_type = "lib"] pub struct TreeBuilder { pub h: H } diff --git a/tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs b/tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs index 7b4c8b01a9e2f..ad0fe922d6f2f 100644 --- a/tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs +++ b/tests/ui/cross-crate/auxiliary/generic-fn-with-supertrait-bound-cross-crate.rs @@ -1,4 +1,5 @@ -#![crate_name="numeric"] +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/4208 +#![crate_name="generic_fn_with_supertrait_bound_cross_crate"] #![crate_type = "lib"] pub trait Trig { diff --git a/tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs b/tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs index b7bd375250f0b..84ac2b5ae9de3 100644 --- a/tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs +++ b/tests/ui/cross-crate/auxiliary/graceful-error-for-mistyped-assoc-const.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/41549 pub trait Trait { const CONST: u32; } diff --git a/tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs b/tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs index ae6d44eeb7703..5d935380e0649 100644 --- a/tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs +++ b/tests/ui/cross-crate/auxiliary/impl-extern-trait-with-associated-type.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/20389 pub trait T { type C; fn dummy(&self) { } diff --git a/tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs b/tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs index 31359e86559dd..4f70e98f22af9 100644 --- a/tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs +++ b/tests/ui/cross-crate/auxiliary/imported-struct-not-confused-with-variant.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/19293 pub struct Foo (pub isize); pub enum MyEnum { Foo(Foo), diff --git a/tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs b/tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs index a99385a834dfb..e498dd0758cef 100644 --- a/tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs +++ b/tests/ui/cross-crate/auxiliary/link-extern-crate-with-drop-type.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/20389 fn foo(_x: i32) { } diff --git a/tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs b/tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs index 373e646ba2c39..f808fa793e475 100644 --- a/tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs +++ b/tests/ui/cross-crate/auxiliary/macro-generated-module-path-resolution.rs @@ -1,2 +1,3 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/38190 #[macro_export] macro_rules! m { ([$i:item]) => {} } diff --git a/tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs b/tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs index fef5213db9f7a..02f85ee90ee6b 100644 --- a/tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs +++ b/tests/ui/cross-crate/auxiliary/method-call-on-extern-fn-return-value.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/51798 #![crate_type = "lib"] pub fn vec() -> Vec { vec![] } diff --git a/tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs b/tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs index 1e8211bfaa783..6ab538044fa5c 100644 --- a/tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs +++ b/tests/ui/cross-crate/auxiliary/monomorphize-index-op-cross-crate.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2631 #![crate_name="req"] #![crate_type = "lib"] diff --git a/tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs b/tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs index 1e8891c51206f..2545f4f0c48cc 100644 --- a/tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs +++ b/tests/ui/cross-crate/auxiliary/mut-ref-write-visible-after-unwind.rs @@ -1,4 +1,5 @@ -#![crate_name="a"] +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/29265 +#![crate_name="mut_ref_write_visible_after_unwind"] #![crate_type = "lib"] pub struct X(pub u8); diff --git a/tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs b/tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs index 22bb1c8f97709..24f7601b67125 100644 --- a/tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs +++ b/tests/ui/cross-crate/auxiliary/nested-struct-in-polymorphic-impl-method.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/3136 #![crate_type = "lib"] trait x { diff --git a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs index 7998f1870b8fe..22618804fe629 100644 --- a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs +++ b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-a.rs @@ -1,7 +1,8 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/32518 //@ no-prefer-dynamic //@ compile-flags: -Ccodegen-units=2 --crate-type=lib -extern crate cgu_test; +extern crate no_duplicate_symbols_with_codegen_units_cgu_test as cgu_test; pub mod a { pub fn a() { diff --git a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs index 7998f1870b8fe..22618804fe629 100644 --- a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs +++ b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test-b.rs @@ -1,7 +1,8 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/32518 //@ no-prefer-dynamic //@ compile-flags: -Ccodegen-units=2 --crate-type=lib -extern crate cgu_test; +extern crate no_duplicate_symbols_with_codegen_units_cgu_test as cgu_test; pub mod a { pub fn a() { diff --git a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs index 1103fcb1f0b28..73dd32b34ba8b 100644 --- a/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs +++ b/tests/ui/cross-crate/auxiliary/no-duplicate-symbols-with-codegen-units-cgu-test.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/32518 //@ no-prefer-dynamic //@ compile-flags: --crate-type=lib diff --git a/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs index a48d0dc2c6447..b14ce0b0dc190 100644 --- a/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs +++ b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-1.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/31702 #[derive(Copy)] pub struct U256(pub [u64; 4]); diff --git a/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs index 16300b0f5d530..05da5e21824cd 100644 --- a/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs +++ b/tests/ui/cross-crate/auxiliary/optimized-closure-with-debug-info-cross-crate-2.rs @@ -1,9 +1,10 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/31702 //@ compile-flags: -g -extern crate issue_31702_1; +extern crate optimized_closure_with_debug_info_cross_crate_1; use std::collections::HashMap; -use issue_31702_1::U256; +use optimized_closure_with_debug_info_cross_crate_1::U256; pub struct Ethash { engine_params: fn() -> Option<&'static Vec>, diff --git a/tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs b/tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs index 0e91bb4bcdc1f..a3c278db38a60 100644 --- a/tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs +++ b/tests/ui/cross-crate/auxiliary/stable-hash-for-trait-object-type.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate for regression test of https://github.com/rust-lang/rust/issues/34796 #![crate_type = "lib"] pub trait Future { type Item; diff --git a/tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs b/tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs index 16c2869dc75cc..eb58bb5d29d06 100644 --- a/tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs +++ b/tests/ui/cross-crate/auxiliary/trait-object-projection-bounds-with-interning-order.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/25467 #![crate_type="lib"] pub trait Trait { diff --git a/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs index b90ab32ddc4ad..58d79571f8d97 100644 --- a/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs +++ b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-a.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2414 #![crate_name="a"] #![crate_type = "lib"] diff --git a/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs index fc018349d80f1..eddb36bc4d0fa 100644 --- a/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs +++ b/tests/ui/cross-crate/auxiliary/transitive-crate-dependency-with-trait-impl-b.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/2414 #![crate_name="b"] #![crate_type = "lib"] diff --git a/tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs b/tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs index 07c743eb2aa34..68b9f6843ddbd 100644 --- a/tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs +++ b/tests/ui/cross-crate/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs @@ -1,3 +1,4 @@ +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/30123 use std::marker::PhantomData; pub struct Directed; diff --git a/tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs b/tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs index 411e99b603da4..cf0843f01ce8a 100644 --- a/tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs +++ b/tests/ui/cross-crate/const-fn-evaluated-cross-crate.rs @@ -1,7 +1,11 @@ //@ run-pass -//@ aux-build:issue-36954.rs +//@ aux-build:const-fn-evaluated-cross-crate.rs +//! Regression test for https://github.com/rust-lang/rust/issues/36954 +//! Cross crate const fn evaluation failed because the compiler's +//! internal argument lookup table used crate local ids that didn't +//! exist when evaluating a const fn from another crate. -extern crate issue_36954 as lib; +extern crate const_fn_evaluated_cross_crate as lib; fn main() { let _ = lib::FOO; diff --git a/tests/ui/cross-crate/construct-extern-struct-with-destructor.rs b/tests/ui/cross-crate/construct-extern-struct-with-destructor.rs index fd090d5e7b50e..d916305bbc764 100644 --- a/tests/ui/cross-crate/construct-extern-struct-with-destructor.rs +++ b/tests/ui/cross-crate/construct-extern-struct-with-destructor.rs @@ -1,8 +1,10 @@ //@ run-pass -//@ aux-build:issue-3012-1.rs +//@ aux-build:construct-extern-struct-with-destructor.rs +//! Regression test for https://github.com/rust-lang/rust/issues/3012 +//! Guarantees that you can construct cross crate structs. -extern crate socketlib; +extern crate construct_extern_struct_with_destructor as socketlib; use socketlib::socket; diff --git a/tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs b/tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs index a3da9be3a3b65..25e52c153ba0e 100644 --- a/tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs +++ b/tests/ui/cross-crate/cross-crate-static-reference-and-field-access.rs @@ -1,7 +1,11 @@ -//@ aux-build:issue-29265.rs +//@ aux-build:cross-crate-static-reference-and-field-access.rs //@ check-pass -extern crate issue_29265 as lib; +//! Regression test for https://github.com/rust-lang/rust/issues/29265 +//! Exposed an bug where referencing a static variable from another crate +//! was causing an error. + +extern crate cross_crate_static_reference_and_field_access as lib; static _UNUSED: &'static lib::SomeType = &lib::SOME_VALUE; diff --git a/tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs b/tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs index 7660405929bfb..3ff481d2c17e9 100644 --- a/tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs +++ b/tests/ui/cross-crate/cross-crate-trait-inheritance-on-default-method.rs @@ -1,8 +1,10 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:issue-3979-traits.rs +//@ aux-build:cross-crate-trait-inheritance-on-default-method.rs +//! Regression test for https://github.com/rust-lang/rust/issues/3979 +//! Exposed a bug where external traits on a default method were failing to typecheck. -extern crate issue_3979_traits; +extern crate cross_crate_trait_inheritance_on_default_method as issue_3979_traits; use issue_3979_traits::{Positioned, Movable}; struct Point { x: isize, y: isize } diff --git a/tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs b/tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs index 379146d02b3de..c12dc04f5ab4a 100644 --- a/tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs +++ b/tests/ui/cross-crate/cross-crate-type-alias-with-nested-destructors.rs @@ -1,10 +1,11 @@ //@ run-pass -//@ aux-build:issue-2526.rs +//@ aux-build:cross-crate-type-alias-with-nested-destructors.rs +//! Regression test for https://github.com/rust-lang/rust/issues/2526 #![allow(unused_imports)] -extern crate issue_2526; -use issue_2526::*; +extern crate cross_crate_type_alias_with_nested_destructors; +use cross_crate_type_alias_with_nested_destructors::*; pub fn main() {} diff --git a/tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs b/tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs index d8bd9d64a7c60..a7683252757e8 100644 --- a/tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs +++ b/tests/ui/cross-crate/default-trait-method-reachable-through-trait-object.rs @@ -2,13 +2,13 @@ // This test makes sure that we don't run into a linker error because of the // middle::reachable pass missing trait methods with default impls. -//@ aux-build:issue-38226-aux.rs +//@ aux-build:default-trait-method-reachable-through-trait-object.rs // Need -Cno-prepopulate-passes to really disable inlining, otherwise the faulty // code gets optimized out: //@ compile-flags: -Cno-prepopulate-passes -Cpasses=name-anon-globals -extern crate issue_38226_aux; +extern crate default_trait_method_reachable_through_trait_object as issue_38226_aux; fn main() { issue_38226_aux::foo::<()>(); diff --git a/tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs b/tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs index 42b0b008ce9b5..15ce563d575d9 100644 --- a/tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs +++ b/tests/ui/cross-crate/extern-crate-and-impl-inside-method-body.rs @@ -1,5 +1,10 @@ //@ run-pass -//@ aux-build:issue-41053.rs +//@ aux-build:extern-crate-and-impl-inside-method-body.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/41053 +//! An extern crate declaration and trait impl referencing that crate +//! inside an impl method body triggered a borrow conflict in the +//! compiler's visible_parent_map. #![allow(non_local_definitions)] @@ -10,7 +15,7 @@ pub struct Foo; impl Iterator for Foo { type Item = Box; fn next(&mut self) -> Option> { - extern crate issue_41053; + extern crate extern_crate_and_impl_inside_method_body as issue_41053; impl crate::Trait for issue_41053::Test { fn foo(&self) {} } diff --git a/tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs b/tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs index dfb89136cbd22..98d1fec370da9 100644 --- a/tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs +++ b/tests/ui/cross-crate/extern-generic-tuple-struct-construction.rs @@ -1,6 +1,6 @@ //@ run-pass -//@ aux-build:issue-4545.rs +//@ aux-build:extern-generic-tuple-struct-construction.rs +//! Regression test for https://github.com/rust-lang/rust/issues/4545 - -extern crate issue_4545 as somelib; +extern crate extern_generic_tuple_struct_construction as somelib; pub fn main() { somelib::mk::(); } diff --git a/tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs b/tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs index b8ea7e871a736..96f345d002d86 100644 --- a/tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs +++ b/tests/ui/cross-crate/extern-repr-enum-with-discriminant-cast.rs @@ -1,8 +1,12 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:issue-42007-s.rs - -extern crate issue_42007_s; +//@ aux-build:extern-repr-enum-with-discriminant-cast.rs +//! Regression test for https://github.com/rust-lang/rust/issues/42007 +//! This test exposes a bug that happens because the Session LintStore is emptied when linting +//! The LintStore is emptied because the checker wants ownership as it wants to +//! mutate the pass objects and lint levels. +//! The fix was not taking ownership of the entire store just the lint levels and pass objects. +extern crate extern_repr_enum_with_discriminant_cast as issue_42007_s; enum I { E(issue_42007_s::E), diff --git a/tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs b/tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs index 0440789a480aa..a0b5d0e876963 100644 --- a/tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs +++ b/tests/ui/cross-crate/extern-trait-bound-with-array-associated-type.rs @@ -1,7 +1,13 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:issue-48984-aux.rs -extern crate issue48984aux; +//@ aux-build:extern-trait-bound-with-array-associated-type.rs +//! Regression test for https://github.com/rust-lang/rust/issues/48984 +//! This test exposes an error that occurs when a base trait has at +//! least one associated type, and the extending trait specifies the +//! associated type as an array of some kind. In order to trigger the +//! error, the extending trait must be defined in an external crate, and +//! used to constrain a generic type parameter. +extern crate extern_trait_bound_with_array_associated_type as issue48984aux; use issue48984aux::Bar; fn do_thing() { } diff --git a/tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs b/tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs index 731e521f26f89..9d47358777c53 100644 --- a/tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs +++ b/tests/ui/cross-crate/fn-declared-inside-closure-body-cross-crate.rs @@ -1,8 +1,10 @@ //@ run-pass -//@ aux-build:issue-2723-a.rs +//@ aux-build:fn-declared-inside-closure-body-cross-crate.rs -extern crate issue_2723_a; -use issue_2723_a::f; +//! Regression test for https://github.com/rust-lang/rust/issues/2723 + +extern crate fn_declared_inside_closure_body_cross_crate; +use fn_declared_inside_closure_body_cross_crate::f; pub fn main() { unsafe { diff --git a/tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs b/tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs index 503698f88c620..0fc404784e22b 100644 --- a/tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs +++ b/tests/ui/cross-crate/fn-local-impl-returned-as-trait-object.rs @@ -1,6 +1,9 @@ //@ run-pass -//@ aux-build:issue-2380.rs - +//@ aux-build:fn-local-impl-returned-as-trait-object.rs +//! Regression test for https://github.com/rust-lang/rust/issues/2380 +//! This test exposes a bug where a function that defines a trait impl inside its body +//! and returns it as a trait object failed because the reachability pass skipped nested +//! items in function bodies. extern crate a; diff --git a/tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs b/tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs index 84938bea022d1..bce55b2140068 100644 --- a/tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs +++ b/tests/ui/cross-crate/generic-fn-with-supertrait-bound-cross-crate.rs @@ -1,9 +1,9 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:issue-4208-cc.rs +//@ aux-build:generic-fn-with-supertrait-bound-cross-crate.rs - -extern crate numeric; +//! Regression test for https://github.com/rust-lang/rust/issues/4208 +extern crate generic_fn_with_supertrait_bound_cross_crate as numeric; use numeric::{sin, Angle}; fn foo>(theta: A) -> T { sin(&theta) } diff --git a/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs index 8f57515415c6e..238fb6bf0e738 100644 --- a/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs +++ b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.rs @@ -1,7 +1,8 @@ -//@ aux-build:issue-41549.rs - - -extern crate issue_41549; +//@ aux-build:graceful-error-for-mistyped-assoc-const.rs +//! Regression test for https://github.com/rust-lang/rust/issues/41549 +//! Mismatched types on exernal associated constants used to ice, +//! this test confirms that it errors correctly. +extern crate graceful_error_for_mistyped_assoc_const as issue_41549; struct S; diff --git a/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr index 55be59684b55d..18b06462de7b6 100644 --- a/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr +++ b/tests/ui/cross-crate/graceful-error-for-mistyped-assoc-const.stderr @@ -1,5 +1,5 @@ error[E0326]: implemented const `CONST` has an incompatible type for trait - --> $DIR/issue-41549.rs:9:18 + --> $DIR/graceful-error-for-mistyped-assoc-const.rs:10:18 | LL | const CONST: () = (); | ^^ expected `u32`, found `()` diff --git a/tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs b/tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs index e201663afc522..c6905e9002b29 100644 --- a/tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs +++ b/tests/ui/cross-crate/impl-extern-trait-with-associated-type.rs @@ -1,13 +1,15 @@ //@ run-pass #![allow(dead_code)] -//@ aux-build:issue-20389.rs +//@ aux-build:impl-extern-trait-with-associated-type.rs +//! Regression test for https://github.com/rust-lang/rust/issues/20389 +//! This test confirms that code implementing a trait with an associated type from an external crate +//! runs. - -extern crate issue_20389; +extern crate impl_extern_trait_with_associated_type; struct Foo; -impl issue_20389::T for Foo { +impl impl_extern_trait_with_associated_type::T for Foo { type C = (); } diff --git a/tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs b/tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs index 42effe303d036..458fc32be0cea 100644 --- a/tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs +++ b/tests/ui/cross-crate/imported-struct-not-confused-with-variant.rs @@ -1,8 +1,11 @@ //@ run-pass -//@ aux-build:issue-19293.rs +//@ aux-build:imported-struct-not-confused-with-variant.rs -extern crate issue_19293; -use issue_19293::{Foo, MyEnum}; +//! Regression test for https://github.com/rust-lang/rust/issues/19293 +//! This test ensures that cross crate variants are properly namespaced under their enum or struct. + +extern crate imported_struct_not_confused_with_variant; +use imported_struct_not_confused_with_variant::{Foo, MyEnum}; fn main() { MyEnum::Foo(Foo(5)); diff --git a/tests/ui/cross-crate/link-extern-crate-with-drop-type.rs b/tests/ui/cross-crate/link-extern-crate-with-drop-type.rs index b66843d48cad6..623a644dcbf9f 100644 --- a/tests/ui/cross-crate/link-extern-crate-with-drop-type.rs +++ b/tests/ui/cross-crate/link-extern-crate-with-drop-type.rs @@ -1,7 +1,10 @@ //@ run-pass -//@ aux-build:issue-2170-lib.rs +//@ aux-build:link-extern-crate-with-drop-type.rs +//! Regression test for https://github.com/rust-lang/rust/issues/2170 +//! This test just verifies that linking against an external crate works without +//! a metadata failure. Apparently, having a Drop that calls another function is the trigger. -extern crate issue_2170_lib; +extern crate link_extern_crate_with_drop_type; pub fn main() { // let _ = issue_2170_lib::rsrc(2); diff --git a/tests/ui/cross-crate/macro-generated-module-path-resolution.rs b/tests/ui/cross-crate/macro-generated-module-path-resolution.rs index 539d7f2ed3be4..f785c24a83623 100644 --- a/tests/ui/cross-crate/macro-generated-module-path-resolution.rs +++ b/tests/ui/cross-crate/macro-generated-module-path-resolution.rs @@ -1,13 +1,17 @@ //@ run-pass -//@ aux-build:issue-38190.rs +//@ aux-build:macro-generated-module-path-resolution.rs +//! Regression test for https://github.com/rust-lang/rust/issues/38190 +//! Non inline modules parsed as macro item fragments used the wrong +//! directory for file resolution, because the fragment parser didn't +//! inherit the correct directory from the macro invocation context. #[macro_use] -extern crate issue_38190; +extern crate macro_generated_module_path_resolution as aux; mod auxiliary { m!([ - #[path = "issue-38190.rs"] - mod issue_38190; + #[path = "macro-generated-module-path-resolution"] + mod aux; ]); } diff --git a/tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs b/tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs index f4d59f39952eb..26a24aeb8ca99 100644 --- a/tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs +++ b/tests/ui/cross-crate/method-call-on-extern-fn-return-value.rs @@ -1,8 +1,12 @@ //@ edition:2018 -//@ aux-build:issue-51798.rs +//@ aux-build:method-call-on-extern-fn-return-value.rs //@ check-pass +//! Regression test for https://github.com/rust-lang/rust/issues/51798 +//! Calling a method on a value returned from an external crate function +//! caused the privacy checker to panic when looking up the method's +//! type dependent definition. Requires 2018 edition. -extern crate issue_51798; +extern crate method_call_on_extern_fn_return_value as issue_51798; mod server { fn f() { diff --git a/tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs b/tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs index fb2ecd74a6595..b915bbebf785b 100644 --- a/tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs +++ b/tests/ui/cross-crate/monomorphize-index-op-cross-crate.rs @@ -1,6 +1,8 @@ //@ run-pass -//@ aux-build:issue-2631-a.rs +//@ aux-build:monomorphize-index-op-cross-crate.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/2631 extern crate req; diff --git a/tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs b/tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs index 843a684a85b5e..2e3073286f0f6 100644 --- a/tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs +++ b/tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs @@ -1,14 +1,16 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/29485 +//! Exposed an LLVM bug that caused rustc to panic. //@ run-pass -//@ aux-build:issue-29485.rs +//@ aux-build:mut-ref-write-visible-after-unwind.rs //@ needs-unwind //@ needs-threads //@ ignore-backends: gcc -extern crate a; +extern crate mut_ref_write_visible_after_unwind as lib; fn main() { let _ = std::thread::spawn(move || { - a::f(&mut a::X(0), g); + lib::f(&mut lib::X(0), g); }).join(); } diff --git a/tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs b/tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs index bd6ea732643f1..12d09cdc84440 100644 --- a/tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs +++ b/tests/ui/cross-crate/nested-struct-in-polymorphic-impl-method.rs @@ -1,7 +1,8 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/3136 //@ run-pass -//@ aux-build:issue-3136-a.rs +//@ aux-build:nested-struct-in-polymorphic-impl-method.rs -extern crate issue_3136_a; +extern crate nested_struct_in_polymorphic_impl_method; pub fn main() {} diff --git a/tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs b/tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs index 45a882850c009..f54c89a9162c3 100644 --- a/tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs +++ b/tests/ui/cross-crate/no-duplicate-symbols-with-codegen-units.rs @@ -1,11 +1,12 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/32518 //@ run-pass //@ no-prefer-dynamic -//@ aux-build:cgu_test.rs -//@ aux-build:cgu_test_a.rs -//@ aux-build:cgu_test_b.rs +//@ aux-build:no-duplicate-symbols-with-codegen-units-cgu-test.rs +//@ aux-build:no-duplicate-symbols-with-codegen-units-cgu-test-a.rs +//@ aux-build:no-duplicate-symbols-with-codegen-units-cgu-test-b.rs -extern crate cgu_test_a; -extern crate cgu_test_b; +extern crate no_duplicate_symbols_with_codegen_units_cgu_test_a as cgu_test_a; +extern crate no_duplicate_symbols_with_codegen_units_cgu_test_b as cgu_test_b; fn main() { cgu_test_a::a::a(); diff --git a/tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs b/tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs index 1cf01f7f04ecc..f0b34bdd86f0a 100644 --- a/tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs +++ b/tests/ui/cross-crate/optimized-closure-with-debug-info-cross-crate.rs @@ -1,10 +1,11 @@ //@ run-pass -//@ aux-build:issue-31702-1.rs -//@ aux-build:issue-31702-2.rs +//@ aux-build:optimized-closure-with-debug-info-cross-crate-1.rs +//@ aux-build:optimized-closure-with-debug-info-cross-crate-2.rs +//! Regression test for https://github.com/rust-lang/rust/issues/31702 // this test is actually entirely in the linked library crates -extern crate issue_31702_1; -extern crate issue_31702_2; +extern crate optimized_closure_with_debug_info_cross_crate_1; +extern crate optimized_closure_with_debug_info_cross_crate_2; fn main() {} diff --git a/tests/ui/cross-crate/stable-hash-for-trait-object-type.rs b/tests/ui/cross-crate/stable-hash-for-trait-object-type.rs index 1a417b3483068..725469e4e4f91 100644 --- a/tests/ui/cross-crate/stable-hash-for-trait-object-type.rs +++ b/tests/ui/cross-crate/stable-hash-for-trait-object-type.rs @@ -1,5 +1,6 @@ //@ run-pass #![allow(dead_code)] +// Regression test for https://github.com/rust-lang/rust/issues/34796 // This test case exposes conditions where the encoding of a trait object type // with projection predicates would differ between this crate and the upstream // crate, because the predicates were encoded in different order within each @@ -8,8 +9,8 @@ // the symbol name. // The fix was to make the order in which predicates get encoded stable. -//@ aux-build:issue-34796-aux.rs -extern crate issue_34796_aux; +//@ aux-build:stable-hash-for-trait-object-type.rs +extern crate stable_hash_for_trait_object_type as issue_34796_aux; fn mk() -> T { loop {} } diff --git a/tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs b/tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs index 1ba5a0ef697a1..44aff69126c2a 100644 --- a/tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs +++ b/tests/ui/cross-crate/trait-object-projection-bounds-with-interning-order.rs @@ -1,11 +1,13 @@ //@ run-pass #![allow(unused_variables)] -//@ aux-build:issue-25467.rs +//@ aux-build:trait-object-projection-bounds-with-interning-order.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/25467 pub type Issue25467BarT = (); pub type Issue25467FooT = (); -extern crate issue_25467 as aux; +extern crate trait_object_projection_bounds_with_interning_order as aux; fn main() { let o: aux::Object = None; diff --git a/tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs b/tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs index ac75c5c51051c..8d3b15cfd86bb 100644 --- a/tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs +++ b/tests/ui/cross-crate/transitive-crate-dependency-with-trait-impl.rs @@ -1,7 +1,8 @@ //@ run-pass -//@ aux-build:issue-2414-a.rs -//@ aux-build:issue-2414-b.rs +//@ aux-build:transitive-crate-dependency-with-trait-impl-a.rs +//@ aux-build:transitive-crate-dependency-with-trait-impl-b.rs +//! Regression test for https://github.com/rust-lang/rust/issues/2414 extern crate b; diff --git a/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs index 88fab44741f2e..b0b6f05610d50 100644 --- a/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs +++ b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.rs @@ -1,7 +1,8 @@ -//@ aux-build:issue-30123-aux.rs +//! Regression test for https://github.com/rust-lang/rust/issues/30123 +//@ aux-build:type-default-applied-in-cross-crate-method-lookup.rs -extern crate issue_30123_aux; -use issue_30123_aux::*; +extern crate type_default_applied_in_cross_crate_method_lookup; +use type_default_applied_in_cross_crate_method_lookup::*; fn main() { let ug = Graph::::new_undirected(); diff --git a/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr index 1e2747407d1da..c5c5f206fe071 100644 --- a/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr +++ b/tests/ui/cross-crate/type-default-applied-in-cross-crate-method-lookup.stderr @@ -1,15 +1,15 @@ -error[E0599]: no associated function or constant named `new_undirected` found for struct `issue_30123_aux::Graph` in the current scope - --> $DIR/issue-30123.rs:7:33 +error[E0599]: no associated function or constant named `new_undirected` found for struct `type_default_applied_in_cross_crate_method_lookup::Graph` in the current scope + --> $DIR/type-default-applied-in-cross-crate-method-lookup.rs:8:33 | LL | let ug = Graph::::new_undirected(); - | ^^^^^^^^^^^^^^ associated function or constant not found in `issue_30123_aux::Graph` + | ^^^^^^^^^^^^^^ associated function or constant not found in `type_default_applied_in_cross_crate_method_lookup::Graph` | -note: if you're trying to build a new `issue_30123_aux::Graph`, consider using `issue_30123_aux::Graph::::new` which returns `issue_30123_aux::Graph<_, _>` - --> $DIR/auxiliary/issue-30123-aux.rs:14:5 +note: if you're trying to build a new `type_default_applied_in_cross_crate_method_lookup::Graph`, consider using `type_default_applied_in_cross_crate_method_lookup::Graph::::new` which returns `type_default_applied_in_cross_crate_method_lookup::Graph<_, _>` + --> $DIR/auxiliary/type-default-applied-in-cross-crate-method-lookup.rs:15:5 | LL | pub fn new() -> Self { | ^^^^^^^^^^^^^^^^^^^^ - = note: the associated function or constant was found for `issue_30123_aux::Graph` + = note: the associated function or constant was found for `type_default_applied_in_cross_crate_method_lookup::Graph` error: aborting due to 1 previous error diff --git a/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-1.rs b/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-1.rs index 7b2bfbba12e6e..bac086ba0c054 100644 --- a/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-1.rs +++ b/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-1.rs @@ -1,5 +1,4 @@ -//! Auxiliary crate for . - +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/18913 //@ no-prefer-dynamic #![crate_type = "rlib"] diff --git a/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-2.rs b/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-2.rs index fc0d3d6ea4283..05dba52c6625e 100644 --- a/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-2.rs +++ b/tests/ui/linking/auxiliary/duplicate-rlib-crate-name-precedence-2.rs @@ -1,5 +1,4 @@ -//! Auxiliary crate for . - +//! Auxiliary crate testing this issue https://github.com/rust-lang/rust/issues/18913 //@ no-prefer-dynamic #![crate_type = "rlib"] From f1d8aedadf012810e28285cb5671095badcf589d Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Tue, 2 Jun 2026 02:41:15 -0500 Subject: [PATCH 15/33] add infallible primitive type lookups to template arg resolver --- src/etc/lldb_lookup.py | 2 ++ src/etc/lldb_providers.py | 45 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index cc3e8411306d9..77c508f3ebb77 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -114,6 +114,8 @@ def __lldb_init_module(debugger: lldb.SBDebugger, _dict: LLDBOpaque): FEATURE_FLAGS |= LLDBFeature.StaticFields if getattr(lldb, "eFormatterMatchCallback", None) is not None: FEATURE_FLAGS |= LLDBFeature.TypeRecognizers + if getattr(lldb, "eBasicTypeFloat128", None) is not None: + FEATURE_FLAGS |= LLDBFeature.Float128 register_providers_compatibility() diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 81841dcc4cbb1..f6c2ab8f2b8c7 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -1,6 +1,6 @@ from __future__ import annotations import sys -from typing import Generator, List, TYPE_CHECKING, Optional +from typing import Generator, Dict, List, TYPE_CHECKING, Optional from enum import Flag, auto from lldb import ( @@ -9,6 +9,15 @@ eBasicTypeLong, eBasicTypeUnsignedLong, eBasicTypeUnsignedChar, + eBasicTypeUnsignedShort, + eBasicTypeUnsignedLongLong, + eBasicTypeSignedChar, + eBasicTypeShort, + eBasicTypeLongLong, + eBasicTypeFloat, + eBasicTypeDouble, + eBasicTypeHalf, + eBasicTypeChar32, eFormatChar, eTypeIsInteger, ) @@ -67,6 +76,9 @@ class LLDBFeature(Flag): """Added in LLDB 18. Adds functions to `SBType` the inspection of a struct's static fields.""" TypeRecognizers = auto() """Added in LLDB 19. Callback-based type matching for synthetic/summary providers.""" + Float128 = auto() + """Added in LLDB 22.1. Adds builtin support for Float 128's, including an `eBasicTypeFloat128`, + a formatter, and handlers in `TypeSystemClang`""" FEATURE_FLAGS: LLDBFeature = LLDBFeature(0) @@ -198,6 +210,21 @@ def get_template_args(type_name: str) -> Generator[str, None, None]: MSVC_PTR_PREFIX: List[str] = ["ref$<", "ref_mut$<", "ptr_const$<", "ptr_mut$<"] +PRIMITIVE_TYPES: Dict[str, int] = { + "u8": eBasicTypeUnsignedChar, + "u16": eBasicTypeUnsignedShort, + "u32": eBasicTypeUnsignedLong, + "u64": eBasicTypeUnsignedLongLong, + "i8": eBasicTypeSignedChar, + "i16": eBasicTypeShort, + "i32": eBasicTypeLong, + "i64": eBasicTypeLongLong, + "f16": eBasicTypeHalf, + "f32": eBasicTypeFloat, + "f64": eBasicTypeDouble, + "char": eBasicTypeChar32, +} + def resolve_msvc_template_arg(arg_name: str, target: SBTarget) -> SBType: """ @@ -214,6 +241,22 @@ def resolve_msvc_template_arg(arg_name: str, target: SBTarget) -> SBType: current version of LLDB, so instead the types are generated via `base_type.GetPointerType()` and `base_type.GetArrayType()`, which bypass the PDB file and ask clang directly for the type node. """ + + # As of LLDB 22, finding primitives based on `FindFirstType` with their rust name no longer + # works. Instead, we can look them up by their `eBasicType` equivalent. For usize and isize, + # we convert them to their bit-sized counterpart before the lookup + if arg_name == "isize" or arg_name == "usize": + equivalent = f"{arg_name[0]}{target.GetAddressByteSize() * 8}" + return target.GetBasicType(PRIMITIVE_TYPES[equivalent]) + + if (basic_type := PRIMITIVE_TYPES.get(arg_name)) is not None: + return target.GetBasicType(basic_type) + + if arg_name == "f128" and LLDBFeature.Float128 in FEATURE_FLAGS: + from lldb import eBasicTypeFloat128 + + return target.GetBasicType(eBasicTypeFloat128) + result = target.FindFirstType(arg_name) if result.IsValid(): From c6945a5b4b314ccc513635099713776d0df6e2d0 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Sat, 6 Jun 2026 02:56:30 -0500 Subject: [PATCH 16/33] fix `breakpoint_callback` path --- src/etc/lldb_batchmode/runner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/etc/lldb_batchmode/runner.py b/src/etc/lldb_batchmode/runner.py index e9b106390f6f9..cdc5458606858 100644 --- a/src/etc/lldb_batchmode/runner.py +++ b/src/etc/lldb_batchmode/runner.py @@ -98,7 +98,7 @@ def execute_command(command_interpreter, command): "registering breakpoint callback, id = " + str(breakpoint_id) ) callback_command = f"breakpoint command add -s python {str(breakpoint_id)} -o \ - 'import lldb_batchmode; lldb_batchmode.breakpoint_callback'" +'import lldb_batchmode; lldb_batchmode.runner.breakpoint_callback'" command_interpreter.HandleCommand(callback_command, res) if res.Succeeded(): From c4d84db5f184088791011f216811d9e9fec32f0e Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 8 Aug 2025 17:47:25 +0200 Subject: [PATCH 17/33] Resolver: Batched import resolution. Import resolution now happens in 2 phases: 1. We resolve all undetermined and collect their resolutions 2. Write all resolutions to the Resolver state. Repeat this untill we reach a fix point. + Bless tests --- compiler/rustc_resolve/src/imports.rs | 313 +++++++++++------- compiler/rustc_resolve/src/lib.rs | 35 +- .../crates/hir-ty/src/mir/lower/as_place.rs | 2 +- tests/ui/imports/ambiguous-14.rs | 1 - tests/ui/imports/ambiguous-14.stderr | 36 +- tests/ui/imports/ambiguous-9.rs | 9 +- tests/ui/imports/ambiguous-9.stderr | 52 +-- tests/ui/imports/duplicate.rs | 1 - tests/ui/imports/duplicate.stderr | 71 ++-- tests/ui/imports/import-loop-2.rs | 4 +- tests/ui/imports/import-loop-2.stderr | 8 +- tests/ui/imports/import4.rs | 4 +- tests/ui/imports/import4.stderr | 8 +- .../ui/imports/same-res-ambigious.fail.stderr | 2 +- .../ui/imports/same-res-ambigious.pass.stderr | 20 ++ tests/ui/imports/same-res-ambigious.rs | 3 +- tests/ui/privacy/privacy1.stderr | 24 +- 17 files changed, 303 insertions(+), 290 deletions(-) create mode 100644 tests/ui/imports/same-res-ambigious.pass.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 46cc163ca8ed2..bed025438c331 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -57,6 +57,16 @@ pub(crate) enum PendingDecl<'ra> { Pending, } +enum ImportResolutionKind<'ra> { + Single(PerNS>), + Glob(Vec<(Decl<'ra>, BindingKey, Span /* orig_ident_span */)>), +} + +struct ImportResolution<'ra> { + kind: ImportResolutionKind<'ra>, + imported_module: ModuleOrUniformRoot<'ra>, +} + impl<'ra> PendingDecl<'ra> { pub(crate) fn decl(self) -> Option> { match self { @@ -442,7 +452,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && (vis == import.vis || max_vis.get().is_none_or(|max_vis| vis.greater_than(max_vis, self.tcx))) { - max_vis.set_unchecked(Some(vis)) + // `set` can't fail because this can only happen during "write_import_resolutions" + max_vis.set(Some(vis), self) } self.arenas.alloc_decl(DeclData { @@ -559,7 +570,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && glob_decl.ambiguity.get().is_none() { // Do not lose glob ambiguities when re-fetching the glob. - glob_decl.ambiguity.set_unchecked(Some((old_ambig, true))); + glob_decl.ambiguity.set(Some((old_ambig, true)), self); } glob_decl } else if glob_decl.res() != old_glob_decl.res() { @@ -567,7 +578,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { || self.is_rustybuzz_0_4_0(old_glob_decl, glob_decl) || self.is_pdf_0_9_0(old_glob_decl, glob_decl) || self.is_net2_0_2_39(old_glob_decl, glob_decl); - old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, warning))); + old_glob_decl.ambiguity.set(Some((glob_decl, warning)), self); old_glob_decl } else if let old_vis = old_glob_decl.vis() && let vis = glob_decl.vis() @@ -576,17 +587,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // We are glob-importing the same item but with a different visibility. // All visibilities here are ordered because all of them are ancestors of `module`. if vis.greater_than(old_vis, self.tcx) { - old_glob_decl.ambiguity_vis_max.set_unchecked(Some(glob_decl)); + old_glob_decl.ambiguity_vis_max.set(Some(glob_decl), self); } else if let old_min_vis = old_glob_decl.min_vis() && old_min_vis != vis && old_min_vis.greater_than(vis, self.tcx) { - old_glob_decl.ambiguity_vis_min.set_unchecked(Some(glob_decl)); + old_glob_decl.ambiguity_vis_min.set(Some(glob_decl), self); } old_glob_decl } else if glob_decl.is_ambiguity_recursive() && !old_glob_decl.is_ambiguity_recursive() { // Overwriting a non-ambiguous glob import with an ambiguous glob import. - old_glob_decl.ambiguity.set_unchecked(Some((glob_decl, true))); + old_glob_decl.ambiguity.set(Some((glob_decl, true)), self); old_glob_decl } else { old_glob_decl @@ -613,7 +624,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // because they can be fetched by glob imports from those modules, and bring traits // into scope both directly and through glob imports. let key = BindingKey::new_disambiguated(ident, ns, || { - module.underscore_disambiguator.update_unchecked(|d| d + 1); + module.underscore_disambiguator.update(self, |d| d + 1); module.underscore_disambiguator.get() }); self.update_local_resolution(module, key, orig_ident_span, |this, resolution| { @@ -650,7 +661,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let (binding, t) = { let resolution = &mut *self .resolution_or_default(module.to_module(), key, orig_ident_span) - .borrow_mut_unchecked(); + .borrow_mut(self); let old_decl = resolution.determined_decl(); let old_vis = old_decl.map(|d| d.vis()); @@ -665,7 +676,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } }; - let Ok(glob_importers) = module.glob_importers.try_borrow_mut_unchecked() else { + let Ok(glob_importers) = module.glob_importers.try_borrow_mut(self) else { return t; }; @@ -727,11 +738,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Import resolution // - // This is a fixed-point algorithm. We resolve imports until our efforts - // are stymied by an unresolved import; then we bail out of the current - // module and continue. We terminate successfully once no more imports - // remain or unsuccessfully when no forward progress in resolving imports - // is made. + // This is a batched fixed-point algorithm. Each import is resolved in + // isolation, with any resolutions collected for later. + // After a full pass over the current set of `indeterminate_imports`, + // the collected resolutions are committed together. The process + // repeats until either no imports remain or no further progress can + // be made. /// Resolves all imports for the crate. This method performs the fixed- /// point iteration. @@ -741,16 +753,125 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { while indeterminate_count < prev_indeterminate_count { prev_indeterminate_count = indeterminate_count; indeterminate_count = 0; + let mut resolutions = Vec::new(); self.assert_speculative = true; for import in mem::take(&mut self.indeterminate_imports) { - let import_indeterminate_count = self.cm().resolve_import(import); + let (resolution, import_indeterminate_count) = self.cm().resolve_import(import); indeterminate_count += import_indeterminate_count; match import_indeterminate_count { 0 => self.determined_imports.push(import), _ => self.indeterminate_imports.push(import), } + if let Some(resolution) = resolution { + resolutions.push((import, resolution)); + } } self.assert_speculative = false; + self.write_import_resolutions(resolutions); + } + } + + fn write_import_resolutions( + &mut self, + import_resolutions: Vec<(Import<'ra>, ImportResolution<'ra>)>, + ) { + for (import, resolution) in &import_resolutions { + let ImportResolution { imported_module, .. } = resolution; + import.imported_module.set(Some(*imported_module), self); + + if import.is_glob() + && let ModuleOrUniformRoot::Module(module) = imported_module + && import.parent_scope.module != *module + && module.is_local() + { + module.glob_importers.borrow_mut(self).push(*import); + } + } + + for (import, resolution) in import_resolutions { + let ImportResolution { imported_module, kind: resolution_kind } = resolution; + + match (&import.kind, resolution_kind) { + ( + ImportKind::Single { target, decls, .. }, + ImportResolutionKind::Single(import_decls), + ) => { + self.per_ns(|this, ns| { + match import_decls[ns] { + PendingDecl::Ready(Some(import_decl)) => { + if import_decl.is_assoc_item() + && !this.tcx.features().import_trait_associated_functions() + { + feature_err( + this.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + this.plant_decl_into_local_module( + IdentKey::new(*target), + target.span, + ns, + import_decl, + ); + decls[ns].set(PendingDecl::Ready(Some(import_decl)), this); + } + PendingDecl::Ready(None) => { + // Don't remove underscores from `single_imports`, they were never added. + if target.name != kw::Underscore { + let key = BindingKey::new(IdentKey::new(*target), ns); + this.update_local_resolution( + import.parent_scope.module.expect_local(), + key, + target.span, + |_, resolution| { + resolution.single_imports.swap_remove(&import); + }, + ); + } + decls[ns].set(PendingDecl::Ready(None), this); + } + PendingDecl::Pending => {} + } + }); + } + (ImportKind::Glob { id, .. }, ImportResolutionKind::Glob(imported_decls)) => { + let ModuleOrUniformRoot::Module(module) = imported_module else { + self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); + continue; + }; + + if module.is_trait() && !self.tcx.features().import_trait_associated_functions() + { + feature_err( + self.tcx.sess, + sym::import_trait_associated_functions, + import.span, + "`use` associated items of traits is unstable", + ) + .emit(); + } + + for (binding, key, orig_ident_span) in imported_decls { + let import_decl = self.new_import_decl(binding, import); + let _ = self + .try_plant_decl_into_local_module( + key.ident, + orig_ident_span, + key.ns, + import_decl, + ) + .expect("planting a glob cannot fail"); + } + + self.record_partial_res(*id, PartialRes::new(module.res().unwrap())); + } + + // Something weird happened, which shouldn't have happened. + _ => unreachable!("mismatched import and resolution kind"), + } } } @@ -1085,12 +1206,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// - `0` means its resolution is determined. /// - Other values mean that indeterminate exists under certain namespaces. /// - /// Meanwhile, if resolve successful, the resolved bindings are written - /// into the module. - fn resolve_import<'r>(mut self: CmResolver<'r, 'ra, 'tcx>, import: Import<'ra>) -> usize { + /// Meanwhile, if resolution is successful, its result is returned. + fn resolve_import<'r>( + mut self: CmResolver<'r, 'ra, 'tcx>, + import: Import<'ra>, + ) -> (Option>, usize) { debug!( - "(resolving import for module) resolving import `{}::...` in `{}`", + "(resolving import for module) resolving import `{}::{}` in `{}`", Segment::names_to_string(&import.module_path), + import_kind_to_string(&import.kind), module_to_string(import.parent_scope.module).unwrap_or_else(|| "???".to_string()), ); let module = if let Some(module) = import.imported_module.get() { @@ -1105,21 +1229,24 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { match path_res { PathResult::Module(module) => module, - PathResult::Indeterminate => return 3, - PathResult::NonModule(..) | PathResult::Failed { .. } => return 0, + PathResult::Indeterminate => return (None, 3), + PathResult::NonModule(..) | PathResult::Failed { .. } => return (None, 0), } }; - import.imported_module.set_unchecked(Some(module)); - let (source, target, bindings) = match import.kind { - ImportKind::Single { source, target, ref decls, .. } => (source, target, decls), + let (source, bindings) = match import.kind { + ImportKind::Single { source, ref decls, .. } => (source, decls), ImportKind::Glob { .. } => { - self.get_mut_unchecked().resolve_glob_import(import); - return 0; + let import_resolution = ImportResolution { + imported_module: module, + kind: self.resolve_glob_import(import, module), + }; + return (Some(import_resolution), 0); } _ => unreachable!(), }; + let mut import_decls = PerNS::default(); let mut indeterminate_count = 0; self.per_ns_cm(|mut this, ns| { if bindings[ns].get() != PendingDecl::Pending { @@ -1132,54 +1259,26 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &import.parent_scope, Some(import), ); - let parent = import.parent_scope.module; - let binding = match binding_result { + let pending_decl = match binding_result { Ok(binding) => { - if binding.is_assoc_item() - && !this.tcx.features().import_trait_associated_functions() - { - feature_err( - this.tcx.sess, - sym::import_trait_associated_functions, - import.span, - "`use` associated items of traits is unstable", - ) - .emit(); - } // We need the `target`, `source` can be extracted. let import_decl = this.new_import_decl(binding, import); - this.get_mut_unchecked().plant_decl_into_local_module( - IdentKey::new(target), - target.span, - ns, - import_decl, - ); PendingDecl::Ready(Some(import_decl)) } - Err(Determinacy::Determined) => { - // Don't remove underscores from `single_imports`, they were never added. - if target.name != kw::Underscore { - let key = BindingKey::new(IdentKey::new(target), ns); - this.get_mut_unchecked().update_local_resolution( - parent.expect_local(), - key, - target.span, - |_, resolution| { - resolution.single_imports.swap_remove(&import); - }, - ); - } - PendingDecl::Ready(None) - } + Err(Determinacy::Determined) => PendingDecl::Ready(None), Err(Determinacy::Undetermined) => { indeterminate_count += 1; PendingDecl::Pending } }; - bindings[ns].set_unchecked(binding); + import_decls[ns] = pending_decl; }); + let import_resolution = ImportResolution { + imported_module: module, + kind: ImportResolutionKind::Single(import_decls), + }; - indeterminate_count + (Some(import_resolution), indeterminate_count) } /// Performs final import resolution, consistency checks and error reporting. @@ -1799,68 +1898,40 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { false } - fn resolve_glob_import(&mut self, import: Import<'ra>) { - // This function is only called for glob imports. - let ImportKind::Glob { id, .. } = import.kind else { unreachable!() }; + fn resolve_glob_import( + &self, + import: Import<'ra>, + imported_module: ModuleOrUniformRoot<'ra>, + ) -> ImportResolutionKind<'ra> { + let import_bindings = match imported_module { + ModuleOrUniformRoot::Module(module) if module != import.parent_scope.module => self + .resolutions(module) + .borrow() + .iter() + .filter_map(|(key, resolution)| { + let res = resolution.borrow(); + let decl = res.determined_decl()?; + let mut key = *key; + let scope = match key.ident.ctxt.update_unchecked(|ctxt| { + ctxt.reverse_glob_adjust(module.expansion, import.span) + }) { + Some(Some(def)) => self.expn_def_scope(def), + Some(None) => import.parent_scope.module, + None => return None, + }; + self.is_accessible_from(decl.vis(), scope).then_some(( + decl, + key, + res.orig_ident_span, + )) + }) + .collect::>(), - let ModuleOrUniformRoot::Module(module) = import.imported_module.get().unwrap() else { - self.dcx().emit_err(CannotGlobImportAllCrates { span: import.span }); - return; + // Errors are reported in `write_imports_resolutions` + _ => vec![], }; - if module.is_trait() && !self.tcx.features().import_trait_associated_functions() { - feature_err( - self.tcx.sess, - sym::import_trait_associated_functions, - import.span, - "`use` associated items of traits is unstable", - ) - .emit(); - } - - if module == import.parent_scope.module { - return; - } - - // Add to module's glob_importers - if module.is_local() { - module.glob_importers.borrow_mut_unchecked().push(import); - } - - // Ensure that `resolutions` isn't borrowed during `try_define`, - // since it might get updated via a glob cycle. - let bindings = self - .resolutions(module) - .borrow() - .iter() - .filter_map(|(key, resolution)| { - let resolution = resolution.borrow(); - resolution.determined_decl().map(|decl| (*key, decl, resolution.orig_ident_span)) - }) - .collect::>(); - for (mut key, binding, orig_ident_span) in bindings { - let scope = - match key.ident.ctxt.update_unchecked(|ctxt| { - ctxt.reverse_glob_adjust(module.expansion, import.span) - }) { - Some(Some(def)) => self.expn_def_scope(def), - Some(None) => import.parent_scope.module, - None => continue, - }; - if self.is_accessible_from(binding.vis(), scope) { - let import_decl = self.new_import_decl(binding, import); - self.try_plant_decl_into_local_module( - key.ident, - orig_ident_span, - key.ns, - import_decl, - ) - .expect("planting a glob cannot fail"); - } - } - - // Record the destination of this import - self.record_partial_res(id, PartialRes::new(module.res().unwrap())); + ImportResolutionKind::Glob(import_bindings) } // Miscellaneous post-processing, including recording re-exports, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 9af55565d30b7..090722c496fd8 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2868,16 +2868,10 @@ mod ref_mut { #[track_caller] pub(crate) fn get_mut(&mut self) -> &mut T { match self.mutable { - false => panic!("Can't mutably borrow speculative resolver"), + false => panic!("can't mutably borrow speculative resolver"), true => self.p, } } - - /// Returns a mutable reference to the inner value without checking if - /// it's in a mutable state. - pub(crate) fn get_mut_unchecked(&mut self) -> &mut T { - self.p - } } /// A wrapper around a [`Cell`] that only allows mutation based on a condition in the resolver. @@ -2901,12 +2895,12 @@ mod ref_mut { self.0.get() } - pub(crate) fn update_unchecked(&self, f: impl FnOnce(T) -> T) + pub(crate) fn update<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>, f: impl FnOnce(T) -> T) where T: Copy, { let old = self.get(); - self.set_unchecked(f(old)); + self.set(f(old), r); } } @@ -2915,7 +2909,10 @@ mod ref_mut { CmCell(Cell::new(value)) } - pub(crate) fn set_unchecked(&self, val: T) { + pub(crate) fn set<'ra, 'tcx>(&self, val: T, r: &Resolver<'ra, 'tcx>) { + if r.assert_speculative { + panic!("not allowed to mutate a `CmCell` during speculative resolution") + } self.0.set(val); } @@ -2941,16 +2938,26 @@ mod ref_mut { #[track_caller] pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> RefMut<'_, T> { if r.assert_speculative { - panic!("Not allowed to mutably borrow a CmRefCell during speculative resolution"); + panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution"); } - self.borrow_mut_unchecked() + self.0.borrow_mut() } - #[track_caller] pub(crate) fn try_borrow_mut_unchecked(&self) -> Result, BorrowMutError> { self.0.try_borrow_mut() } + #[track_caller] + pub(crate) fn try_borrow_mut<'ra, 'tcx>( + &self, + r: &Resolver<'ra, 'tcx>, + ) -> Result, BorrowMutError> { + if r.assert_speculative { + panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution"); + } + self.0.try_borrow_mut() + } + #[track_caller] pub(crate) fn borrow(&self) -> Ref<'_, T> { self.0.borrow() @@ -2960,7 +2967,7 @@ mod ref_mut { impl CmRefCell { pub(crate) fn take<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> T { if r.assert_speculative { - panic!("Not allowed to mutate a CmRefCell during speculative resolution"); + panic!("not allowed to mutate a CmRefCell during speculative resolution"); } self.0.take() } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs index 2ed7aedecffef..453866e93b965 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/as_place.rs @@ -1,7 +1,7 @@ //! MIR lowering for places use hir_def::FunctionId; -use rustc_type_ir::inherent::{Region as _, Ty as _}; +use rustc_type_ir::inherent::Region as _; use super::*; use crate::{ diff --git a/tests/ui/imports/ambiguous-14.rs b/tests/ui/imports/ambiguous-14.rs index ba2d7dc4e0166..b7203a2cb6fb4 100644 --- a/tests/ui/imports/ambiguous-14.rs +++ b/tests/ui/imports/ambiguous-14.rs @@ -22,5 +22,4 @@ mod g { fn main() { g::foo(); //~^ ERROR `foo` is ambiguous - //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } diff --git a/tests/ui/imports/ambiguous-14.stderr b/tests/ui/imports/ambiguous-14.stderr index 2ca10d2d6a848..327dd075945a4 100644 --- a/tests/ui/imports/ambiguous-14.stderr +++ b/tests/ui/imports/ambiguous-14.stderr @@ -1,4 +1,4 @@ -error: `foo` is ambiguous +error[E0659]: `foo` is ambiguous --> $DIR/ambiguous-14.rs:23:8 | LL | g::foo(); @@ -6,44 +6,18 @@ LL | g::foo(); | = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the function imported here - --> $DIR/ambiguous-14.rs:18:13 + --> $DIR/ambiguous-14.rs:13:13 | LL | pub use a::*; | ^^^^ = help: consider adding an explicit import of `foo` to disambiguate note: `foo` could also refer to the function imported here - --> $DIR/ambiguous-14.rs:19:13 + --> $DIR/ambiguous-14.rs:14:13 | -LL | pub use f::*; +LL | pub use b::*; | ^^^^ = help: consider adding an explicit import of `foo` to disambiguate - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default error: aborting due to 1 previous error -Future incompatibility report: Future breakage diagnostic: -error: `foo` is ambiguous - --> $DIR/ambiguous-14.rs:23:8 - | -LL | g::foo(); - | ^^^ ambiguous name - | - = note: ambiguous because of multiple glob imports of a name in the same module -note: `foo` could refer to the function imported here - --> $DIR/ambiguous-14.rs:18:13 - | -LL | pub use a::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate -note: `foo` could also refer to the function imported here - --> $DIR/ambiguous-14.rs:19:13 - | -LL | pub use f::*; - | ^^^^ - = help: consider adding an explicit import of `foo` to disambiguate - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/ambiguous-9.rs b/tests/ui/imports/ambiguous-9.rs index 58796031bf18f..0e60a2929c024 100644 --- a/tests/ui/imports/ambiguous-9.rs +++ b/tests/ui/imports/ambiguous-9.rs @@ -4,16 +4,16 @@ pub mod dsl { mod range { pub fn date_range() {} } - pub use self::range::*; //~ WARNING ambiguous glob re-exports + pub use self::range::*; use super::prelude::*; } pub mod prelude { mod t { - pub fn date_range() {} + pub fn date_range() {} } - pub use self::t::*; //~ WARNING ambiguous glob re-exports - pub use super::dsl::*; + pub use self::t::*; + pub use super::dsl::*; //~ WARNING ambiguous glob re-exports } use dsl::*; @@ -22,5 +22,4 @@ use prelude::*; fn main() { date_range(); //~^ ERROR `date_range` is ambiguous - //~| ERROR `date_range` is ambiguous } diff --git a/tests/ui/imports/ambiguous-9.stderr b/tests/ui/imports/ambiguous-9.stderr index b6e4c30a8d410..0ffbeb7c89509 100644 --- a/tests/ui/imports/ambiguous-9.stderr +++ b/tests/ui/imports/ambiguous-9.stderr @@ -6,56 +6,28 @@ LL | date_range(); | = note: ambiguous because of multiple glob imports of a name in the same module note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:19:5 + --> $DIR/ambiguous-9.rs:16:13 | -LL | use dsl::*; - | ^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate -note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:20:5 - | -LL | use prelude::*; - | ^^^^^^^^^^ - = help: consider adding an explicit import of `date_range` to disambiguate - -error[E0659]: `date_range` is ambiguous - --> $DIR/ambiguous-9.rs:23:5 - | -LL | date_range(); - | ^^^^^^^^^^ ambiguous name - | - = note: ambiguous because of multiple glob imports of a name in the same module -note: `date_range` could refer to the function imported here - --> $DIR/ambiguous-9.rs:7:13 - | -LL | pub use self::range::*; - | ^^^^^^^^^^^^^^ +LL | pub use super::dsl::*; + | ^^^^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate note: `date_range` could also refer to the function imported here - --> $DIR/ambiguous-9.rs:8:9 + --> $DIR/ambiguous-9.rs:15:13 | -LL | use super::prelude::*; - | ^^^^^^^^^^^^^^^^^ +LL | pub use self::t::*; + | ^^^^^^^^^^ = help: consider adding an explicit import of `date_range` to disambiguate warning: ambiguous glob re-exports - --> $DIR/ambiguous-9.rs:7:13 - | -LL | pub use self::range::*; - | ^^^^^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here -LL | use super::prelude::*; - | ----------------- but the name `date_range` in the value namespace is also re-exported here - | - = note: `#[warn(ambiguous_glob_reexports)]` on by default - -warning: ambiguous glob re-exports - --> $DIR/ambiguous-9.rs:15:13 + --> $DIR/ambiguous-9.rs:16:13 | LL | pub use self::t::*; - | ^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here + | ---------- but the name `date_range` in the value namespace is also re-exported here LL | pub use super::dsl::*; - | ------------- but the name `date_range` in the value namespace is also re-exported here + | ^^^^^^^^^^^^^ the name `date_range` in the value namespace is first re-exported here + | + = note: `#[warn(ambiguous_glob_reexports)]` on by default -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/imports/duplicate.rs b/tests/ui/imports/duplicate.rs index 0a652889ca8ad..be089dbf5a4af 100644 --- a/tests/ui/imports/duplicate.rs +++ b/tests/ui/imports/duplicate.rs @@ -35,7 +35,6 @@ fn main() { f::foo(); //~ ERROR `foo` is ambiguous g::foo(); //~^ ERROR `foo` is ambiguous - //~| WARNING this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } mod ambiguous_module_errors { diff --git a/tests/ui/imports/duplicate.stderr b/tests/ui/imports/duplicate.stderr index f02d35b1d28ce..7bff44109e40b 100644 --- a/tests/ui/imports/duplicate.stderr +++ b/tests/ui/imports/duplicate.stderr @@ -9,20 +9,20 @@ LL | use crate::a::foo; = note: `foo` must be defined only once in the value namespace of this module error[E0659]: `foo` is ambiguous - --> $DIR/duplicate.rs:48:15 + --> $DIR/duplicate.rs:47:15 | LL | use self::foo::bar; | ^^^ ambiguous name | = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the module imported here - --> $DIR/duplicate.rs:45:9 + --> $DIR/duplicate.rs:44:9 | LL | use self::m1::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate note: `foo` could also refer to the module imported here - --> $DIR/duplicate.rs:46:9 + --> $DIR/duplicate.rs:45:9 | LL | use self::m2::*; | ^^^^^^^^^^^ @@ -49,26 +49,6 @@ LL | pub use crate::b::*; = help: consider adding an explicit import of `foo` to disambiguate error[E0659]: `foo` is ambiguous - --> $DIR/duplicate.rs:51:9 - | -LL | foo::bar(); - | ^^^ ambiguous name - | - = note: ambiguous because of multiple glob imports of a name in the same module -note: `foo` could refer to the module imported here - --> $DIR/duplicate.rs:45:9 - | -LL | use self::m1::*; - | ^^^^^^^^^^^ - = help: consider adding an explicit import of `foo` to disambiguate -note: `foo` could also refer to the module imported here - --> $DIR/duplicate.rs:46:9 - | -LL | use self::m2::*; - | ^^^^^^^^^^^ - = help: consider adding an explicit import of `foo` to disambiguate - -error: `foo` is ambiguous --> $DIR/duplicate.rs:36:8 | LL | g::foo(); @@ -76,46 +56,39 @@ LL | g::foo(); | = note: ambiguous because of multiple glob imports of a name in the same module note: `foo` could refer to the function imported here - --> $DIR/duplicate.rs:29:13 + --> $DIR/duplicate.rs:24:13 | LL | pub use crate::a::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate note: `foo` could also refer to the function imported here - --> $DIR/duplicate.rs:30:13 + --> $DIR/duplicate.rs:25:13 | -LL | pub use crate::f::*; +LL | pub use crate::b::*; | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default - -error: aborting due to 5 previous errors -Some errors have detailed explanations: E0252, E0659. -For more information about an error, try `rustc --explain E0252`. -Future incompatibility report: Future breakage diagnostic: -error: `foo` is ambiguous - --> $DIR/duplicate.rs:36:8 +error[E0659]: `foo` is ambiguous + --> $DIR/duplicate.rs:50:9 | -LL | g::foo(); - | ^^^ ambiguous name +LL | foo::bar(); + | ^^^ ambiguous name | = note: ambiguous because of multiple glob imports of a name in the same module -note: `foo` could refer to the function imported here - --> $DIR/duplicate.rs:29:13 +note: `foo` could refer to the module imported here + --> $DIR/duplicate.rs:44:9 | -LL | pub use crate::a::*; - | ^^^^^^^^^^^ +LL | use self::m1::*; + | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate -note: `foo` could also refer to the function imported here - --> $DIR/duplicate.rs:30:13 +note: `foo` could also refer to the module imported here + --> $DIR/duplicate.rs:45:9 | -LL | pub use crate::f::*; - | ^^^^^^^^^^^ +LL | use self::m2::*; + | ^^^^^^^^^^^ = help: consider adding an explicit import of `foo` to disambiguate - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #114095 - = note: `#[deny(ambiguous_glob_imports)]` (part of `#[deny(future_incompatible)]`) on by default +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0252, E0659. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/imports/import-loop-2.rs b/tests/ui/imports/import-loop-2.rs index 42f9a07fff389..af5c6509d38b6 100644 --- a/tests/ui/imports/import-loop-2.rs +++ b/tests/ui/imports/import-loop-2.rs @@ -1,9 +1,9 @@ mod a { - pub use crate::b::x; + pub use crate::b::x; //~ ERROR unresolved import `crate::b::x` } mod b { - pub use crate::a::x; //~ ERROR unresolved import `crate::a::x` + pub use crate::a::x; fn main() { let y = x; } } diff --git a/tests/ui/imports/import-loop-2.stderr b/tests/ui/imports/import-loop-2.stderr index 2ef40c4e21829..dfa7cf35eaac2 100644 --- a/tests/ui/imports/import-loop-2.stderr +++ b/tests/ui/imports/import-loop-2.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `crate::a::x` - --> $DIR/import-loop-2.rs:6:13 +error[E0432]: unresolved import `crate::b::x` + --> $DIR/import-loop-2.rs:2:13 | -LL | pub use crate::a::x; - | ^^^^^^^^^^^ no `x` in `a` +LL | pub use crate::b::x; + | ^^^^^^^^^^^ no `x` in `b` error: aborting due to 1 previous error diff --git a/tests/ui/imports/import4.rs b/tests/ui/imports/import4.rs index f670cc06201c0..76a9887534c34 100644 --- a/tests/ui/imports/import4.rs +++ b/tests/ui/imports/import4.rs @@ -1,4 +1,4 @@ -mod a { pub use crate::b::foo; } -mod b { pub use crate::a::foo; } //~ ERROR unresolved import `crate::a::foo` +mod a { pub use crate::b::foo; } //~ ERROR unresolved import `crate::b::foo` +mod b { pub use crate::a::foo; } fn main() { println!("loop"); } diff --git a/tests/ui/imports/import4.stderr b/tests/ui/imports/import4.stderr index 4faa5f0520a9d..07fdc6a3d0ced 100644 --- a/tests/ui/imports/import4.stderr +++ b/tests/ui/imports/import4.stderr @@ -1,8 +1,8 @@ -error[E0432]: unresolved import `crate::a::foo` - --> $DIR/import4.rs:2:17 +error[E0432]: unresolved import `crate::b::foo` + --> $DIR/import4.rs:1:17 | -LL | mod b { pub use crate::a::foo; } - | ^^^^^^^^^^^^^ no `foo` in `a` +LL | mod a { pub use crate::b::foo; } + | ^^^^^^^^^^^^^ no `foo` in `b` error: aborting due to 1 previous error diff --git a/tests/ui/imports/same-res-ambigious.fail.stderr b/tests/ui/imports/same-res-ambigious.fail.stderr index dfd7c5a5f94e0..aeeff5f2e2ad8 100644 --- a/tests/ui/imports/same-res-ambigious.fail.stderr +++ b/tests/ui/imports/same-res-ambigious.fail.stderr @@ -1,5 +1,5 @@ error[E0603]: derive macro `Embed` is private - --> $DIR/same-res-ambigious.rs:8:28 + --> $DIR/same-res-ambigious.rs:7:28 | LL | #[derive(ambigious_extern::Embed)] | ^^^^^ private derive macro diff --git a/tests/ui/imports/same-res-ambigious.pass.stderr b/tests/ui/imports/same-res-ambigious.pass.stderr new file mode 100644 index 0000000000000..a1d75a4387f66 --- /dev/null +++ b/tests/ui/imports/same-res-ambigious.pass.stderr @@ -0,0 +1,20 @@ +error[E0603]: derive macro `Embed` is private + --> $DIR/same-res-ambigious.rs:7:28 + | +LL | #[derive(ambigious_extern::Embed)] + | ^^^^^ private derive macro + | +note: the derive macro `Embed` is defined here + --> $DIR/auxiliary/same-res-ambigious-extern.rs:11:9 + | +LL | pub use RustEmbed as Embed; + | ^^^^^^^^^ +help: import `Embed` directly + | +LL - #[derive(ambigious_extern::Embed)] +LL + #[derive(same_res_ambigious_extern_macro::RustEmbed)] + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/same-res-ambigious.rs b/tests/ui/imports/same-res-ambigious.rs index b5c13a15b7c9c..52a40450b942f 100644 --- a/tests/ui/imports/same-res-ambigious.rs +++ b/tests/ui/imports/same-res-ambigious.rs @@ -1,11 +1,10 @@ //@ edition: 2018 //@ revisions: fail pass -//@[pass] check-pass //@[pass] aux-crate: ambigious_extern=same-res-ambigious-extern.rs //@[fail] aux-crate: ambigious_extern=same-res-ambigious-extern-fail.rs // see https://github.com/rust-lang/rust/pull/147196 -#[derive(ambigious_extern::Embed)] //[fail]~ ERROR: derive macro `Embed` is private +#[derive(ambigious_extern::Embed)] //~ ERROR: derive macro `Embed` is private struct Foo{} fn main(){} diff --git a/tests/ui/privacy/privacy1.stderr b/tests/ui/privacy/privacy1.stderr index 5d1e003c703b4..22cc16b12af79 100644 --- a/tests/ui/privacy/privacy1.stderr +++ b/tests/ui/privacy/privacy1.stderr @@ -34,18 +34,6 @@ note: the module `baz` is defined here LL | mod baz { | ^^^^^^^ -error[E0603]: module `baz` is private - --> $DIR/privacy1.rs:148:18 - | -LL | use bar::baz; - | ^^^ private module - | -note: the module `baz` is defined here - --> $DIR/privacy1.rs:57:5 - | -LL | mod baz { - | ^^^^^^^ - error[E0603]: module `i` is private --> $DIR/privacy1.rs:172:20 | @@ -60,6 +48,18 @@ note: the module `i` is defined here LL | mod i { | ^^^^^ +error[E0603]: module `baz` is private + --> $DIR/privacy1.rs:148:18 + | +LL | use bar::baz; + | ^^^ private module + | +note: the module `baz` is defined here + --> $DIR/privacy1.rs:57:5 + | +LL | mod baz { + | ^^^^^^^ + error[E0603]: module `baz` is private --> $DIR/privacy1.rs:111:21 | From b09dbec01db64a823f3d1b96cc8a8b1f89dd0a83 Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Tue, 24 Feb 2026 18:02:09 +0100 Subject: [PATCH 18/33] hack for RustEmbed with updated test --- compiler/rustc_resolve/src/imports.rs | 48 ++++++++++++++++--- compiler/rustc_span/src/symbol.rs | 2 + .../ui/imports/same-res-ambigious.fail.stderr | 20 -------- .../ui/imports/same-res-ambigious.pass.stderr | 20 -------- tests/ui/imports/same-res-ambigious.rs | 3 +- 5 files changed, 46 insertions(+), 47 deletions(-) delete mode 100644 tests/ui/imports/same-res-ambigious.fail.stderr delete mode 100644 tests/ui/imports/same-res-ambigious.pass.stderr diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index bed025438c331..9e0f5c24d1101 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1934,6 +1934,38 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ImportResolutionKind::Glob(import_bindings) } + // Hack for the `rust_embed` regression observed in the crater run of #145108. + fn rust_embed_hack(&self, module: LocalModule<'ra>, decl: Decl<'ra>) -> bool { + // We are looking for this pattern: + // ```rust + // #[macro_use] + // extern crate rust_embed_impl; + // pub use rust_embed_impl::*; + // + // pub use RustEmbed as Embed; + // ``` + if let DeclKind::Import { source_decl, import } = decl.kind + // Check that `decl` is the re-export: "pub use RustEmbed as Embed;" + && let ImportKind::Single { source, .. } = import.kind + && source.name == sym::RustEmbed + // make sure that the import points to the #[macro_use] import + && let DeclKind::Import { import, .. } = source_decl.kind + && matches!(import.kind, ImportKind::MacroUse { .. }) + && self.macro_use_prelude.contains_key(&source.name) // and that the name actually exists in the macro_use_prelude + // Then check that `RustEmbed` exists in the modules Macro namespace. + && let Some(y_decl) = self + .resolution(module.to_module(), BindingKey::new(IdentKey::new(source), MacroNS)) + .and_then(|res| res.best_decl()) + // which comes from "pub use rust_embed_impl::*" + && y_decl.is_glob_import() + && y_decl.vis().is_public() + { + return true; + } + + false + } + // Miscellaneous post-processing, including recording re-exports, // reporting conflicts, and reporting unresolved imports. fn finalize_resolutions_in( @@ -1950,13 +1982,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let mut children = Vec::new(); let mut ambig_children = Vec::new(); - module.to_module().for_each_child(self, |_this, ident, orig_ident_span, _, binding| { - let res = binding.res().expect_non_local(); + module.to_module().for_each_child(self, |this, ident, orig_ident_span, _, decl| { + let res = decl.res().expect_non_local(); if res != def::Res::Err { + let vis = if this.rust_embed_hack(module, decl) { + Visibility::Public + } else { + decl.vis() + }; let ident = ident.orig(orig_ident_span); - let child = - |reexport_chain| ModChild { ident, res, vis: binding.vis(), reexport_chain }; - if let Some((ambig_binding1, ambig_binding2)) = binding.descent_to_ambiguity() { + let child = |reexport_chain| ModChild { ident, res, vis, reexport_chain }; + if let Some((ambig_binding1, ambig_binding2)) = decl.descent_to_ambiguity() { let main = child(ambig_binding1.reexport_chain()); let second = ModChild { ident, @@ -1966,7 +2002,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; ambig_children.push(AmbigModChild { main, second }) } else { - children.push(child(binding.reexport_chain())); + children.push(child(decl.reexport_chain())); } } }); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index fb433aef68cf8..86eea0bf303c6 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -294,6 +294,8 @@ symbols! { ResumeTy, Reverse, Rust, + // Temporary name for the rust_embed hack introduced in #145108 + RustEmbed, RustaceansAreAwesome, RwLock, RwLockReadGuard, diff --git a/tests/ui/imports/same-res-ambigious.fail.stderr b/tests/ui/imports/same-res-ambigious.fail.stderr deleted file mode 100644 index aeeff5f2e2ad8..0000000000000 --- a/tests/ui/imports/same-res-ambigious.fail.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0603]: derive macro `Embed` is private - --> $DIR/same-res-ambigious.rs:7:28 - | -LL | #[derive(ambigious_extern::Embed)] - | ^^^^^ private derive macro - | -note: the derive macro `Embed` is defined here - --> $DIR/auxiliary/same-res-ambigious-extern-fail.rs:16:9 - | -LL | pub use RustEmbed as Embed; - | ^^^^^^^^^ -help: import `Embed` directly - | -LL - #[derive(ambigious_extern::Embed)] -LL + #[derive(same_res_ambigious_extern_macro::RustEmbed)] - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/same-res-ambigious.pass.stderr b/tests/ui/imports/same-res-ambigious.pass.stderr deleted file mode 100644 index a1d75a4387f66..0000000000000 --- a/tests/ui/imports/same-res-ambigious.pass.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0603]: derive macro `Embed` is private - --> $DIR/same-res-ambigious.rs:7:28 - | -LL | #[derive(ambigious_extern::Embed)] - | ^^^^^ private derive macro - | -note: the derive macro `Embed` is defined here - --> $DIR/auxiliary/same-res-ambigious-extern.rs:11:9 - | -LL | pub use RustEmbed as Embed; - | ^^^^^^^^^ -help: import `Embed` directly - | -LL - #[derive(ambigious_extern::Embed)] -LL + #[derive(same_res_ambigious_extern_macro::RustEmbed)] - | - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0603`. diff --git a/tests/ui/imports/same-res-ambigious.rs b/tests/ui/imports/same-res-ambigious.rs index 52a40450b942f..0bfd10f18ada8 100644 --- a/tests/ui/imports/same-res-ambigious.rs +++ b/tests/ui/imports/same-res-ambigious.rs @@ -1,10 +1,11 @@ +//@ check-pass //@ edition: 2018 //@ revisions: fail pass //@[pass] aux-crate: ambigious_extern=same-res-ambigious-extern.rs //@[fail] aux-crate: ambigious_extern=same-res-ambigious-extern-fail.rs // see https://github.com/rust-lang/rust/pull/147196 -#[derive(ambigious_extern::Embed)] //~ ERROR: derive macro `Embed` is private +#[derive(ambigious_extern::Embed)] struct Foo{} fn main(){} From fe7c7a11a7b450504e9674518fcf6ddb0e581a2f Mon Sep 17 00:00:00 2001 From: LorrensP-2158466 Date: Fri, 5 Jun 2026 16:58:54 +0200 Subject: [PATCH 19/33] Add extra line in generator script for `core_arch` that unambiguously imports the correct traits for `aarch64`. + run the generator to apply change. --- library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs | 1 + library/stdarch/crates/stdarch-gen-arm/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 6c6a2476a43fd..e1157f3440cfb 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -12,6 +12,7 @@ use stdarch_test::assert_instr; use super::*; use crate::core_arch::arch::aarch64::*; +use super::{AsSigned, AsUnsigned}; #[doc = "Absolute difference"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svabd[_f32]_m)"] diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index b7e2aa416fb59..717a1707aafe3 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -166,7 +166,7 @@ use super::*;{uses_neon} "#, uses_neon = if generated_input.ctx.uses_neon_types { - "\nuse crate::core_arch::arch::aarch64::*;" + "\nuse crate::core_arch::arch::aarch64::*;\nuse super::{AsSigned, AsUnsigned};" } else { "" }, From d21aa1c6f408299d5f7634be413c0a901c63a680 Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 6 Jun 2026 20:30:55 +0200 Subject: [PATCH 20/33] move batch --- .../issue-19037.rs => derives/clone-copy/clone-ref-to-dst.rs} | 0 .../dyn-incompat-const-slice.rs} | 0 .../dyn-incompat-const-slice.stderr} | 0 .../manual-fn-impl-lifetime-elision.rs} | 0 .../trait-bounds/hrtb-closure-lifetime-infer.rs} | 0 .../trait-bounds/hrtb-unused-lifetime.rs} | 0 tests/ui/{issues/issue-19367.rs => match/match-field-reassign.rs} | 0 .../issue-19086.rs => pattern/struct-variant-as-tuple-variant.rs} | 0 .../struct-variant-as-tuple-variant.stderr} | 0 .../issue-19811-escape-unicode.rs => str/char-escape-unicode.rs} | 0 .../error-reporting/incompatible-method-multiline.rs} | 0 .../error-reporting/incompatible-method-multiline.stderr} | 0 .../object/inherent-method-on-dyn-with-rc-coercion.rs} | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-19037.rs => derives/clone-copy/clone-ref-to-dst.rs} (100%) rename tests/ui/{issues/issue-19380.rs => dyn-compatibility/dyn-incompat-const-slice.rs} (100%) rename tests/ui/{issues/issue-19380.stderr => dyn-compatibility/dyn-incompat-const-slice.stderr} (100%) rename tests/ui/{issues/issue-19982.rs => fn_traits/manual-fn-impl-lifetime-elision.rs} (100%) rename tests/ui/{issues/issue-19135.rs => higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs} (100%) rename tests/ui/{issues/issue-19098.rs => higher-ranked/trait-bounds/hrtb-unused-lifetime.rs} (100%) rename tests/ui/{issues/issue-19367.rs => match/match-field-reassign.rs} (100%) rename tests/ui/{issues/issue-19086.rs => pattern/struct-variant-as-tuple-variant.rs} (100%) rename tests/ui/{issues/issue-19086.stderr => pattern/struct-variant-as-tuple-variant.stderr} (100%) rename tests/ui/{issues/issue-19811-escape-unicode.rs => str/char-escape-unicode.rs} (100%) rename tests/ui/{issues/issue-21332.rs => traits/error-reporting/incompatible-method-multiline.rs} (100%) rename tests/ui/{issues/issue-21332.stderr => traits/error-reporting/incompatible-method-multiline.stderr} (100%) rename tests/ui/{issues/issue-19404.rs => traits/object/inherent-method-on-dyn-with-rc-coercion.rs} (100%) diff --git a/tests/ui/issues/issue-19037.rs b/tests/ui/derives/clone-copy/clone-ref-to-dst.rs similarity index 100% rename from tests/ui/issues/issue-19037.rs rename to tests/ui/derives/clone-copy/clone-ref-to-dst.rs diff --git a/tests/ui/issues/issue-19380.rs b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs similarity index 100% rename from tests/ui/issues/issue-19380.rs rename to tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs diff --git a/tests/ui/issues/issue-19380.stderr b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr similarity index 100% rename from tests/ui/issues/issue-19380.stderr rename to tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr diff --git a/tests/ui/issues/issue-19982.rs b/tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs similarity index 100% rename from tests/ui/issues/issue-19982.rs rename to tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs diff --git a/tests/ui/issues/issue-19135.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs similarity index 100% rename from tests/ui/issues/issue-19135.rs rename to tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs diff --git a/tests/ui/issues/issue-19098.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs similarity index 100% rename from tests/ui/issues/issue-19098.rs rename to tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs diff --git a/tests/ui/issues/issue-19367.rs b/tests/ui/match/match-field-reassign.rs similarity index 100% rename from tests/ui/issues/issue-19367.rs rename to tests/ui/match/match-field-reassign.rs diff --git a/tests/ui/issues/issue-19086.rs b/tests/ui/pattern/struct-variant-as-tuple-variant.rs similarity index 100% rename from tests/ui/issues/issue-19086.rs rename to tests/ui/pattern/struct-variant-as-tuple-variant.rs diff --git a/tests/ui/issues/issue-19086.stderr b/tests/ui/pattern/struct-variant-as-tuple-variant.stderr similarity index 100% rename from tests/ui/issues/issue-19086.stderr rename to tests/ui/pattern/struct-variant-as-tuple-variant.stderr diff --git a/tests/ui/issues/issue-19811-escape-unicode.rs b/tests/ui/str/char-escape-unicode.rs similarity index 100% rename from tests/ui/issues/issue-19811-escape-unicode.rs rename to tests/ui/str/char-escape-unicode.rs diff --git a/tests/ui/issues/issue-21332.rs b/tests/ui/traits/error-reporting/incompatible-method-multiline.rs similarity index 100% rename from tests/ui/issues/issue-21332.rs rename to tests/ui/traits/error-reporting/incompatible-method-multiline.rs diff --git a/tests/ui/issues/issue-21332.stderr b/tests/ui/traits/error-reporting/incompatible-method-multiline.stderr similarity index 100% rename from tests/ui/issues/issue-21332.stderr rename to tests/ui/traits/error-reporting/incompatible-method-multiline.stderr diff --git a/tests/ui/issues/issue-19404.rs b/tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs similarity index 100% rename from tests/ui/issues/issue-19404.rs rename to tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs From eff5e8dd0650ff8de33d7aa22909c5f71a25c3e0 Mon Sep 17 00:00:00 2001 From: zedddie Date: Sat, 6 Jun 2026 20:31:09 +0200 Subject: [PATCH 21/33] bless batch --- tests/ui/derives/clone-copy/clone-ref-to-dst.rs | 2 ++ tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs | 2 ++ .../ui/dyn-compatibility/dyn-incompat-const-slice.stderr | 8 ++++---- tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs | 2 ++ .../trait-bounds/hrtb-closure-lifetime-infer.rs | 2 ++ .../ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs | 3 +++ tests/ui/match/match-field-reassign.rs | 8 +++++--- tests/ui/pattern/struct-variant-as-tuple-variant.rs | 2 ++ tests/ui/pattern/struct-variant-as-tuple-variant.stderr | 2 +- tests/ui/str/char-escape-unicode.rs | 1 + .../error-reporting/incompatible-method-multiline.rs | 3 +++ .../error-reporting/incompatible-method-multiline.stderr | 2 +- .../object/inherent-method-on-dyn-with-rc-coercion.rs | 2 ++ 13 files changed, 30 insertions(+), 9 deletions(-) diff --git a/tests/ui/derives/clone-copy/clone-ref-to-dst.rs b/tests/ui/derives/clone-copy/clone-ref-to-dst.rs index 7f88a89a65702..3eb8bba709329 100644 --- a/tests/ui/derives/clone-copy/clone-ref-to-dst.rs +++ b/tests/ui/derives/clone-copy/clone-ref-to-dst.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs index fce737cba18d2..d4cb2817d663b 100644 --- a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs +++ b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.rs @@ -1,3 +1,5 @@ +//! Regression test for . + trait Qiz { fn qiz(); } diff --git a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr index 4c41d41ae3792..46ed6a48a77fa 100644 --- a/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr +++ b/tests/ui/dyn-compatibility/dyn-incompat-const-slice.stderr @@ -1,12 +1,12 @@ error[E0038]: the trait `Qiz` is not dyn compatible - --> $DIR/issue-19380.rs:11:29 + --> $DIR/dyn-incompat-const-slice.rs:13:29 | LL | foos: &'static [&'static (dyn Qiz + 'static)] | ^^^^^^^^^^^^^^^^^ `Qiz` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-19380.rs:2:6 + --> $DIR/dyn-incompat-const-slice.rs:4:6 | LL | trait Qiz { | --- this trait is not dyn compatible... @@ -23,14 +23,14 @@ LL | fn qiz() where Self: Sized; | +++++++++++++++++ error[E0038]: the trait `Qiz` is not dyn compatible - --> $DIR/issue-19380.rs:16:31 + --> $DIR/dyn-incompat-const-slice.rs:18:31 | LL | const BAR : Bar = Bar { foos: &[&FOO]}; | ^^^^^^^ `Qiz` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/issue-19380.rs:2:6 + --> $DIR/dyn-incompat-const-slice.rs:4:6 | LL | trait Qiz { | --- this trait is not dyn compatible... diff --git a/tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs b/tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs index 4bace6d734ff1..550f917e72891 100644 --- a/tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs +++ b/tests/ui/fn_traits/manual-fn-impl-lifetime-elision.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass #![feature(fn_traits, unboxed_closures)] diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs index 42288511ab588..d4d81a31d4197 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-closure-lifetime-infer.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ run-pass use std::marker::PhantomData; diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs index 97e8ca17de1ec..576d59d401881 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-unused-lifetime.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Tests that we don't ICE from unused lifetime in HRTB. + //@ check-pass pub trait Handler { fn handle(&self, _: &mut String); diff --git a/tests/ui/match/match-field-reassign.rs b/tests/ui/match/match-field-reassign.rs index 1cd6c483375ab..c7135ac92fbfd 100644 --- a/tests/ui/match/match-field-reassign.rs +++ b/tests/ui/match/match-field-reassign.rs @@ -1,3 +1,8 @@ +//! Regression test for . +//! +//! Make sure we don't reuse the same alloca when matching +//! on field of struct or tuple which we reassign in the match body. + //@ run-pass #![allow(unused_assignments)] @@ -6,9 +11,6 @@ struct S { o: Option } -// Make sure we don't reuse the same alloca when matching -// on field of struct or tuple which we reassign in the match body. - fn main() { let mut a = (0, Some("right".to_string())); let b = match a.1 { diff --git a/tests/ui/pattern/struct-variant-as-tuple-variant.rs b/tests/ui/pattern/struct-variant-as-tuple-variant.rs index 42148c5f5a18d..944371ae9e952 100644 --- a/tests/ui/pattern/struct-variant-as-tuple-variant.rs +++ b/tests/ui/pattern/struct-variant-as-tuple-variant.rs @@ -1,3 +1,5 @@ +//! Regression test for . + use Foo::FooB; enum Foo { diff --git a/tests/ui/pattern/struct-variant-as-tuple-variant.stderr b/tests/ui/pattern/struct-variant-as-tuple-variant.stderr index 03b9249bb1e3d..1cd063e453100 100644 --- a/tests/ui/pattern/struct-variant-as-tuple-variant.stderr +++ b/tests/ui/pattern/struct-variant-as-tuple-variant.stderr @@ -1,5 +1,5 @@ error[E0532]: expected tuple struct or tuple variant, found variant `FooB` - --> $DIR/issue-19086.rs:10:9 + --> $DIR/struct-variant-as-tuple-variant.rs:12:9 | LL | FooB { x: i32, y: i32 } | ----------------------- `FooB` defined here diff --git a/tests/ui/str/char-escape-unicode.rs b/tests/ui/str/char-escape-unicode.rs index 7be77b88494b2..11975e15c1d38 100644 --- a/tests/ui/str/char-escape-unicode.rs +++ b/tests/ui/str/char-escape-unicode.rs @@ -1,3 +1,4 @@ +//! Regression test for . //@ run-pass fn main() { diff --git a/tests/ui/traits/error-reporting/incompatible-method-multiline.rs b/tests/ui/traits/error-reporting/incompatible-method-multiline.rs index ad764f84aa81a..950ee9d9e0b1c 100644 --- a/tests/ui/traits/error-reporting/incompatible-method-multiline.rs +++ b/tests/ui/traits/error-reporting/incompatible-method-multiline.rs @@ -1,3 +1,6 @@ +//! Regression test for . +//! Ensure multi-line error formatting for "method has incompatible type for trait" diagnostics. + struct S; impl Iterator for S { diff --git a/tests/ui/traits/error-reporting/incompatible-method-multiline.stderr b/tests/ui/traits/error-reporting/incompatible-method-multiline.stderr index 237b3acc9b4df..4f797dedfa846 100644 --- a/tests/ui/traits/error-reporting/incompatible-method-multiline.stderr +++ b/tests/ui/traits/error-reporting/incompatible-method-multiline.stderr @@ -1,5 +1,5 @@ error[E0053]: method `next` has an incompatible type for trait - --> $DIR/issue-21332.rs:5:27 + --> $DIR/incompatible-method-multiline.rs:8:27 | LL | fn next(&mut self) -> Result { Ok(7) } | ^^^^^^^^^^^^^^^^ expected `Option`, found `Result` diff --git a/tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs b/tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs index ff9bb1f2e037e..fc8715e8d513a 100644 --- a/tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs +++ b/tests/ui/traits/object/inherent-method-on-dyn-with-rc-coercion.rs @@ -1,3 +1,5 @@ +//! Regression test for + //@ build-pass #![allow(dead_code)] #![allow(unused_variables)] From 8cac9a30a9de5d09bafc48dadbc9f4a2dd4ed7e1 Mon Sep 17 00:00:00 2001 From: Aria Givens Date: Sat, 6 Jun 2026 17:06:50 -0400 Subject: [PATCH 22/33] Suggest using comma to separate valid attribute list items --- compiler/rustc_attr_parsing/src/parser.rs | 33 +++++++++++++++---- .../src/session_diagnostics.rs | 13 ++++++++ .../expected-comma-found-token.rs | 4 +-- .../expected-comma-found-token.stderr | 8 ++--- 4 files changed, 44 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 4d714fccc3f61..799b5ccbe4e40 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -30,8 +30,8 @@ use thin_vec::ThinVec; use crate::ShouldEmit; use crate::session_diagnostics::{ - InvalidMetaItem, InvalidMetaItemQuoteIdentSugg, InvalidMetaItemRemoveNegSugg, MetaBadDelim, - MetaBadDelimSugg, SuffixedLiteralInAttribute, + ExpectedComma, InvalidMetaItem, InvalidMetaItemQuoteIdentSugg, InvalidMetaItemRemoveNegSugg, + MetaBadDelim, MetaBadDelimSugg, SuffixedLiteralInAttribute, }; #[derive(Clone, Debug)] @@ -704,6 +704,29 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { self.parser.dcx().create_err(err) } + fn should_continue_parsing_meta_items(&mut self) -> Result> { + if self.parser.eat(exp!(Comma)) { + return Ok(true); + } else if self.parser.token == token::Eof { + return Ok(false); + } + + let mut snapshot = self.parser.create_snapshot_for_diagnostic(); + if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }) { + let span = self.parser.prev_token.span.shrink_to_hi(); + self.should_emit = ShouldEmit::Nothing; + match self.parse_meta_item_inner() { + Ok(_) => { + return Err(self.parser.dcx().create_err(ExpectedComma { span })); + } + Err(e) => { + e.cancel(); + } + } + } + snapshot.unexpected_any() + } + fn parse( tokens: TokenStream, psess: &'sess ParseSess, @@ -724,15 +747,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> { while this.parser.token != token::Eof { sub_parsers.push(this.parse_meta_item_inner()?); - if !this.parser.eat(exp!(Comma)) { + if !this.should_continue_parsing_meta_items()? { break; } } - if parser.token != token::Eof { - parser.unexpected()?; - } - Ok(MetaItemListParser { sub_parsers, span }) } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index b4afdfd7ce409..6dc629583cebe 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1032,3 +1032,16 @@ pub(crate) struct SanitizeInvalidStatic { pub span: Span, pub field: &'static str, } + +#[derive(Diagnostic)] +#[diag("attribute items not separated with `,`")] +pub(crate) struct ExpectedComma { + #[primary_span] + #[suggestion( + "try adding `,` here", + code = ",", + applicability = "maybe-incorrect", + style = "short" + )] + pub span: Span, +} diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.rs b/tests/ui/on-unimplemented/expected-comma-found-token.rs index d60ab3341fd6d..09c293f7eba78 100644 --- a/tests/ui/on-unimplemented/expected-comma-found-token.rs +++ b/tests/ui/on-unimplemented/expected-comma-found-token.rs @@ -4,7 +4,7 @@ #![feature(rustc_attrs)] #[rustc_on_unimplemented( - message="the message" - label="the label" //~ ERROR expected `,`, found `label` + message="the message" //~ ERROR attribute items not separated with `,` + label="the label" )] trait T {} diff --git a/tests/ui/on-unimplemented/expected-comma-found-token.stderr b/tests/ui/on-unimplemented/expected-comma-found-token.stderr index 2717100a1dc64..cdc80a4d9267c 100644 --- a/tests/ui/on-unimplemented/expected-comma-found-token.stderr +++ b/tests/ui/on-unimplemented/expected-comma-found-token.stderr @@ -1,10 +1,8 @@ -error: expected `,`, found `label` - --> $DIR/expected-comma-found-token.rs:8:5 +error: attribute items not separated with `,` + --> $DIR/expected-comma-found-token.rs:7:26 | LL | message="the message" - | - expected `,` -LL | label="the label" - | ^^^^^ unexpected token + | ^ help: try adding `,` here error: aborting due to 1 previous error From a23630fe793bd1629ebe2e424be952ce1782a86e Mon Sep 17 00:00:00 2001 From: majiayu000 <1835304752@qq.com> Date: Sun, 7 Jun 2026 12:43:47 +0800 Subject: [PATCH 23/33] Document Repeat::count panic behavior --- library/core/src/iter/sources/repeat.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/library/core/src/iter/sources/repeat.rs b/library/core/src/iter/sources/repeat.rs index 197b5f2124235..bdad4adccabac 100644 --- a/library/core/src/iter/sources/repeat.rs +++ b/library/core/src/iter/sources/repeat.rs @@ -111,6 +111,11 @@ impl Iterator for Repeat { panic!("iterator is infinite"); } + /// Consumes the iterator and panics. + /// + /// # Panics + /// + /// This method always panics because `Repeat` is infinite. #[track_caller] fn count(self) -> usize { panic!("iterator is infinite"); From 4af2ca0a93bb638583ab8b675b38b1044734997a Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Sat, 6 Jun 2026 21:57:35 -0700 Subject: [PATCH 24/33] In `copy_nonoverlapping`, use `mul nuw nsw` to compute the byte count --- compiler/rustc_codegen_ssa/src/mir/statement.rs | 2 +- .../intrinsics/copy_nonoverlapping.rs | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs index afbef86bd089e..950a4112ebfae 100644 --- a/compiler/rustc_codegen_ssa/src/mir/statement.rs +++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs @@ -86,7 +86,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { .layout_of(bx.typing_env().as_query_input(pointee)) .expect("expected pointee to have a layout"); let elem_size = pointee_layout.layout.size().bytes(); - let bytes = bx.mul(count, bx.const_usize(elem_size)); + let bytes = bx.unchecked_sumul(count, bx.const_usize(elem_size)); let align = pointee_layout.layout.align.abi; let dst = dst_val.immediate(); diff --git a/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs b/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs new file mode 100644 index 0000000000000..84a1f713ce68c --- /dev/null +++ b/tests/codegen-llvm/intrinsics/copy_nonoverlapping.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Copt-level=3 -C no-prepopulate-passes +//@ only-64bit (so I don't need to worry about usize) + +#![crate_type = "lib"] +#![feature(core_intrinsics)] + +// This deals in a count of elements, not bytes, so we need to multiply. +// Ensure we preserve UB from a count too high to be valid. +use std::intrinsics::copy_nonoverlapping; + +// CHECK-LABEL: @copy_u16( +#[no_mangle] +pub unsafe fn copy_u16(src: *const u16, dst: *mut u16, count: usize) { + // CHECK: [[BYTES:%.+]] = mul nuw nsw i64 %count, 2 + // CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 2 %dst, ptr align 2 %src, i64 [[BYTES]], i1 false) + copy_nonoverlapping(src, dst, count) +} From 4e26424d8b00c98fa55034963689df91222e0af5 Mon Sep 17 00:00:00 2001 From: "Mark Z. Ding" Date: Sun, 7 Jun 2026 01:06:01 -0400 Subject: [PATCH 25/33] chore: Update annotate-snippets to 0.12.16 --- Cargo.lock | 6 +++--- compiler/rustc_errors/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3f7b3a4367db..7aeb863159ddb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,9 +64,9 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.12.15" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92570a3f9c98e7e84df84b71d0965ac99b1871fcd75a3773a3bd1bad13f64cf7" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" dependencies = [ "anstyle", "memchr", @@ -3958,7 +3958,7 @@ dependencies = [ name = "rustc_errors" version = "0.0.0" dependencies = [ - "annotate-snippets 0.12.15", + "annotate-snippets 0.12.16", "anstream", "anstyle", "derive_setters", diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml index 386467c3e1edb..b0eed7ae2aad9 100644 --- a/compiler/rustc_errors/Cargo.toml +++ b/compiler/rustc_errors/Cargo.toml @@ -5,7 +5,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start -annotate-snippets = { version = "0.12.15", features = ["simd"] } +annotate-snippets = { version = "0.12.16", features = ["simd"] } anstream = "0.6.20" anstyle = "1.0.13" derive_setters = "0.1.6" From ddba286997c5a31e663552bec7e1d8e2ce7fe271 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 7 Jun 2026 09:37:57 +0200 Subject: [PATCH 26/33] Use impl(self) instead of Sealed --- library/core/src/convert/num.rs | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs index 9f6b6453cea94..19398b4680583 100644 --- a/library/core/src/convert/num.rs +++ b/library/core/src/convert/num.rs @@ -1,32 +1,5 @@ use crate::num::{IntErrorKind, TryFromIntError}; -mod private { - /// This trait being unreachable from outside the crate prevents other - /// implementations of the integer cast traits. - #[unstable(feature = "integer_casts", issue = "157388")] - pub trait Sealed {} - - /// This trait being unreachable from outside the crate prevents other - /// implementations of the integer cast traits. - /// - /// `Cast : SealedCast` avoids the orphan rule, which would otherwise - /// allow e.g. implementing `Cast` for `u8`. - #[unstable(feature = "integer_casts", issue = "157388")] - pub trait SealedCast: Sealed {} - - #[unstable(feature = "integer_casts", issue = "157388")] - impl SealedCast for U {} - - macro_rules! impl_sealed_int { - ([$($T:ty),*]) => {$( - #[unstable(feature = "integer_casts", issue = "157388")] - impl Sealed for $T { } - )*}; - } - - impl_sealed_int!([u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); -} - /// Supporting trait for inherent methods of `f32` and `f64` such as `to_int_unchecked`. /// Typically doesn’t need to be used directly. #[unstable(feature = "convert_float_to_int", issue = "67057")] @@ -661,7 +634,7 @@ impl_nonzero_int_try_from_nonzero_int!(isize => u8, u16, u32, u64, u128, usize); /// Conversion between integers, wrapping around or saturating at the target type's boundaries. #[unstable(feature = "integer_casts", issue = "157388")] #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] -pub const trait BoundedCastFromInt: private::SealedCast + Sized { +pub impl(self) const trait BoundedCastFromInt: Sized { /// Converts `value` to this type, wrapping around at the boundary of the type. #[unstable(feature = "integer_casts", issue = "157388")] fn wrapping_cast_from(value: T) -> Self; @@ -674,7 +647,7 @@ pub const trait BoundedCastFromInt: private::SealedCast + Sized { /// Fallible conversion between integers. #[unstable(feature = "integer_casts", issue = "157388")] #[rustc_const_unstable(feature = "integer_casts", issue = "157388")] -pub const trait CheckedCastFromInt: private::SealedCast + Sized { +pub impl(self) const trait CheckedCastFromInt: Sized { /// Converts `value` to this type, returning `None` if overflow would have occurred. #[unstable(feature = "integer_casts", issue = "157388")] fn checked_cast_from(value: T) -> Option; From bf174baace3b98bae12a224addda2fa8585878cb Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 7 Jun 2026 10:01:52 +0200 Subject: [PATCH 27/33] Use 'representable' rather than 'lies in domain' --- library/core/src/num/int_macros.rs | 9 +++++---- library/core/src/num/uint_macros.rs | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 97f51f923f410..2954716e99371 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -4111,7 +4111,7 @@ macro_rules! int_impl { } /// Converts `self` to the target integer type, returning `None` if the value - /// does not lie in the target type's domain. + /// is not representable by the target type. /// /// # Examples /// @@ -4129,11 +4129,11 @@ macro_rules! int_impl { } /// Converts `self` to the target integer type, panicking if the value - /// does not lie in the target type's domain. + /// is not representable by the target type. /// /// # Panics /// - /// This function will panic if the value does not lie in the target type's domain. + /// This function will panic if the value is not representable by the target type. /// /// # Examples /// @@ -4157,7 +4157,8 @@ macro_rules! int_impl { T::strict_cast_from(self) } - /// Converts `self` to the target integer type, assuming the value lies in the target type's domain. + /// Converts `self` to the target integer type, assuming the value is + /// representable by the target type. /// /// # Safety /// diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a4d2045a91d2e..b42032718cdb7 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -4269,7 +4269,7 @@ macro_rules! uint_impl { } /// Converts `self` to the target integer type, returning `None` if the value - /// does not lie in the target type's domain. + /// is not representable by the target type. /// /// # Examples /// @@ -4287,11 +4287,11 @@ macro_rules! uint_impl { } /// Converts `self` to the target integer type, panicking if the value - /// does not lie in the target type's domain. + /// is not representable by the target type. /// /// # Panics /// - /// This function will panic if the value does not lie in the target type's domain. + /// This function will panic if the value is not representable by the target type. /// /// # Examples /// @@ -4315,7 +4315,8 @@ macro_rules! uint_impl { T::strict_cast_from(self) } - /// Converts `self` to the target integer type, assuming the value lies in the target type's domain. + /// Converts `self` to the target integer type, assuming the value is + /// representable by the target type. /// /// # Safety /// From 0053d7602a87baf5437c013ab61ddc02c411faa6 Mon Sep 17 00:00:00 2001 From: Yotam Ofek Date: Sat, 6 Jun 2026 20:40:09 +0300 Subject: [PATCH 28/33] Cleanup and optimize `render_impls` - take ownership of the `Vec<&Impl>` instead of copying into another alloc - reuse `ImplString` to do natural sort ordering - lazy formatting --- src/librustdoc/html/render/mod.rs | 113 ++++++++---------- src/librustdoc/html/render/print_item.rs | 23 ++-- .../macro/const-rendering-macros-33302.rs | 20 ++-- 3 files changed, 77 insertions(+), 79 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index fd6d389542b99..4de2a46007877 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -40,6 +40,7 @@ mod type_layout; mod write_shared; use std::borrow::Cow; +use std::cmp::Ordering; use std::collections::VecDeque; use std::fmt::{self, Display as _, Write}; use std::iter::Peekable; @@ -79,7 +80,7 @@ use crate::html::format::{ use crate::html::markdown::{ HeadingOffset, IdMap, Markdown, MarkdownItemInfo, MarkdownSummaryLine, short_markdown_summary, }; -use crate::html::render::print_item::compare_names; +use crate::html::render::print_item::ImplString; use crate::html::render::search_index::get_function_type_for_search; use crate::html::static_files::SCRAPE_EXAMPLES_HELP_MD; use crate::html::{highlight, sources}; @@ -954,46 +955,50 @@ fn impl_trait_key(cx: &Context<'_>, i: &Impl) -> Option { // Render the list of items inside one of the sections "Trait Implementations", // "Auto Trait Implementations," "Blanket Trait Implementations" (on struct/enum pages). -fn render_impls( - cx: &Context<'_>, - mut w: impl Write, - impls: &[&Impl], - containing_item: &clean::Item, +fn render_impls<'a, 'cx>( + cx: &'a Context<'cx>, + mut impls: Vec<&'a Impl>, + containing_item: &'a clean::Item, toggle_open_by_default: bool, -) -> fmt::Result { +) -> impl fmt::Display + use<'a, 'cx> { + impls.sort_by_cached_key(|imp| { + let prefix = match imp.inner_impl().polarity { + ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => Ordering::Greater, + ty::ImplPolarity::Negative => Ordering::Less, + }; + (prefix, ImplString::new_path(imp, cx)) + }); // Render each impl alongside its `impl_trait_key`, which is used as the primary sorting key // to match the impl order in the sidebar. - let mut keyed_rendered_impls = impls - .iter() - .map(|i| { - let did = i.trait_did().unwrap(); - let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx()); - let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); - let imp = render_impl( - cx, - i, - containing_item, - assoc_link, - RenderMode::Normal, - None, - &[], - ImplRenderingParameters { - show_def_docs: true, - show_default_items: true, - show_non_assoc_items: true, - toggle_open_by_default, - }, - ); - (impl_trait_key(cx, i).unwrap(), imp.to_string()) - }) - .collect::>(); - // Sort and then remove the `impl_trait_key`s, which are no longer needed after sorting. - keyed_rendered_impls - .sort_by(|(k1, h1), (k2, h2)| compare_names(k1, k2).then_with(|| h1.cmp(h2))); - let joined: String = keyed_rendered_impls.into_iter().map(|a| a.1).collect(); - - w.write_str(&joined) + fmt::from_fn(move |f| { + impls + .iter() + .map(|i| { + fmt::from_fn(|f| { + let did = i.trait_did().unwrap(); + let provided_trait_methods = i.inner_impl().provided_trait_methods(cx.tcx()); + let assoc_link = AssocItemLink::GotoSource(did.into(), &provided_trait_methods); + render_impl( + cx, + i, + containing_item, + assoc_link, + RenderMode::Normal, + None, + &[], + ImplRenderingParameters { + show_def_docs: true, + show_default_items: true, + show_non_assoc_items: true, + toggle_open_by_default, + }, + ) + .fmt(f) + }) + }) + .joined("", f) + }) } /// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item. @@ -1415,16 +1420,12 @@ fn render_all_impls( mut w: impl Write, cx: &Context<'_>, containing_item: &clean::Item, - concrete_impls: &[&Impl], - auto_trait_impls: &[&Impl], - blanket_impls: &[&Impl], + concrete_impls: Vec<&Impl>, + auto_trait_impls: Vec<&Impl>, + blanket_impls: Vec<&Impl>, ) -> fmt::Result { - let impls = { - let mut buf = String::new(); - render_impls(cx, &mut buf, concrete_impls, containing_item, true)?; - buf - }; - if !impls.is_empty() { + if !concrete_impls.is_empty() { + let impls = render_impls(cx, concrete_impls, containing_item, true); write!( w, "{}
{impls}
", @@ -1433,25 +1434,24 @@ fn render_all_impls( } if !auto_trait_impls.is_empty() { + let impls = render_impls(cx, auto_trait_impls, containing_item, false); // FIXME: Change the ID to `auto-trait-implementations-list`! write!( w, - "{}
", + "{}
{impls}
", write_impl_section_heading("Auto Trait Implementations", "synthetic-implementations",) )?; - render_impls(cx, &mut w, auto_trait_impls, containing_item, false)?; - w.write_str("
")?; } if !blanket_impls.is_empty() { + let impls = render_impls(cx, blanket_impls, containing_item, false); write!( w, - "{}
", + "{}
{impls}
", write_impl_section_heading("Blanket Implementations", "blanket-implementations") )?; - render_impls(cx, &mut w, blanket_impls, containing_item, false)?; - w.write_str("
")?; } + Ok(()) } @@ -1588,14 +1588,7 @@ fn render_assoc_items_inner( let (blanket_impls, concrete_impls): (Vec<&Impl>, _) = trait_impls.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); - render_all_impls( - w, - cx, - containing_item, - &concrete_impls, - &auto_trait_impls, - &blanket_impls, - )?; + render_all_impls(w, cx, containing_item, concrete_impls, auto_trait_impls, blanket_impls)?; } Ok(()) } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 8385e691ed385..7469b08b4b424 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -32,8 +32,8 @@ use crate::formats::item_type::ItemType; use crate::html::escape::{Escape, EscapeBodyTextWithWbr}; use crate::html::format::{ Ending, PrintWithSpace, full_print_fn_decl, print_abi_with_space, print_constness_with_space, - print_generic_bound, print_generics, print_impl, print_import, print_type, print_where_clause, - visibility_print_with_space, + print_generic_bound, print_generics, print_impl, print_import, print_path, print_type, + print_where_clause, visibility_print_with_space, }; use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::render::sidebar::filters; @@ -1016,9 +1016,9 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt: let (mut synthetic, mut concrete): (Vec<&&Impl>, Vec<&&Impl>) = local.iter().partition(|i| i.inner_impl().kind.is_auto()); - synthetic.sort_by_cached_key(|i| ImplString::new(i, cx)); - concrete.sort_by_cached_key(|i| ImplString::new(i, cx)); - foreign.sort_by_cached_key(|i| ImplString::new(i, cx)); + synthetic.sort_by_cached_key(|i| ImplString::new_impl(i, cx)); + concrete.sort_by_cached_key(|i| ImplString::new_impl(i, cx)); + foreign.sort_by_cached_key(|i| ImplString::new_impl(i, cx)); if !foreign.is_empty() { write!( @@ -1969,7 +1969,7 @@ fn item_primitive(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display { let (concrete, synthetic, blanket_impl) = get_filtered_impls_for_reference(&cx.shared, it); - render_all_impls(w, cx, it, &concrete, &synthetic, &blanket_impl) + render_all_impls(w, cx, it, concrete, synthetic, blanket_impl) } }) } @@ -2346,16 +2346,21 @@ where } #[derive(PartialEq, Eq)] -struct ImplString { +pub(super) struct ImplString { // Plain text (not HTML text) because this is only used for sorting purposes, and the plain // text is much shorter and thus faster to compare. cmp_text: String, } impl ImplString { - fn new(i: &Impl, cx: &Context<'_>) -> ImplString { + fn new_impl(i: &Impl, cx: &Context<'_>) -> Self { let impl_ = i.inner_impl(); - ImplString { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) } + Self { cmp_text: format!("{:#}", print_impl(impl_, false, cx)) } + } + + pub(super) fn new_path(i: &Impl, cx: &Context<'_>) -> Option { + let path = i.inner_impl().trait_.as_ref()?; + Some(Self { cmp_text: format!("{:#}", print_path(path, cx)) }) } } diff --git a/tests/rustdoc-html/macro/const-rendering-macros-33302.rs b/tests/rustdoc-html/macro/const-rendering-macros-33302.rs index 9fd45df08be34..26b7d3d008481 100644 --- a/tests/rustdoc-html/macro/const-rendering-macros-33302.rs +++ b/tests/rustdoc-html/macro/const-rendering-macros-33302.rs @@ -1,5 +1,5 @@ // https://github.com/rust-lang/rust/issues/33302 -#![crate_name="issue_33302"] +#![crate_name = "issue_33302"] // Ensure constant and array length values are not taken from source // code, which wreaks havoc with macros. @@ -25,11 +25,12 @@ macro_rules! make { } //@ has issue_33302/struct.S.html \ - // '//*[@class="impl"]' 'impl T<[i32; 16]> for S' - //@ has - '//*[@id="associatedconstant.C"]' 'const C: [i32; 16]' + // '//*[@class="impl"]' 'impl T<(i32, i32)> for S' + //@ has - '//*[@id="associatedconstant.C"]' 'const C: (i32, i32)' //@ has - '//*[@id="associatedconstant.D"]' 'const D: i32' - impl T<[i32; ($n * $n)]> for S { - const C: [i32; ($n * $n)] = [0; ($n * $n)]; + impl T<(i32, i32)> for S { + const C: (i32, i32) = ($n, $n); + const D: i32 = ($n / $n); } //@ has issue_33302/struct.S.html \ @@ -41,12 +42,11 @@ macro_rules! make { } //@ has issue_33302/struct.S.html \ - // '//*[@class="impl"]' 'impl T<(i32, i32)> for S' - //@ has - '//*[@id="associatedconstant.C-2"]' 'const C: (i32, i32)' + // '//*[@class="impl"]' 'impl T<[i32; 16]> for S' + //@ has - '//*[@id="associatedconstant.C-2"]' 'const C: [i32; 16]' //@ has - '//*[@id="associatedconstant.D-2"]' 'const D: i32' - impl T<(i32, i32)> for S { - const C: (i32, i32) = ($n, $n); - const D: i32 = ($n / $n); + impl T<[i32; ($n * $n)]> for S { + const C: [i32; ($n * $n)] = [0; ($n * $n)]; } }; } From 9d5fa4015ac72936575172bb464939a738f07630 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sun, 7 Jun 2026 11:43:00 +0200 Subject: [PATCH 29/33] Add tests --- library/coretests/tests/lib.rs | 2 + library/coretests/tests/num/cast.rs | 101 ++++++++++++++++++++++++++++ library/coretests/tests/num/mod.rs | 1 + 3 files changed, 104 insertions(+) create mode 100644 library/coretests/tests/num/cast.rs diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index aa6aa1478bd70..4cb98fb92abb0 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -67,6 +67,7 @@ #![feature(hashmap_internals)] #![feature(int_from_ascii)] #![feature(int_roundings)] +#![feature(integer_casts)] #![feature(io_slice_as_bytes)] #![feature(ip)] #![feature(is_ascii_octdigit)] @@ -82,6 +83,7 @@ #![feature(iterator_try_collect)] #![feature(iterator_try_reduce)] #![feature(layout_for_ptr)] +#![feature(macro_metavar_expr_concat)] #![feature(maybe_uninit_fill)] #![feature(maybe_uninit_uninit_array_transpose)] #![feature(min_specialization)] diff --git a/library/coretests/tests/num/cast.rs b/library/coretests/tests/num/cast.rs new file mode 100644 index 0000000000000..dddfd3a02ee64 --- /dev/null +++ b/library/coretests/tests/num/cast.rs @@ -0,0 +1,101 @@ +use std::sync::LazyLock; + +// All (negative) integers which are at or near a power of two to test +// boundary conditions. We use strings so we can convert to any type using +// parsing, while still being able to use the *position* in ORDERED_VALS for +// comparisons. +static ORDERED_VALS: LazyLock> = LazyLock::new(|| { + let mut pos_int_vals = Vec::new(); + for exp in 0..=127 { + let val = 1_u128 << exp; + pos_int_vals.push(val.saturating_sub(2)); + pos_int_vals.push(val.saturating_sub(1)); + pos_int_vals.push(val); + pos_int_vals.push(val.saturating_add(1)); + pos_int_vals.push(val.saturating_add(2)); + } + pos_int_vals.sort(); + pos_int_vals.dedup(); + + let mut pos_str_vals: Vec<_> = pos_int_vals.iter().map(|i| i.to_string()).collect(); + + // These are manual because the upper ones overflow even u128. + pos_str_vals.push("340282366920938463463374607431768211454".to_owned()); // 2**128 - 2 + pos_str_vals.push("340282366920938463463374607431768211455".to_owned()); // 2**128 - 1 + pos_str_vals.push("340282366920938463463374607431768211456".to_owned()); // 2**128 + pos_str_vals.push("340282366920938463463374607431768211457".to_owned()); // 2**128 + 1 + pos_str_vals.push("340282366920938463463374607431768211458".to_owned()); // 2**128 + 2 + + let mut out = Vec::new(); + for val in pos_str_vals[1..].iter().rev() { + out.push(format!("-{val}")); + } + out.extend(pos_str_vals); + out +}); + +macro_rules! make_checked_cast_test { + ($Src:ident as [$($Dst:ident),*]) => {$( + #[test] + #[allow(non_snake_case)] + fn ${concat(test_checked_cast_, $Src, _to_, $Dst)}() { + for val in ORDERED_VALS.iter() { + if let Some(src) = val.parse::<$Src>().ok() { + let dst: Option<$Dst> = val.parse().ok(); + assert_eq!(src.checked_cast::<$Dst>(), dst); + } + } + } + )*} +} + +macro_rules! make_bounded_cast_test { + (|$src:ident| $raw:expr, $Src:ident as [$($Dst:ident),*]) => {$( + #[test] + #[allow(non_snake_case)] + fn ${concat(test_bounded_cast_, $Src, _to_, $Dst)}() { + let ord_idx = |s| ORDERED_VALS.iter().position(|v| *v == s).unwrap(); + let dst_min_idx = ord_idx(<$Dst>::MIN.to_string()); + let dst_max_idx = ord_idx(<$Dst>::MAX.to_string()); + for (val_idx, val) in ORDERED_VALS.iter().enumerate() { + if let Some($src) = val.parse::<$Src>().ok() { + let dst: Option<$Dst> = val.parse().ok(); + + assert_eq!($src.wrapping_cast::<$Dst>(), $raw as $Dst); + + if val_idx > dst_max_idx { + assert_eq!($src.saturating_cast::<$Dst>(), <$Dst>::MAX); + } else if val_idx < dst_min_idx { + assert_eq!($src.saturating_cast::<$Dst>(), <$Dst>::MIN); + } else { + assert_eq!($src.saturating_cast::<$Dst>(), dst.unwrap()); + } + } + } + } + )*} +} + +macro_rules! make_tests_for_src { + (|$src:ident| $raw:expr, [$($Src:ident),*]) => {$( + make_checked_cast_test!( $Src as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); + make_bounded_cast_test!(|$src| $raw, $Src as [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); + + // NonZero types are not (yet) implemented. + // make_checked_cast_test!($Src as [ + // NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, + // NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize + // ]); + )*} +} + +make_tests_for_src!(|x| x, [u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, isize]); + +// NonZero types are not (yet) implemented. +// make_tests_for_src!( +// |x| x.get(), +// [ +// NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, +// NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize +// ] +// ); diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index a82ac6fcd45f0..90666fc0b1ad2 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -23,6 +23,7 @@ mod u8; mod bignum; mod carryless_mul; +mod cast; mod const_from; mod dec2flt; mod float_ieee754_flt2dec_dec2flt; From f8ba021e5af8dd09e3d0d1729134a171994e00e3 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 7 Jun 2026 13:18:24 +0000 Subject: [PATCH 30/33] std::io::LineWriter: cap write_vectored newline scan to avoid quadratic write_all_vectored --- library/std/src/io/buffered/linewritershim.rs | 157 ++++++++++-------- library/std/src/io/buffered/tests.rs | 127 ++++++++++++++ 2 files changed, 219 insertions(+), 65 deletions(-) diff --git a/library/std/src/io/buffered/linewritershim.rs b/library/std/src/io/buffered/linewritershim.rs index 967e24812b9ff..2135eb6d2e578 100644 --- a/library/std/src/io/buffered/linewritershim.rs +++ b/library/std/src/io/buffered/linewritershim.rs @@ -49,6 +49,78 @@ impl<'a, W: ?Sized + Write> LineWriterShim<'a, W> { _ => Ok(()), } } + + /// Vectored line-buffered write over an already-capped list of buffers. + /// + /// The caller is responsible for trimming `bufs` to the prefix it is + /// willing to scan (see `MAX_BUFS_TO_SCAN`). This method only ever writes + /// or buffers bytes from `bufs`, so any newline it might bury in the + /// `BufWriter` is one it has itself scanned for -- buffers the caller + /// dropped past the cap can never end up stuck in the buffer. Bytes not + /// accounted for in the return value are left for the next call. + fn write_vectored_scanned(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + // Find the buffer containing the last newline. + let last_newline_buf_idx = bufs + .iter() + .enumerate() + .rev() + .find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i)); + + // If there are no new newlines (that is, if this write is less than + // one line), just do a regular buffered write. + let last_newline_buf_idx = match last_newline_buf_idx { + None => { + self.flush_if_completed_line()?; + return self.buffer.write_vectored(bufs); + } + Some(i) => i, + }; + + // Flush existing content to prepare for our write. + self.buffer.flush_buf()?; + + // This is what we're going to try to write directly to the inner + // writer. The rest will be buffered, if nothing goes wrong. + let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1); + + // Write `lines` directly to the inner writer. In keeping with the + // `write` convention, make at most one attempt to add new (unbuffered) + // data. Because this write doesn't touch the BufWriter state directly, + // and the buffer is known to be empty, we don't need to worry about + // self.panicked here. + let flushed = self.inner_mut().write_vectored(lines)?; + + // If inner returns Ok(0), propagate that to the caller without + // doing additional buffering; otherwise we're just guaranteeing + // an "ErrorKind::WriteZero" later. + if flushed == 0 { + return Ok(0); + } + + // Don't try to reconstruct the exact amount written; just bail + // in the event of a partial write. + let mut lines_len: usize = 0; + for buf in lines { + // With overlapping/duplicate slices the total length may in theory + // exceed usize::MAX + lines_len = lines_len.saturating_add(buf.len()); + if flushed < lines_len { + return Ok(flushed); + } + } + + // Now that the write has succeeded, buffer the rest (or as much of the + // rest as possible). `tail` is the part of the scanned prefix after the + // last newline, so it cannot contain a newline of its own. + let buffered: usize = tail + .iter() + .filter(|buf| !buf.is_empty()) + .map(|buf| self.buffer.write_to_buf(buf)) + .take_while(|&n| n > 0) + .sum(); + + Ok(flushed + buffered) + } } impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> { @@ -185,71 +257,26 @@ impl<'a, W: ?Sized + Write> Write for LineWriterShim<'a, W> { }; } - // Find the buffer containing the last newline - // FIXME: This is overly slow if there are very many bufs and none contain - // newlines. e.g. writev() on Linux only writes up to 1024 slices, so - // scanning the rest is wasted effort. This makes write_all_vectored() - // quadratic. - let last_newline_buf_idx = bufs - .iter() - .enumerate() - .rev() - .find_map(|(i, buf)| memchr::memchr(b'\n', buf).map(|_| i)); - - // If there are no new newlines (that is, if this write is less than - // one line), just do a regular buffered write - let last_newline_buf_idx = match last_newline_buf_idx { - // No newlines; just do a normal buffered write - None => { - self.flush_if_completed_line()?; - return self.buffer.write_vectored(bufs); - } - Some(i) => i, - }; - - // Flush existing content to prepare for our write - self.buffer.flush_buf()?; - - // This is what we're going to try to write directly to the inner - // writer. The rest will be buffered, if nothing goes wrong. - let (lines, tail) = bufs.split_at(last_newline_buf_idx + 1); - - // Write `lines` directly to the inner writer. In keeping with the - // `write` convention, make at most one attempt to add new (unbuffered) - // data. Because this write doesn't touch the BufWriter state directly, - // and the buffer is known to be empty, we don't need to worry about - // self.panicked here. - let flushed = self.inner_mut().write_vectored(lines)?; - - // If inner returns Ok(0), propagate that to the caller without - // doing additional buffering; otherwise we're just guaranteeing - // an "ErrorKind::WriteZero" later. - if flushed == 0 { - return Ok(0); - } - - // Don't try to reconstruct the exact amount written; just bail - // in the event of a partial write - let mut lines_len: usize = 0; - for buf in lines { - // With overlapping/duplicate slices the total length may in theory - // exceed usize::MAX - lines_len = lines_len.saturating_add(buf.len()); - if flushed < lines_len { - return Ok(flushed); - } - } - - // Now that the write has succeeded, buffer the rest (or as much of the - // rest as possible) - let buffered: usize = tail - .iter() - .filter(|buf| !buf.is_empty()) - .map(|buf| self.buffer.write_to_buf(buf)) - .take_while(|&n| n > 0) - .sum(); - - Ok(flushed + buffered) + // Only scan (and operate on) the first MAX_BUFS_TO_SCAN slices. The cap + // is what keeps write_all_vectored() from going quadratic when callers + // pass many newline-free slices -- without it, every iteration of the + // outer loop rescans every remaining buffer. 1024 is a portable, + // generous upper bound: it is the value of UIO_MAXIOV / IOV_MAX on + // Linux and the BSDs (and the hardcoded cap in + // sys::net::connection::socket::solid), so on those platforms it also + // lines up with the most a single writev() can retire. On platforms + // whose syscall cap is smaller (POSIX requires only 16) or that have no + // cap at all (Windows), the constant still serves its primary purpose + // of bounding scan work. + // + // Everything past the cap is left untouched for the next call; the + // outer loop in write_all_vectored() makes forward progress via the + // short return value, and correctness is preserved everywhere. We hand + // the capped prefix to a helper so the rest of the logic can only ever + // see -- and therefore only ever write or buffer -- buffers we have + // actually scanned for newlines. + const MAX_BUFS_TO_SCAN: usize = 1024; + self.write_vectored_scanned(&bufs[..bufs.len().min(MAX_BUFS_TO_SCAN)]) } fn is_write_vectored(&self) -> bool { diff --git a/library/std/src/io/buffered/tests.rs b/library/std/src/io/buffered/tests.rs index 742e753f9b951..8888ffa0c4cb7 100644 --- a/library/std/src/io/buffered/tests.rs +++ b/library/std/src/io/buffered/tests.rs @@ -752,6 +752,133 @@ fn line_vectored_partial_and_errors() { } } +/// Regression test for the quadratic scan in `LineWriterShim::write_vectored`. +/// +/// When given a long list of newline-free buffers and a sink that only +/// retires a few slices per call, the previous implementation rescanned all +/// remaining buffers on every iteration of `write_all_vectored`, producing +/// O(N^2) work. The fix caps the scan to a constant prefix; this test +/// verifies that bytes still come out in order when the only newline lives +/// past that cap. +#[test] +fn line_vectored_long_input_past_scan_cap() { + /// Vectored sink that retires at most one non-empty slice per call, + /// mimicking a writev() bounded by IOV_MAX. + #[derive(Default)] + struct OneSliceSink { + buffer: Vec, + } + + impl Write for OneSliceSink { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buffer.extend_from_slice(buf); + Ok(buf.len()) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + for b in bufs { + if !b.is_empty() { + self.buffer.extend_from_slice(b); + return Ok(b.len()); + } + } + Ok(0) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn is_write_vectored(&self) -> bool { + true + } + } + + // Place the only newline well past the 1024-slice scan cap. + const N: usize = 1500; + const NEWLINE_AT: usize = 1400; + let bytes: Vec = (0..N).map(|i| if i == NEWLINE_AT { b'\n' } else { b'a' }).collect(); + let mut io_slices: Vec> = bytes.chunks(1).map(IoSlice::new).collect(); + + let mut writer = LineWriter::new(OneSliceSink::default()); + writer.write_all_vectored(&mut io_slices).unwrap(); + + // The newline past the scan cap must still trigger a flush through + // the inner writer; only the tail after the newline may remain buffered. + assert_eq!(writer.get_ref().buffer, bytes[..=NEWLINE_AT]); + + writer.flush().unwrap(); + assert_eq!(writer.get_ref().buffer, bytes); +} + +/// Regression test for newlines buried past the `write_vectored` scan cap. +/// +/// `LineWriterShim::write_vectored` only scans a bounded prefix of the slice +/// list for newlines. An earlier version computed the head/tail split against +/// the *full* list, so when more than the cap's worth of slices were passed in +/// a single call and one of the unscanned slices held a newline, that newline +/// was silently copied into the inner `BufWriter` instead of being flushed -- +/// leaving a completed line stuck in the buffer. +/// +/// The invariant this checks is the core line-buffering guarantee: once all +/// input has been written, everything up to and including the *last* newline +/// must have reached the inner writer, and only the trailing partial line may +/// remain buffered. It holds regardless of the exact scan-cap value, and it is +/// driven through the public `write_all_vectored` entry point so the cap +/// boundary is crossed naturally. +#[test] +fn line_vectored_flushes_newline_past_scan_cap() { + /// Vectored sink that accepts every slice in full, so any data that fails + /// to reach it must have been (incorrectly) left in the LineWriter buffer. + #[derive(Default)] + struct FullSink { + buffer: Vec, + } + + impl Write for FullSink { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buffer.extend_from_slice(buf); + Ok(buf.len()) + } + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + let mut written = 0; + for b in bufs { + self.buffer.extend_from_slice(b); + written += b.len(); + } + Ok(written) + } + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } + fn is_write_vectored(&self) -> bool { + true + } + } + + // Two newlines: one comfortably inside the scan cap and one well past it, + // so a single `write_vectored` call sees the first but not the second. + const N: usize = 1100; + const FIRST_NEWLINE: usize = 5; + const LAST_NEWLINE: usize = 1050; + let bytes: Vec = (0..N) + .map(|i| if i == FIRST_NEWLINE || i == LAST_NEWLINE { b'\n' } else { b'a' }) + .collect(); + let mut io_slices: Vec> = bytes.chunks(1).map(IoSlice::new).collect(); + + // The buffer has to be large enough to hold the whole tail past the first + // newline; otherwise it fills up before the buggy split would even reach + // the second newline, masking the bug. + let mut writer = LineWriter::with_capacity(4096, FullSink::default()); + writer.write_all_vectored(&mut io_slices).unwrap(); + + // Everything up to and including the last newline must have been flushed; + // only the trailing partial line is allowed to remain buffered. The buggy + // version left the last newline buried in the buffer, so the sink only saw + // up to the first newline. + assert_eq!(writer.get_ref().buffer, bytes[..=LAST_NEWLINE]); + + writer.flush().unwrap(); + assert_eq!(writer.get_ref().buffer, bytes); +} + /// Test that, in cases where vectored writing is not enabled, the /// LineWriter uses the normal `write` call, which more-correctly handles /// partial lines From 9419baeee856724fba345c114aef34569a2120b9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:01:07 +0000 Subject: [PATCH 31/33] Use WorkProductMap instead of FxIndexMap This is an UnordMap internally. Iteration order for the work product map should not matter aside from the place it is serialized where sorting by WorkProductId is sufficient. --- compiler/rustc_codegen_cranelift/src/lib.rs | 6 +++--- compiler/rustc_codegen_gcc/src/lib.rs | 5 ++--- compiler/rustc_codegen_llvm/src/lib.rs | 5 ++--- compiler/rustc_codegen_ssa/src/back/write.rs | 13 ++++--------- compiler/rustc_codegen_ssa/src/traits/backend.rs | 5 ++--- compiler/rustc_incremental/src/persist/save.rs | 15 ++++++--------- compiler/rustc_interface/src/queries.rs | 5 ++--- compiler/rustc_interface/src/util.rs | 7 +++---- .../codegen-backend/auxiliary/the_backend.rs | 15 ++++----------- 9 files changed, 28 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 38cb986034859..af783f31a2136 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -40,7 +40,7 @@ use cranelift_codegen::settings::{self, Configurable}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo, TargetConfig, back}; use rustc_log::tracing::info; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::WorkProductMap; use rustc_session::Session; use rustc_session::config::OutputFilenames; use rustc_span::{Symbol, sym}; @@ -88,7 +88,7 @@ mod prelude { }; pub(crate) use cranelift_module::{self, DataDescription, FuncId, Linkage, Module}; pub(crate) use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Scalar, Size, VariantIdx}; - pub(crate) use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; + pub(crate) use rustc_data_structures::fx::FxHashMap; pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE}; pub(crate) use rustc_index::Idx; pub(crate) use rustc_middle::mir::{self, *}; @@ -235,7 +235,7 @@ impl CodegenBackend for CraneliftCodegenBackend { sess: &Session, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .unwrap() diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 9669f40166287..850b67c7b25af 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -89,11 +89,10 @@ use rustc_codegen_ssa::base::codegen_crate; use rustc_codegen_ssa::target_features::cfg_target_feature; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; @@ -301,7 +300,7 @@ impl CodegenBackend for GccCodegenBackend { sess: &Session, _outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 7c05ecbab6d1c..c0593bb467796 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -32,11 +32,10 @@ use rustc_codegen_ssa::back::write::{ }; use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; @@ -358,7 +357,7 @@ impl CodegenBackend for LlvmCodegenBackend { sess: &Session, outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { let (compiled_modules, work_products) = ongoing_codegen .downcast::>() .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 1b7817cb17bfe..2262db392f54e 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -6,7 +6,6 @@ use std::sync::mpsc::{Receiver, Sender, channel}; use std::{assert_matches, fs, io, mem, str, thread}; use rustc_abi::Size; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; @@ -22,7 +21,7 @@ use rustc_incremental::{ use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::bug; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{ @@ -460,8 +459,8 @@ pub(crate) fn start_async_codegen( fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( sess: &Session, compiled_modules: &CompiledModules, -) -> FxIndexMap { - let mut work_products = FxIndexMap::default(); +) -> WorkProductMap { + let mut work_products = WorkProductMap::default(); if sess.opts.incremental.is_none() || sess.opts.unstable_opts.disable_incr_comp_backend_caching { @@ -2099,11 +2098,7 @@ pub struct OngoingCodegen { } impl OngoingCodegen { - pub fn join( - self, - sess: &Session, - crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + pub fn join(self, sess: &Session, crate_info: &CrateInfo) -> (CompiledModules, WorkProductMap) { self.shared_emitter_main.check(sess, true); let maybe_lto_modules = sess.time("join_worker_thread", || match self.coordinator.join() { diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 6bee9f7cadee7..6014f1af4bfc3 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -2,11 +2,10 @@ use std::any::Any; use std::hash::Hash; use rustc_ast::expand::allocator::AllocatorMethod; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_metadata::EncodedMetadata; use rustc_metadata::creader::MetadataLoaderDyn; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::WorkProductMap; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; @@ -130,7 +129,7 @@ pub trait CodegenBackend { sess: &Session, outputs: &OutputFilenames, crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap); + ) -> (CompiledModules, WorkProductMap); fn print_pass_timings(&self) {} diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index ab695dddf06e6..69705f28aa114 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -1,8 +1,7 @@ use std::fs; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::par_join; -use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::{DepGraph, WorkProductMap}; use rustc_middle::query::on_disk_cache; use rustc_middle::ty::TyCtxt; use rustc_serialize::Encodable as RustcEncodable; @@ -93,7 +92,7 @@ pub(crate) fn save_dep_graph(tcx: TyCtxt<'_>) { pub fn save_work_product_index( sess: &Session, dep_graph: &DepGraph, - new_work_products: FxIndexMap, + new_work_products: WorkProductMap, ) { if sess.opts.incremental.is_none() { return; @@ -126,18 +125,16 @@ pub fn save_work_product_index( // Check that we did not delete one of the current work-products: debug_assert!({ - new_work_products.iter().all(|(_, wp)| { + new_work_products.items().all(|(_, wp)| { wp.saved_files.items().all(|(_, path)| in_incr_comp_dir_sess(sess, path).exists()) }) }); } -fn encode_work_product_index( - work_products: &FxIndexMap, - encoder: &mut FileEncoder, -) { +fn encode_work_product_index(work_products: &WorkProductMap, encoder: &mut FileEncoder) { let serialized_products: Vec<_> = work_products - .iter() + .to_sorted_stable_ord() + .into_iter() .map(|(id, work_product)| SerializedWorkProduct { id: *id, work_product: work_product.clone(), diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 20ac6e258ed16..7a106e1089e2c 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -3,12 +3,11 @@ use std::sync::Arc; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo}; -use rustc_data_structures::indexmap::IndexMap; use rustc_data_structures::svh::Svh; use rustc_errors::timings::TimingSection; use rustc_hir::def_id::LOCAL_CRATE; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::DepGraph; +use rustc_middle::dep_graph::{DepGraph, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, OutputFilenames, OutputType}; @@ -51,7 +50,7 @@ impl Linker { let (compiled_modules, mut work_products) = sess.time("finish_ongoing_codegen", || { match self.ongoing_codegen.downcast::() { // This was a check only build - Ok(compiled_modules) => (*compiled_modules, IndexMap::default()), + Ok(compiled_modules) => (*compiled_modules, WorkProductMap::default()), Err(ongoing_codegen) => codegen_backend.join_codegen( ongoing_codegen, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d7d306918fd0d..4cb4876284706 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -14,11 +14,10 @@ use rustc_codegen_ssa::target_features::cfg_target_feature; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo, TargetConfig}; use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN}; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::jobserver::Proxy; use rustc_data_structures::sync; use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib}; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::WorkProductMap; use rustc_middle::ty::{CurrentGcx, TyCtxt}; use rustc_query_impl::{CollectActiveJobsKind, collect_active_query_jobs}; use rustc_session::config::{ @@ -418,8 +417,8 @@ impl CodegenBackend for DummyCodegenBackend { _sess: &Session, _outputs: &OutputFilenames, _crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { - (*ongoing_codegen.downcast().unwrap(), FxIndexMap::default()) + ) -> (CompiledModules, WorkProductMap) { + (*ongoing_codegen.downcast().unwrap(), WorkProductMap::default()) } fn link( diff --git a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs index 8a7cacf20e2e4..610a4990a5a4b 100644 --- a/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs +++ b/tests/ui-fulldeps/codegen-backend/auxiliary/the_backend.rs @@ -4,24 +4,17 @@ #![deny(warnings)] extern crate rustc_codegen_ssa; -extern crate rustc_data_structures; -extern crate rustc_driver; -extern crate rustc_errors; -extern crate rustc_hir; +extern crate rustc_driver as _; extern crate rustc_metadata; extern crate rustc_middle; extern crate rustc_session; -extern crate rustc_span; -extern crate rustc_symbol_mangling; -extern crate rustc_target; use std::any::Any; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo}; -use rustc_data_structures::fx::FxIndexMap; use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::dep_graph::WorkProductMap; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::OutputFilenames; @@ -47,11 +40,11 @@ impl CodegenBackend for TheBackend { _sess: &Session, _outputs: &OutputFilenames, _crate_info: &CrateInfo, - ) -> (CompiledModules, FxIndexMap) { + ) -> (CompiledModules, WorkProductMap) { let codegen_results = ongoing_codegen .downcast::() .expect("in join_codegen: ongoing_codegen is not a CompiledModules"); - (*codegen_results, FxIndexMap::default()) + (*codegen_results, WorkProductMap::default()) } fn link( From f4846298634c8c06b7c6929b2bf4cd44794ba132 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 4 Jun 2026 10:39:13 +0000 Subject: [PATCH 32/33] Assert incr comp in copy_cgu_workproduct_to_incr_comp_cache_dir It was already only called when incr comp is enabled and this allows cleaning up the callers a bit. --- compiler/rustc_codegen_ssa/src/back/write.rs | 7 +++---- .../rustc_incremental/src/persist/work_product.rs | 8 +++++--- compiler/rustc_interface/src/queries.rs | 13 ++++++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 2262db392f54e..112cf45ebbf2e 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -489,14 +489,13 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( if let Some(path) = &module.bytecode { files.push((OutputType::Bitcode.extension(), path.as_path())); } - if let Some((id, product)) = copy_cgu_workproduct_to_incr_comp_cache_dir( + let (id, product) = copy_cgu_workproduct_to_incr_comp_cache_dir( sess, &module.name, files.as_slice(), &module.links_from_incr_cache, - ) { - work_products.insert(id, product); - } + ); + work_products.insert(id, product); } work_products diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 7b1eb0a82e397..64dae5c0869b9 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -16,14 +16,16 @@ use crate::persist::fs::*; /// Copies a CGU work product to the incremental compilation directory, so next compilation can /// find and reuse it. +/// +/// Panics when incr comp is disabled. pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, files: &[(&'static str, &Path)], known_links: &[PathBuf], -) -> Option<(WorkProductId, WorkProduct)> { +) -> (WorkProductId, WorkProduct) { debug!(?cgu_name, ?files); - sess.opts.incremental.as_ref()?; + assert!(sess.opts.incremental.is_some()); let mut saved_files = UnordMap::default(); for (ext, path) in files { @@ -50,7 +52,7 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files }; debug!(?work_product); let work_product_id = WorkProductId::from_cgu_name(cgu_name); - Some((work_product_id, work_product)) + (work_product_id, work_product) } /// Removes files for a given work product. diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 7a106e1089e2c..6026cfd5f71fe 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -89,14 +89,13 @@ impl Linker { if sess.opts.incremental.is_some() && let Some(path) = self.metadata.path() - && let Some((id, product)) = - rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( - sess, - "metadata", - &[("rmeta", path)], - &[], - ) { + let (id, product) = rustc_incremental::copy_cgu_workproduct_to_incr_comp_cache_dir( + sess, + "metadata", + &[("rmeta", path)], + &[], + ); work_products.insert(id, product); } From ddbf3b9ec6bc1e28b32a53df6abcab13989fcd0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 6 Mar 2026 18:42:32 +0100 Subject: [PATCH 33/33] Syntactically reject equality predicates --- compiler/rustc_ast/src/ast.rs | 2 - compiler/rustc_ast_lowering/src/item.rs | 12 - .../rustc_ast_passes/src/ast_validation.rs | 176 +------------- compiler/rustc_ast_passes/src/diagnostics.rs | 43 ---- .../rustc_ast_pretty/src/pprust/state/item.rs | 8 - .../src/deriving/coerce_pointee.rs | 3 +- compiler/rustc_hir/src/hir.rs | 4 - compiler/rustc_hir/src/intravisit.rs | 4 - .../src/check/compare_impl_item.rs | 2 - .../src/collect/predicates_of.rs | 4 - .../src/collect/resolve_bound_vars.rs | 6 - compiler/rustc_hir_pretty/src/lib.rs | 8 - compiler/rustc_lint/src/builtin.rs | 1 - compiler/rustc_parse/src/parser/generics.rs | 104 ++++++++- compiler/rustc_passes/src/input_stats.rs | 4 +- src/librustdoc/clean/mod.rs | 11 +- src/librustdoc/clean/simplify.rs | 4 +- src/librustdoc/clean/types.rs | 2 +- src/librustdoc/html/format.rs | 2 +- src/librustdoc/json/conversions.rs | 2 +- .../clippy/clippy_lints/src/lifetimes.rs | 8 - .../src/multiple_bound_locations.rs | 1 - .../clippy/clippy_utils/src/ast_utils/mod.rs | 1 - .../clippy/clippy_utils/src/hir_utils.rs | 3 - src/tools/rustfmt/src/types.rs | 10 - ...pe-projection-from-multiple-supertraits.rs | 7 +- ...rojection-from-multiple-supertraits.stderr | 24 +- .../equality-bound.rs | 82 ------- .../equality-bound.stderr | 218 ------------------ .../missing-bounds.fixed | 5 +- .../missing-bounds.rs | 5 +- .../missing-bounds.stderr | 38 +-- tests/ui/parser/equality-predicates-0.rs | 20 ++ tests/ui/parser/equality-predicates-0.stderr | 15 ++ tests/ui/parser/equality-predicates-1.rs | 20 ++ tests/ui/parser/equality-predicates-1.stderr | 15 ++ .../where-equality-constraints.rs | 6 - .../where-equality-constraints.stderr | 18 -- 38 files changed, 182 insertions(+), 716 deletions(-) delete mode 100644 tests/ui/generic-associated-types/equality-bound.rs delete mode 100644 tests/ui/generic-associated-types/equality-bound.stderr create mode 100644 tests/ui/parser/equality-predicates-0.rs create mode 100644 tests/ui/parser/equality-predicates-0.stderr create mode 100644 tests/ui/parser/equality-predicates-1.rs create mode 100644 tests/ui/parser/equality-predicates-1.stderr delete mode 100644 tests/ui/where-clauses/where-equality-constraints.rs delete mode 100644 tests/ui/where-clauses/where-equality-constraints.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 8a342acbfa913..b8339c74dac03 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -509,8 +509,6 @@ pub enum WherePredicateKind { BoundPredicate(WhereBoundPredicate), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate), - /// An equality predicate (unsupported). - EqPredicate(WhereEqPredicate), } /// A type bound. diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 0e518c10e3bb7..8ae2f3bda9f92 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2111,18 +2111,6 @@ impl<'hir> LoweringContext<'_, 'hir> { in_where_clause: true, }) } - WherePredicateKind::EqPredicate(WhereEqPredicate { lhs_ty, rhs_ty }) => { - hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty: self.lower_ty_alloc( - lhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - rhs_ty: self.lower_ty_alloc( - rhs_ty, - ImplTraitContext::Disallowed(ImplTraitPosition::Bound), - ), - }) - } }); hir::WherePredicate { hir_id, span, kind } } diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index db0c5256184c5..081de1ac2de6b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -17,7 +17,6 @@ //! require name resolution or type checking, or other kinds of complex analysis. use std::mem; -use std::ops::{Deref, DerefMut}; use std::str::FromStr; use itertools::{Either, Itertools}; @@ -37,7 +36,6 @@ use rustc_session::lint::builtin::{ }; use rustc_span::{Ident, Span, kw, sym}; use rustc_target::spec::{AbiMap, AbiMapping}; -use thin_vec::thin_vec; use crate::diagnostics::{self, TildeConstReason}; @@ -1593,14 +1591,8 @@ impl Visitor<'_> for AstValidator<'_> { } validate_generic_param_order(self.dcx(), &generics.params, generics.span); - - for predicate in &generics.where_clause.predicates { - let span = predicate.span; - if let WherePredicateKind::EqPredicate(predicate) = &predicate.kind { - deny_equality_constraints(self, predicate, span, generics); - } - } walk_list!(self, visit_generic_param, &generics.params); + for predicate in &generics.where_clause.predicates { match &predicate.kind { WherePredicateKind::BoundPredicate(bound_pred) => { @@ -1625,7 +1617,7 @@ impl Visitor<'_> for AstValidator<'_> { } } } - _ => {} + WherePredicateKind::RegionPredicate(_) => {} } self.visit_where_predicate(predicate); } @@ -1962,170 +1954,6 @@ impl Visitor<'_> for AstValidator<'_> { } } -/// When encountering an equality constraint in a `where` clause, emit an error. If the code seems -/// like it's setting an associated type, provide an appropriate suggestion. -fn deny_equality_constraints( - this: &AstValidator<'_>, - predicate: &WhereEqPredicate, - predicate_span: Span, - generics: &Generics, -) { - let mut err = diagnostics::EqualityInWhere { span: predicate_span, assoc: None, assoc2: None }; - - // Given `
::Bar = RhsTy`, suggest `A: Foo`. - if let TyKind::Path(Some(qself), full_path) = &predicate.lhs_ty.kind - && let TyKind::Path(None, path) = &qself.ty.kind - && let [PathSegment { ident, args: None, .. }] = &path.segments[..] - { - for param in &generics.params { - if param.ident == *ident - && let [PathSegment { ident, args, .. }] = &full_path.segments[qself.position..] - { - // Make a new `Path` from `foo::Bar` to `Foo`. - let mut assoc_path = full_path.clone(); - // Remove `Bar` from `Foo::Bar`. - assoc_path.segments.pop(); - let len = assoc_path.segments.len() - 1; - let gen_args = args.as_deref().cloned(); - // Build ``. - let arg = AngleBracketedArg::Constraint(AssocItemConstraint { - id: rustc_ast::node_id::DUMMY_NODE_ID, - ident: *ident, - gen_args, - kind: AssocItemConstraintKind::Equality { - term: predicate.rhs_ty.clone().into(), - }, - span: ident.span, - }); - // Add `` to `Foo`. - match &mut assoc_path.segments[len].args { - Some(args) => match args.deref_mut() { - GenericArgs::Parenthesized(_) | GenericArgs::ParenthesizedElided(..) => { - continue; - } - GenericArgs::AngleBracketed(args) => { - args.args.push(arg); - } - }, - empty_args => { - *empty_args = Some( - AngleBracketedArgs { span: ident.span, args: thin_vec![arg] }.into(), - ); - } - } - err.assoc = Some(diagnostics::AssociatedSuggestion { - span: predicate_span, - ident: *ident, - param: param.ident, - path: pprust::path_to_string(&assoc_path), - }) - } - } - } - - let mut suggest = - |poly: &PolyTraitRef, potential_assoc: &PathSegment, predicate: &WhereEqPredicate| { - if let [trait_segment] = &poly.trait_ref.path.segments[..] { - let assoc = pprust::path_to_string(&ast::Path::from_ident(potential_assoc.ident)); - let ty = pprust::ty_to_string(&predicate.rhs_ty); - let (args, span) = match &trait_segment.args { - Some(args) => match args.deref() { - ast::GenericArgs::AngleBracketed(args) => { - let Some(arg) = args.args.last() else { - return; - }; - (format!(", {assoc} = {ty}"), arg.span().shrink_to_hi()) - } - _ => return, - }, - None => (format!("<{assoc} = {ty}>"), trait_segment.span().shrink_to_hi()), - }; - let removal_span = if generics.where_clause.predicates.len() == 1 { - // We're removing th eonly where bound left, remove the whole thing. - generics.where_clause.span - } else { - let mut span = predicate_span; - let mut prev_span: Option = None; - let mut preds = generics.where_clause.predicates.iter().peekable(); - // Find the predicate that shouldn't have been in the where bound list. - while let Some(pred) = preds.next() { - if let WherePredicateKind::EqPredicate(_) = pred.kind - && pred.span == predicate_span - { - if let Some(next) = preds.peek() { - // This is the first predicate, remove the trailing comma as well. - span = span.with_hi(next.span.lo()); - } else if let Some(prev_span) = prev_span { - // Remove the previous comma as well. - span = span.with_lo(prev_span.hi()); - } - } - prev_span = Some(pred.span); - } - span - }; - err.assoc2 = Some(diagnostics::AssociatedSuggestion2 { - span, - args, - predicate: removal_span, - trait_segment: trait_segment.ident, - potential_assoc: potential_assoc.ident, - }); - } - }; - - if let TyKind::Path(None, full_path) = &predicate.lhs_ty.kind { - // Given `A: Foo, Foo::Bar = RhsTy`, suggest `A: Foo`. - for bounds in generics.params.iter().map(|p| &p.bounds).chain( - generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind { - WherePredicateKind::BoundPredicate(p) => Some(&p.bounds), - _ => None, - }), - ) { - for bound in bounds { - if let GenericBound::Trait(poly) = bound - && poly.modifiers == TraitBoundModifiers::NONE - { - if full_path.segments[..full_path.segments.len() - 1] - .iter() - .map(|segment| segment.ident.name) - .zip(poly.trait_ref.path.segments.iter().map(|segment| segment.ident.name)) - .all(|(a, b)| a == b) - && let Some(potential_assoc) = full_path.segments.last() - { - suggest(poly, potential_assoc, predicate); - } - } - } - } - // Given `A: Foo, A::Bar = RhsTy`, suggest `A: Foo`. - if let [potential_param, potential_assoc] = &full_path.segments[..] { - for (ident, bounds) in generics.params.iter().map(|p| (p.ident, &p.bounds)).chain( - generics.where_clause.predicates.iter().filter_map(|pred| match &pred.kind { - WherePredicateKind::BoundPredicate(p) - if let ast::TyKind::Path(None, path) = &p.bounded_ty.kind - && let [segment] = &path.segments[..] => - { - Some((segment.ident, &p.bounds)) - } - _ => None, - }), - ) { - if ident == potential_param.ident { - for bound in bounds { - if let ast::GenericBound::Trait(poly) = bound - && poly.modifiers == TraitBoundModifiers::NONE - { - suggest(poly, potential_assoc, predicate); - } - } - } - } - } - } - this.dcx().emit_err(err); -} - pub fn check_crate( sess: &Session, features: &Features, diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index a6b75cb70a548..89284ca3524fd 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -878,49 +878,6 @@ pub(crate) struct PatternInBodiless { pub span: Span, } -#[derive(Diagnostic)] -#[diag("equality constraints are not yet supported in `where` clauses")] -#[note("see issue #20041 for more information")] -pub(crate) struct EqualityInWhere { - #[primary_span] - #[label("not supported")] - pub span: Span, - #[subdiagnostic] - pub assoc: Option, - #[subdiagnostic] - pub assoc2: Option, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "if `{$ident}` is an associated type you're trying to set, use the associated type binding syntax", - code = "{param}: {path}", - style = "verbose", - applicability = "maybe-incorrect" -)] -pub(crate) struct AssociatedSuggestion { - #[primary_span] - pub span: Span, - pub ident: Ident, - pub param: Ident, - pub path: String, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "if `{$trait_segment}::{$potential_assoc}` is an associated type you're trying to set, use the associated type binding syntax", - applicability = "maybe-incorrect" -)] -pub(crate) struct AssociatedSuggestion2 { - #[suggestion_part(code = "{args}")] - pub span: Span, - pub args: String, - #[suggestion_part(code = "")] - pub predicate: Span, - pub trait_segment: Ident, - pub potential_assoc: Ident, -} - #[derive(Diagnostic)] #[diag("`#![feature]` may not be used on the {$channel} release channel", code = E0554)] pub(crate) struct FeatureOnNonNightly { diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index 820c49cd0612c..86fb0e62bdaa4 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -869,14 +869,6 @@ impl<'a> State<'a> { self.print_lifetime_bounds(bounds); } } - ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } } } diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 43399b614b50a..80296a43ee490 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -396,8 +396,7 @@ impl<'a> ast::mut_visit::MutVisitor for TypeSubstitution<'a> { self.visit_param_bound(bound, BoundKind::Bound) } } - rustc_ast::WherePredicateKind::RegionPredicate(_) - | rustc_ast::WherePredicateKind::EqPredicate(_) => {} + rustc_ast::WherePredicateKind::RegionPredicate(_) => {} } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ab2fa550c4f9a..53141dcc5042f 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1193,8 +1193,6 @@ pub enum WherePredicateKind<'hir> { BoundPredicate(WhereBoundPredicate<'hir>), /// A lifetime predicate (e.g., `'a: 'b + 'c`). RegionPredicate(WhereRegionPredicate<'hir>), - /// An equality predicate (unsupported). - EqPredicate(WhereEqPredicate<'hir>), } impl<'hir> WherePredicateKind<'hir> { @@ -1202,7 +1200,6 @@ impl<'hir> WherePredicateKind<'hir> { match self { WherePredicateKind::BoundPredicate(p) => p.origin == PredicateOrigin::WhereClause, WherePredicateKind::RegionPredicate(p) => p.in_where_clause, - WherePredicateKind::EqPredicate(_) => false, } } @@ -1210,7 +1207,6 @@ impl<'hir> WherePredicateKind<'hir> { match self { WherePredicateKind::BoundPredicate(p) => p.bounds, WherePredicateKind::RegionPredicate(p) => p.bounds, - WherePredicateKind::EqPredicate(_) => &[], } } } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 85f0e97a0a9d6..b0c6a136ba29f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1200,10 +1200,6 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( try_visit!(visitor.visit_lifetime(lifetime)); walk_list!(visitor, visit_param_bound, bounds); } - WherePredicateKind::EqPredicate(WhereEqPredicate { ref lhs_ty, ref rhs_ty }) => { - try_visit!(visitor.visit_ty_unambig(lhs_ty)); - try_visit!(visitor.visit_ty_unambig(rhs_ty)); - } } V::Result::output() } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 234231ed37fed..964f801e53819 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1202,7 +1202,6 @@ pub(super) fn check_number_of_early_bound_regions<'tcx>( } } } - _ => {} } } if let Some(impl_node) = tcx.hir_get_if_local(impl_def_id.into()) @@ -1225,7 +1224,6 @@ pub(super) fn check_number_of_early_bound_regions<'tcx>( } } } - _ => {} } } if impl_bounds == bounds_span.len() { diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index cf29a76418792..01e78fbd2f63e 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -322,10 +322,6 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen (pred, span) })) } - - hir::WherePredicateKind::EqPredicate(..) => { - // FIXME(#20041) - } } } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 3e48bfe4bc252..adc8be18a0adb 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -999,12 +999,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.visit_lifetime(lifetime); walk_list!(self, visit_param_bound, bounds); } - &hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.visit_ty_unambig(lhs_ty); - self.visit_ty_unambig(rhs_ty); - } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 637ae115131a1..0204c4c9ab5fa 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2530,14 +2530,6 @@ impl<'a> State<'a> { } } } - hir::WherePredicateKind::EqPredicate(hir::WhereEqPredicate { - lhs_ty, rhs_ty, .. - }) => { - self.print_type(lhs_ty); - self.space(); - self.word_space("="); - self.print_type(rhs_ty); - } } } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2c7ccfb25ae9b..df78f854ca500 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2141,7 +2141,6 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { } } } - _ => continue, }; if relevant_lifetimes.is_empty() { continue; diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 969c8548f68b4..e2df607fd0f86 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -2,7 +2,7 @@ use rustc_ast::{ self as ast, AttrVec, DUMMY_NODE_ID, GenericBounds, GenericParam, GenericParamKind, TyKind, WhereClause, token, }; -use rustc_errors::{Applicability, PResult}; +use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::ThinVec; @@ -592,25 +592,47 @@ impl<'a> Parser<'a> { // * `for<'a> for<'b> Trait1<'a, 'b>: Trait2<'a /* ok */, 'b /* not ok */>` let (bound_vars, _) = self.parse_higher_ranked_binder()?; - // Parse type with mandatory colon and (possibly empty) bounds, - // or with mandatory equality sign and the second type. let ty = self.parse_ty_for_where_clause()?; + if self.eat(exp!(Colon)) { + // The bounds may be empty; we intentionally accept predicates like `Ty:`. let bounds = self.parse_generic_bounds()?; - Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { + + return Ok(ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate { bound_generic_params: bound_vars, bounded_ty: ty, bounds, - })) - // FIXME: Decide what should be used here, `=` or `==`. - // FIXME: We are just dropping the binders in lifetime_defs on the floor here. - } else if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) { + })); + } + + // NOTE: If we ever end up impl'ing and stabilizing equality predicates (#20041), + // we need to pick between `=` and `==`, both is not an option! + if self.eat(exp!(Eq)) || self.eat(exp!(EqEq)) { + let lhs_ty = ty; let rhs_ty = self.parse_ty()?; - Ok(ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { lhs_ty: ty, rhs_ty })) - } else { - self.maybe_recover_bounds_doubled_colon(&ty)?; - self.unexpected_any() + + // NOTE: If we ever end up impl'ing equality predicates, + // we ought to track the binder in the AST node! + let _ = bound_vars; + + let mut diag = self.dcx().struct_span_err( + lhs_ty.span.to(rhs_ty.span), + "general type equality constraints are not supported", + ); + diag.note( + "see issue #20041 \ + for more information", + ); + diag.span(lhs_ty.span.to(rhs_ty.span)); + diag.span_label(lhs_ty.span.to(rhs_ty.span), "not supported"); + + suggest_replacing_equality_pred_with_assoc_item_constraint(&mut diag, *lhs_ty, *rhs_ty); + + return Err(diag); } + + self.maybe_recover_bounds_doubled_colon(&ty)?; + self.unexpected_any() } pub(super) fn choose_generics_over_qpath(&self, start: usize) -> bool { @@ -644,3 +666,61 @@ impl<'a> Parser<'a> { || self.is_keyword_ahead(start + 1, &[kw::Const])) } } + +fn suggest_replacing_equality_pred_with_assoc_item_constraint( + diag: &mut Diag<'_>, + lhs_ty: ast::Ty, + rhs_ty: ast::Ty, +) { + let TyKind::Path(qself, ast::Path { segments, .. }) = lhs_ty.kind else { return }; + + let mut parts = Vec::new(); + let applicability = match qself { + // We have something like `Ty::Item = Rhs`. + None if let [self_ty_seg, assoc_item_seg] = &segments[..] + && self_ty_seg.ident.name != kw::PathRoot => + { + parts.push(( + self_ty_seg.span().between(assoc_item_seg.span()), + ": /* Trait */ { + parts.push((lhs_ty.span.until(qself.ty.span), String::new())); + + // We have something like ` as self::Trait>::Item = Rhs`. + if let trait_segs @ [.., final_trait_seg] = &segments[..qself.position] { + parts.push((qself.ty.span.between(trait_segs[0].span()), ": ".into())); + let (span, snippet) = match &final_trait_seg.args { + Some(args) => { + let ast::GenericArgs::AngleBracketed(args) = args else { return }; + let Some(args) = args.args.last() else { return }; + (args.span(), ", ") + } + None => (final_trait_seg.span(), "<"), + }; + parts.push((span.between(assoc_item_seg.span()), snippet.into())); + Applicability::MaybeIncorrect + } + // We have something like `<[u8]>::Item == Rhs`. + else { + parts.push(( + qself.ty.span.between(assoc_item_seg.span()), + ": /* Trait */ return, + }; + + parts.push((lhs_ty.span.between(rhs_ty.span), " = ".into())); + parts.push((rhs_ty.span.shrink_to_hi(), ">".into())); + + diag.multipart_suggestion( + "replace it with an associated item constraint if possible", + parts, + applicability, + ); +} diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 9127e4936803d..2f3fbc28ad49d 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -430,7 +430,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_where_predicate(&mut self, p: &'v hir::WherePredicate<'v>) { record_variants!( (self, p, p.kind, Some(p.hir_id), hir, WherePredicate, WherePredicateKind), - [BoundPredicate, RegionPredicate, EqPredicate] + [BoundPredicate, RegionPredicate] ); hir_visit::walk_where_predicate(self, p) } @@ -705,7 +705,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_where_predicate(&mut self, p: &'v ast::WherePredicate) { record_variants!( (self, p, &p.kind, None, ast, WherePredicate, WherePredicateKind), - [BoundPredicate, RegionPredicate, EqPredicate] + [BoundPredicate, RegionPredicate] ); ast_visit::walk_where_predicate(self, p) } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7442ec99d90eb..c2fd72e96b2de 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -417,15 +417,10 @@ fn clean_where_predicate<'tcx>( bound_params, } } - hir::WherePredicateKind::RegionPredicate(wrp) => WherePredicate::RegionPredicate { lifetime: clean_lifetime(wrp.lifetime, cx), bounds: wrp.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), }, - - // We should never actually reach this case because these predicates should've already been - // rejected in an earlier compiler pass. This feature isn't fully implemented (#20041). - hir::WherePredicateKind::EqPredicate(_) => bug!("EqPredicate"), }) } @@ -530,7 +525,7 @@ fn clean_projection_predicate<'tcx>( pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>, cx: &mut DocContext<'tcx>, ) -> WherePredicate { - WherePredicate::EqPredicate { + WherePredicate::ProjectionPredicate { lhs: clean_projection(pred.map_bound(|p| p.projection_term), cx, None), rhs: clean_middle_term(pred.map_bound(|p| p.term), cx), } @@ -797,8 +792,8 @@ pub(crate) fn clean_generics<'tcx>( } } } - WherePredicate::EqPredicate { lhs, rhs } => { - eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs }); + WherePredicate::ProjectionPredicate { lhs, rhs } => { + eq_predicates.push(WherePredicate::ProjectionPredicate { lhs, rhs }); } } } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index a5b5660589f29..fecbc913771b2 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -40,7 +40,7 @@ pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec) -> ThinVec { lifetimes.push((lifetime, bounds)); } - WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)), + WP::ProjectionPredicate { lhs, rhs } => equalities.push((lhs, rhs)), } } @@ -61,7 +61,7 @@ pub(crate) fn where_clauses(tcx: TyCtxt<'_>, clauses: ThinVec) -> ThinVec, bound_params: Vec }, RegionPredicate { lifetime: Lifetime, bounds: Vec }, - EqPredicate { lhs: QPathData, rhs: Term }, + ProjectionPredicate { lhs: QPathData, rhs: Term }, } impl WherePredicate { diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 0b94d2bf1e641..8172ef1848e80 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -138,7 +138,7 @@ fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) -> } Ok(()) } - clean::WherePredicate::EqPredicate { lhs, rhs } => { + clean::WherePredicate::ProjectionPredicate { lhs, rhs } => { let opts = WithOpts::from(f); write!( f, diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 84faa98384cc4..d2bf6900c276d 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -497,7 +497,7 @@ impl FromClean for WherePredicate { }) .collect(), }, - EqPredicate { lhs, rhs } => WherePredicate::EqPredicate { + ProjectionPredicate { lhs, rhs } => WherePredicate::EqPredicate { // The LHS currently has type `Type` but it should be a `QualifiedPath` since it may // refer to an associated const. However, `EqPredicate` shouldn't exist in the first // place: . diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index ea99b523f09b0..8b50ce279b4b1 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -551,14 +551,6 @@ fn has_where_lifetimes<'tcx>(cx: &LateContext<'tcx>, generics: &'tcx Generics<'_ } } }, - WherePredicateKind::EqPredicate(ref pred) => { - let mut visitor = RefVisitor::new(cx); - walk_unambig_ty(&mut visitor, pred.lhs_ty); - walk_unambig_ty(&mut visitor, pred.rhs_ty); - if !visitor.lts.is_empty() { - return true; - } - }, } } false diff --git a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs index 5b6b4f112455a..8b02c4865d138 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_bound_locations.rs @@ -69,7 +69,6 @@ impl EarlyLintPass for MultipleBoundLocations { emit_lint(cx, *bound_span, pred.lifetime.ident.span); } }, - WherePredicateKind::EqPredicate(_) => {}, } } } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index e0a182523f673..fa93cf208c9d9 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -787,7 +787,6 @@ fn eq_where_predicate(l: &WherePredicate, r: &WherePredicate) -> bool { (RegionPredicate(l), RegionPredicate(r)) => { eq_id(l.lifetime.ident, r.lifetime.ident) && over(&l.bounds, &r.bounds, eq_generic_bound) }, - (EqPredicate(l), EqPredicate(r)) => eq_ty(&l.lhs_ty, &r.lhs_ty) && eq_ty(&l.rhs_ty, &r.rhs_ty), _ => false, } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 7590090f9be40..38724a1053f65 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -301,9 +301,6 @@ impl HirEqInterExpr<'_, '_, '_> { Self::eq_lifetime(l_region.lifetime, r_region.lifetime) && self.eq_generics_bound(l_region.bounds, r_region.bounds) }, - (WherePredicateKind::EqPredicate(l_eq), WherePredicateKind::EqPredicate(r_eq)) => { - self.eq_ty(l_eq.lhs_ty, r_eq.lhs_ty) - }, _ => false, }) } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index e574a9d278265..2dfb5e5b28f61 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -484,16 +484,6 @@ impl Rewrite for ast::WherePredicate { ref lifetime, ref bounds, }) => rewrite_bounded_lifetime(lifetime, bounds, self.span, context, shape)?, - ast::WherePredicateKind::EqPredicate(ast::WhereEqPredicate { - ref lhs_ty, - ref rhs_ty, - .. - }) => { - let lhs_ty_str = lhs_ty - .rewrite_result(context, shape) - .map(|lhs| lhs + " =")?; - rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)? - } }; let mut result = String::with_capacity(attrs_str.len() + pred_str.len() + 1); diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs index b757521e0a452..0072c4c0f2b8b 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.rs @@ -29,12 +29,7 @@ fn paint(c: C, d: C::Color) { //~^ ERROR ambiguous associated type `Color` in bounds of `C` } -fn dent_object_2(c: &dyn BoxCar) where ::Color = COLOR { - //~^ ERROR the value of the associated types - //~| ERROR equality constraints are not yet supported in `where` clauses -} - -fn dent_object_3(c: X) +fn dent_object_2(c: X) where X: BoxCar, X: Vehicle, X: Box diff --git a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr index 063623ebd123f..78a6d02611682 100644 --- a/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr +++ b/tests/ui/associated-types/associated-type-projection-from-multiple-supertraits.stderr @@ -1,11 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:47 - | -LL | fn dent_object_2(c: &dyn BoxCar) where ::Color = COLOR { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information - error[E0221]: ambiguous associated type `Color` in bounds of `C` --> $DIR/associated-type-projection-from-multiple-supertraits.rs:19:32 | @@ -84,21 +76,7 @@ LL - fn paint(c: C, d: C::Color) { LL + fn paint(c: C, d: ::Color) { | -error[E0191]: the value of the associated types `Color` in `Box`, `Color` in `Vehicle` must be specified - --> $DIR/associated-type-projection-from-multiple-supertraits.rs:32:33 - | -LL | type Color; - | ---------- `Vehicle::Color` defined here -... -LL | type Color; - | ---------- `Box::Color` defined here -... -LL | fn dent_object_2(c: &dyn BoxCar) where ::Color = COLOR { - | ^^^^^^ associated types `Color` (from trait `Vehicle`), `Color` (from trait `Box`) must be specified - | - = help: consider introducing a new type parameter, adding `where` constraints using the fully-qualified path to the associated types - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0191, E0221, E0222. For more information about an error, try `rustc --explain E0191`. diff --git a/tests/ui/generic-associated-types/equality-bound.rs b/tests/ui/generic-associated-types/equality-bound.rs deleted file mode 100644 index c136a6d4bdf2e..0000000000000 --- a/tests/ui/generic-associated-types/equality-bound.rs +++ /dev/null @@ -1,82 +0,0 @@ -fn sum>(i: I) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses - panic!() -} -fn sum2(i: I) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses - panic!() -} -fn sum3(i: J) -> i32 where I::Item = i32 { -//~^ ERROR equality constraints are not yet supported in `where` clauses -//~| ERROR cannot find type `I` - panic!() -} - -use std::iter::FromIterator; - -struct X {} - -impl FromIterator for X { - fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct Y {} - -impl FromIterator for Y { - fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct Z {} - -impl FromIterator for Z { - fn from_iter(_: T) -> Self where IntoIterator::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct K {} - -impl FromIterator for K { - fn from_iter(_: T) -> Self where T::Item = A, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct L {} - -impl FromIterator for L { - fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} - -struct M {} - -impl FromIterator for M { - fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, - //~^ ERROR equality constraints are not yet supported in `where` clauses - //~| ERROR cannot find type `A` in this scope - { - todo!() - } -} -fn main() {} diff --git a/tests/ui/generic-associated-types/equality-bound.stderr b/tests/ui/generic-associated-types/equality-bound.stderr deleted file mode 100644 index 0ceb5e329ab3a..0000000000000 --- a/tests/ui/generic-associated-types/equality-bound.stderr +++ /dev/null @@ -1,218 +0,0 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:1:51 - | -LL | fn sum>(i: I) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn sum>(i: I) -> i32 where I::Item = i32 { -LL + fn sum>(i: I) -> i32 { - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:5:41 - | -LL | fn sum2(i: I) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `Iterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn sum2(i: I) -> i32 where I::Item = i32 { -LL + fn sum2>(i: I) -> i32 { - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:9:41 - | -LL | fn sum3(i: J) -> i32 where I::Item = i32 { - | ^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:20:58 - | -LL | fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:31:58 - | -LL | fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:42:55 - | -LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, -LL + fn from_iter>(_: T) -> Self - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:53:55 - | -LL | fn from_iter(_: T) -> Self where T::Item = A, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where T::Item = A, -LL + fn from_iter>(_: T) -> Self - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:64:41 - | -LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, - | - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/equality-bound.rs:75:41 - | -LL | fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, - | ^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax - | -LL - fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:20:79 - | -LL | fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = A, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, IntoIterator::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:31:68 - | -LL | fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = A, -LL + fn from_iter(_: T) -> Self where T: IntoIterator, T::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:42:76 - | -LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, - | ^ -... -LL | struct K {} - | -------- similarly named struct `K` defined here - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, -LL + fn from_iter(_: T) -> Self where IntoIterator::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:53:65 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter(_: T) -> Self where T::Item = A, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where T::Item = A, -LL + fn from_iter(_: T) -> Self where T::Item = K, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:64:62 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where IntoIterator::Item = A, T: IntoIterator, -LL + fn from_iter(_: T) -> Self where IntoIterator::Item = K, T: IntoIterator, - | - -error[E0425]: cannot find type `A` in this scope - --> $DIR/equality-bound.rs:75:51 - | -LL | struct K {} - | -------- similarly named struct `K` defined here -... -LL | fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, - | ^ - | -help: a struct with a similar name exists - | -LL - fn from_iter(_: T) -> Self where T::Item = A, T: IntoIterator, -LL + fn from_iter(_: T) -> Self where T::Item = K, T: IntoIterator, - | - -error[E0433]: cannot find type `I` in this scope - --> $DIR/equality-bound.rs:9:41 - | -LL | fn sum3(i: J) -> i32 where I::Item = i32 { - | ^ use of undeclared type `I` - | -help: a type parameter with a similar name exists - | -LL - fn sum3(i: J) -> i32 where I::Item = i32 { -LL + fn sum3(i: J) -> i32 where J::Item = i32 { - | - -error: aborting due to 16 previous errors - -Some errors have detailed explanations: E0425, E0433. -For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/generic-associated-types/missing-bounds.fixed b/tests/ui/generic-associated-types/missing-bounds.fixed index 15cdd44d7f1f9..7735031233340 100644 --- a/tests/ui/generic-associated-types/missing-bounds.fixed +++ b/tests/ui/generic-associated-types/missing-bounds.fixed @@ -36,12 +36,11 @@ impl> Add for D { struct E(B); -impl> Add for E where B: Add { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/tests/ui/generic-associated-types/missing-bounds.rs b/tests/ui/generic-associated-types/missing-bounds.rs index dad111c8c15cf..0957674d83d2b 100644 --- a/tests/ui/generic-associated-types/missing-bounds.rs +++ b/tests/ui/generic-associated-types/missing-bounds.rs @@ -36,12 +36,11 @@ impl Add for D { struct E(B); -impl Add for E where ::Output = B { - //~^ ERROR equality constraints are not yet supported in `where` clauses +impl Add for E where B: Add { type Output = Self; fn add(self, rhs: Self) -> Self { - Self(self.0 + rhs.0) //~ ERROR mismatched types + Self(self.0 + rhs.0) } } diff --git a/tests/ui/generic-associated-types/missing-bounds.stderr b/tests/ui/generic-associated-types/missing-bounds.stderr index 97b88c26e3b38..b930cfb3f806b 100644 --- a/tests/ui/generic-associated-types/missing-bounds.stderr +++ b/tests/ui/generic-associated-types/missing-bounds.stderr @@ -1,16 +1,3 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/missing-bounds.rs:39:33 - | -LL | impl Add for E where ::Output = B { - | ^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information -help: if `Output` is an associated type you're trying to set, use the associated type binding syntax - | -LL - impl Add for E where ::Output = B { -LL + impl Add for E where B: Add { - | - error[E0308]: mismatched types --> $DIR/missing-bounds.rs:13:11 | @@ -77,30 +64,7 @@ help: consider restricting type parameter `B` with trait `Add` LL | impl> Add for D { | +++++++++++++++++++++++++++ -error[E0308]: mismatched types - --> $DIR/missing-bounds.rs:44:14 - | -LL | impl Add for E where ::Output = B { - | - expected this type parameter -... -LL | Self(self.0 + rhs.0) - | ---- ^^^^^^^^^^^^^^ expected type parameter `B`, found associated type - | | - | arguments to this function are incorrect - | - = note: expected type parameter `B` - found associated type `::Output` -note: tuple struct defined here - --> $DIR/missing-bounds.rs:37:8 - | -LL | struct E(B); - | ^ -help: consider further restricting this bound - | -LL | impl> Add for E where ::Output = B { - | ++++++++++++ - -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors Some errors have detailed explanations: E0308, E0369. For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/parser/equality-predicates-0.rs b/tests/ui/parser/equality-predicates-0.rs new file mode 100644 index 0000000000000..a720d963c220e --- /dev/null +++ b/tests/ui/parser/equality-predicates-0.rs @@ -0,0 +1,20 @@ +// Test that we syntactically reject *equality predicates*. +// +// It's a feature that was originally proposed as part of accepted RFC 135 (2014). It's never been +// fully implemented and in the meantime design & implementation concerns have been raised. +// Between Feb 2017 and Jun 2026 we accidentally accepted such predicates syntactically +// (indeed, without any pre-expansion feature gate). +// +// We *might* add a more restricted version of this feature to the language in the future. +// See discussions in tracking issue for details. + +#[cfg(false)] +fn f(mut xs: T) -> Option +where + T::Item = u8 + //~^ ERROR general type equality constraints are not supported +{ + xs.next() +} + +fn main() {} diff --git a/tests/ui/parser/equality-predicates-0.stderr b/tests/ui/parser/equality-predicates-0.stderr new file mode 100644 index 0000000000000..f5be5d156e0d9 --- /dev/null +++ b/tests/ui/parser/equality-predicates-0.stderr @@ -0,0 +1,15 @@ +error: general type equality constraints are not supported + --> $DIR/equality-predicates-0.rs:14:5 + | +LL | T::Item = u8 + | ^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: replace it with an associated item constraint if possible + | +LL - T::Item = u8 +LL + T: /* Trait */ + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/equality-predicates-1.rs b/tests/ui/parser/equality-predicates-1.rs new file mode 100644 index 0000000000000..b5dcc565fc208 --- /dev/null +++ b/tests/ui/parser/equality-predicates-1.rs @@ -0,0 +1,20 @@ +// Test that we syntactically reject *equality predicates*. +// +// It's a feature that was originally proposed as part of accepted RFC 135 (2014). It's never been +// fully implemented and in the meantime design & implementation concerns have been raised. +// Between Feb 2017 and Jun 2026 we accidentally accepted such predicates syntactically +// (indeed, without any pre-expansion feature gate). +// +// We *might* add a more restricted version of this feature to the language in the future. +// See discussions in tracking issue for details. + +#[cfg(false)] +fn f(mut xs: T) -> Option +where + ::Item == u8 + //~^ ERROR general type equality constraints are not supported +{ + xs.next() +} + +fn main() {} diff --git a/tests/ui/parser/equality-predicates-1.stderr b/tests/ui/parser/equality-predicates-1.stderr new file mode 100644 index 0000000000000..9e7a0b767239a --- /dev/null +++ b/tests/ui/parser/equality-predicates-1.stderr @@ -0,0 +1,15 @@ +error: general type equality constraints are not supported + --> $DIR/equality-predicates-1.rs:14:5 + | +LL | ::Item == u8 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported + | + = note: see issue #20041 for more information +help: replace it with an associated item constraint if possible + | +LL - ::Item == u8 +LL + T: Iterator + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/where-clauses/where-equality-constraints.rs b/tests/ui/where-clauses/where-equality-constraints.rs deleted file mode 100644 index 8828f09d92d33..0000000000000 --- a/tests/ui/where-clauses/where-equality-constraints.rs +++ /dev/null @@ -1,6 +0,0 @@ -fn f() where u8 = u16 {} -//~^ ERROR equality constraints are not yet supported in `where` clauses -fn g() where for<'a> &'static (u8,) == u16, {} -//~^ ERROR equality constraints are not yet supported in `where` clauses - -fn main() {} diff --git a/tests/ui/where-clauses/where-equality-constraints.stderr b/tests/ui/where-clauses/where-equality-constraints.stderr deleted file mode 100644 index 9d8fac02ed33b..0000000000000 --- a/tests/ui/where-clauses/where-equality-constraints.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error: equality constraints are not yet supported in `where` clauses - --> $DIR/where-equality-constraints.rs:1:14 - | -LL | fn f() where u8 = u16 {} - | ^^^^^^^^ not supported - | - = note: see issue #20041 for more information - -error: equality constraints are not yet supported in `where` clauses - --> $DIR/where-equality-constraints.rs:3:14 - | -LL | fn g() where for<'a> &'static (u8,) == u16, {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not supported - | - = note: see issue #20041 for more information - -error: aborting due to 2 previous errors -