From 824cc42ec94a38a6444d1effd870f60f066cc667 Mon Sep 17 00:00:00 2001 From: David Tenty Date: Mon, 13 Apr 2026 13:17:03 -0400 Subject: [PATCH 01/11] [AIX] update linker default to bcdtors The bcdtor mode affects how the AIX linker choose to pull in static constructors and destructors (https://www.ibm.com/docs/en/aix/7.2.0?topic=l-ld-command) to the link. The current setting of all makes static init in archive members live regardless of if the archive member would be otherwise referenced, causing that whole archive member to become part of the link. This default was initially retained for compatibility purposes with historical compilers on the platform which defaulted to this setting. Unfortunately this greedy pulling in of static init can have unintended consequences for applications, for example for programs linked against parts of compiler-rt which contain optional instrumentation (containing static initializers) which may be unused as these now become live in all programs regardless of use. For that reason and similar reasons, this PR switches the default to mbr, which only extracts static init from archive members which would otherwise be referenced. This gives a behaviour very consistent with linkers on other platforms (e.g. Linux). Users requiring the old default behaviour can manually pass -bcdtors:all on the link step which will override any default we pass here. --- compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs index b4f394643a9dd..e333be454da3b 100644 --- a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs +++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs @@ -5,7 +5,7 @@ pub(crate) fn target() -> Target { base.max_atomic_width = Some(64); base.add_pre_link_args( LinkerFlavor::Unix(Cc::No), - &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:all:0:s"], + &["-b64", "-bpT:0x100000000", "-bpD:0x110000000", "-bcdtors:mbr:0:s"], ); Target { From c81ff33d1b047e18706d70754639e09a43411c1e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 16 Apr 2026 15:20:37 +1000 Subject: [PATCH 02/11] Add test demonstrating a bug in `ChunkedBitSet::subtract`. It results in `b64` having many fewer bits set than it should. LLM disclosure: this bug was identified by Claude Code. I did everything else. --- compiler/rustc_index/src/bit_set/tests.rs | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index c6d211f3039b1..bbbf07036209f 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -333,6 +333,33 @@ fn chunked_bitset() { assert_eq!(b10000.count(), 6000); b10000.assert_valid(); b10000b.assert_valid(); + + //----------------------------------------------------------------------- + + let mut b64 = ChunkedBitSet::::new_filled(64); + + let mut b64b = ChunkedBitSet::::new_empty(64); + b64b.insert(0); + + b64.subtract(&b64b); + assert!(!b64.contains(0)); + assert!(!b64.contains(10)); // FIXME + assert!(!b64.contains(50)); // FIXME + assert!(b64.contains(63)); + assert_eq!( + b64.chunks(), + #[rustfmt::skip] + vec![ + Mixed { + chunk_domain_size: 64, + ones_count: 63, + words: Rc::new([ // FIXME + 0x8000000000000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]) + }, + ], + ); } fn with_elements_chunked(elements: &[usize], domain_size: usize) -> ChunkedBitSet { From 3f9dbf2a97590a180a50399c4edfdc9d693376de Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 16 Apr 2026 15:36:06 +1000 Subject: [PATCH 03/11] Fix bug in `ChunkedBitSet::subtract`. It does a masking operation but the mask is computed incorrectly due to operator precedence. The mask is of the form `1 << N - 1` but it should be `(1 << N) - 1` because `-` binds tighter than `1 << N`. This commit fixes the problem, not by adjusting the precedence, but by instead using the existing `clear_excess_bits_in_final_word`, which is consistent with other similar operations. LLM disclosure: this bug was identified by Claude Code. I did everything else. --- compiler/rustc_index/src/bit_set.rs | 13 ++++++++----- compiler/rustc_index/src/bit_set/tests.rs | 8 ++++---- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs index 2c5668e22f389..f486ab48ec219 100644 --- a/compiler/rustc_index/src/bit_set.rs +++ b/compiler/rustc_index/src/bit_set.rs @@ -835,13 +835,16 @@ impl BitRelations> for ChunkedBitSet { changed = true; let num_words = num_words(*chunk_domain_size as usize); debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS); - let mut tail_mask = - 1 << (*chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1; + // Set `self_chunk_words` to `other_chunk_words`, then invert all bits and + // clear any excess bits in the final word. let mut self_chunk_words = **other_chunk_words; - for word in self_chunk_words[0..num_words].iter_mut().rev() { - *word = !*word & tail_mask; - tail_mask = Word::MAX; + for word in self_chunk_words[0..num_words].iter_mut() { + *word = !*word; } + clear_excess_bits_in_final_word( + *chunk_domain_size as usize, + &mut self_chunk_words[..num_words], + ); let self_chunk_ones_count = *chunk_domain_size - *other_chunk_ones_count; debug_assert_eq!( self_chunk_ones_count, diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs index bbbf07036209f..eaf9c62c954f7 100644 --- a/compiler/rustc_index/src/bit_set/tests.rs +++ b/compiler/rustc_index/src/bit_set/tests.rs @@ -343,8 +343,8 @@ fn chunked_bitset() { b64.subtract(&b64b); assert!(!b64.contains(0)); - assert!(!b64.contains(10)); // FIXME - assert!(!b64.contains(50)); // FIXME + assert!(b64.contains(10)); + assert!(b64.contains(50)); assert!(b64.contains(63)); assert_eq!( b64.chunks(), @@ -353,8 +353,8 @@ fn chunked_bitset() { Mixed { chunk_domain_size: 64, ones_count: 63, - words: Rc::new([ // FIXME - 0x8000000000000000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + words: Rc::new([ + 0xfffffffffffffffe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ]) }, From 9854d7e82a3c4305b154883a802f6a395dd2a27c Mon Sep 17 00:00:00 2001 From: SynapLink Date: Sun, 26 Apr 2026 10:06:54 +0200 Subject: [PATCH 04/11] tests: mark migrated UI tests as check-pass --- tests/ui/attributes/attr-before-view-item.rs | 2 +- tests/ui/attributes/attr-before-view-item2.rs | 2 +- tests/ui/attributes/attr-mix-new.rs | 2 +- tests/ui/attributes/class-attributes-1.rs | 2 +- tests/ui/attributes/class-attributes-2.rs | 2 +- tests/ui/attributes/method-attributes.rs | 2 +- tests/ui/attributes/unrestricted-attribute-tokens.rs | 2 +- tests/ui/attributes/variant-attributes.rs | 2 +- tests/ui/conditional-compilation/cfg-attr-multi-false.rs | 2 +- tests/ui/conditional-compilation/cfg-attr-multi-true.rs | 2 +- tests/ui/range/range_traits-4.rs | 2 +- tests/ui/range/range_traits-5.rs | 2 +- tests/ui/range/range_traits-7.rs | 2 +- tests/ui/reachable/expr_andand.rs | 2 +- tests/ui/reachable/expr_oror.rs | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/ui/attributes/attr-before-view-item.rs b/tests/ui/attributes/attr-before-view-item.rs index 19874052e3368..5cc80f4bf1a08 100644 --- a/tests/ui/attributes/attr-before-view-item.rs +++ b/tests/ui/attributes/attr-before-view-item.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![feature(rustc_attrs)] #![feature(test)] diff --git a/tests/ui/attributes/attr-before-view-item2.rs b/tests/ui/attributes/attr-before-view-item2.rs index e58063a13ab0a..eb40b0e6903e8 100644 --- a/tests/ui/attributes/attr-before-view-item2.rs +++ b/tests/ui/attributes/attr-before-view-item2.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![feature(rustc_attrs)] #![feature(test)] diff --git a/tests/ui/attributes/attr-mix-new.rs b/tests/ui/attributes/attr-mix-new.rs index 3ddb1d0d7335c..b03f3cc25ddd7 100644 --- a/tests/ui/attributes/attr-mix-new.rs +++ b/tests/ui/attributes/attr-mix-new.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/class-attributes-1.rs b/tests/ui/attributes/class-attributes-1.rs index 0c8f5f324a3ef..ba41bceb3c71d 100644 --- a/tests/ui/attributes/class-attributes-1.rs +++ b/tests/ui/attributes/class-attributes-1.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass //@ pp-exact - Make sure we actually print the attributes #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/class-attributes-2.rs b/tests/ui/attributes/class-attributes-2.rs index 0ec0cd225969b..875f83cc2da00 100644 --- a/tests/ui/attributes/class-attributes-2.rs +++ b/tests/ui/attributes/class-attributes-2.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/method-attributes.rs b/tests/ui/attributes/method-attributes.rs index ded72d2457b1c..3d7f6f2149882 100644 --- a/tests/ui/attributes/method-attributes.rs +++ b/tests/ui/attributes/method-attributes.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass //@ pp-exact - Make sure we print all the attributes #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/unrestricted-attribute-tokens.rs b/tests/ui/attributes/unrestricted-attribute-tokens.rs index 9f91afb59bf81..9a0bb21c79666 100644 --- a/tests/ui/attributes/unrestricted-attribute-tokens.rs +++ b/tests/ui/attributes/unrestricted-attribute-tokens.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/variant-attributes.rs b/tests/ui/attributes/variant-attributes.rs index a08856aa278d3..7020bdaf2557e 100644 --- a/tests/ui/attributes/variant-attributes.rs +++ b/tests/ui/attributes/variant-attributes.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass //@ pp-exact - Make sure we actually print the attributes #![allow(non_camel_case_types)] diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-false.rs b/tests/ui/conditional-compilation/cfg-attr-multi-false.rs index 871c1b81acd26..b323bc6bef2ab 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-false.rs +++ b/tests/ui/conditional-compilation/cfg-attr-multi-false.rs @@ -1,7 +1,7 @@ // Test that cfg_attr doesn't emit any attributes when the // configuration variable is false. This mirrors `cfg-attr-multi-true.rs` -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![warn(unused_must_use)] diff --git a/tests/ui/conditional-compilation/cfg-attr-multi-true.rs b/tests/ui/conditional-compilation/cfg-attr-multi-true.rs index 24950c8d42341..f4ddc6c89bc3a 100644 --- a/tests/ui/conditional-compilation/cfg-attr-multi-true.rs +++ b/tests/ui/conditional-compilation/cfg-attr-multi-true.rs @@ -2,7 +2,7 @@ // This is done by emitting two attributes that cause new warnings, and then // triggering those warnings. -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![warn(unused_must_use)] diff --git a/tests/ui/range/range_traits-4.rs b/tests/ui/range/range_traits-4.rs index 4241325e1d9af..39948bebe0be6 100644 --- a/tests/ui/range/range_traits-4.rs +++ b/tests/ui/range/range_traits-4.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass use std::ops::*; diff --git a/tests/ui/range/range_traits-5.rs b/tests/ui/range/range_traits-5.rs index a15ea6a711296..0c737c964bcde 100644 --- a/tests/ui/range/range_traits-5.rs +++ b/tests/ui/range/range_traits-5.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass use std::ops::*; diff --git a/tests/ui/range/range_traits-7.rs b/tests/ui/range/range_traits-7.rs index 95e101b0988cf..2648a7f023deb 100644 --- a/tests/ui/range/range_traits-7.rs +++ b/tests/ui/range/range_traits-7.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass use std::ops::*; diff --git a/tests/ui/reachable/expr_andand.rs b/tests/ui/reachable/expr_andand.rs index 40a8c72e52249..f623aa55a94b4 100644 --- a/tests/ui/reachable/expr_andand.rs +++ b/tests/ui/reachable/expr_andand.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![allow(unused_variables)] #![allow(dead_code)] diff --git a/tests/ui/reachable/expr_oror.rs b/tests/ui/reachable/expr_oror.rs index 4ee4b80744285..c5426b55b002a 100644 --- a/tests/ui/reachable/expr_oror.rs +++ b/tests/ui/reachable/expr_oror.rs @@ -1,4 +1,4 @@ -//@ build-pass (FIXME(62277): could be check-pass?) +//@ check-pass #![allow(unused_variables)] #![allow(dead_code)] From 34e1e172b256676c7404124e63527812e7893500 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 27 Apr 2026 00:31:51 +0200 Subject: [PATCH 05/11] Don't reload length in String::push Same as in Vec::push_mut, we get `.len()` once at the start since it won't change in the `reserve()` call. Saves reloading the length after the allocation: https://godbolt.org/z/W3G165Gd7 --- library/alloc/src/string.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 30e52f3e1be46..4e97dfd2d561e 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -1420,7 +1420,7 @@ impl String { // SAFETY: Just reserved capacity for at least the length needed to encode `ch`. unsafe { - core::char::encode_utf8_raw_unchecked(ch as u32, self.vec.as_mut_ptr().add(self.len())); + core::char::encode_utf8_raw_unchecked(ch as u32, self.vec.as_mut_ptr().add(len)); self.vec.set_len(len + ch_len); } } From 49a490ec09af2f4810c7fd8b0d6ca20410efacf4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 27 Apr 2026 15:04:50 +0200 Subject: [PATCH 06/11] enable pipe tests in Miri --- library/std/src/io/pipe.rs | 6 ------ library/std/src/io/pipe/tests.rs | 1 - 2 files changed, 7 deletions(-) diff --git a/library/std/src/io/pipe.rs b/library/std/src/io/pipe.rs index 61b81cf074a6e..e05ccb32a122d 100644 --- a/library/std/src/io/pipe.rs +++ b/library/std/src/io/pipe.rs @@ -40,8 +40,6 @@ use crate::sys::{FromInner, IntoInner, pipe as imp}; /// # Example /// /// ```no_run -/// # #[cfg(miri)] fn main() {} -/// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { /// use std::io::{Read, Write, pipe}; /// use std::process::Command; @@ -126,8 +124,6 @@ impl PipeReader { /// # Examples /// /// ```no_run - /// # #[cfg(miri)] fn main() {} - /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { /// use std::fs; /// use std::io::{pipe, Write}; @@ -185,8 +181,6 @@ impl PipeWriter { /// # Examples /// /// ```no_run - /// # #[cfg(miri)] fn main() {} - /// # #[cfg(not(miri))] /// # fn main() -> std::io::Result<()> { /// use std::process::Command; /// use std::io::{pipe, Read}; diff --git a/library/std/src/io/pipe/tests.rs b/library/std/src/io/pipe/tests.rs index f113b157459d3..2c2d35cc63d9e 100644 --- a/library/std/src/io/pipe/tests.rs +++ b/library/std/src/io/pipe/tests.rs @@ -1,7 +1,6 @@ use crate::io::{Read, Write, pipe}; #[test] -#[cfg(all(any(unix, windows), not(miri)))] fn pipe_creation_clone_and_rw() { let (rx, tx) = pipe().unwrap(); From 612afd1b49950d38fddbe52b3efec862a677928d Mon Sep 17 00:00:00 2001 From: SangHun Kim Date: Mon, 27 Apr 2026 23:27:14 +0900 Subject: [PATCH 07/11] Add regression test --- .../const-eval/static-promotion-issue-101363.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 tests/ui/consts/const-eval/static-promotion-issue-101363.rs diff --git a/tests/ui/consts/const-eval/static-promotion-issue-101363.rs b/tests/ui/consts/const-eval/static-promotion-issue-101363.rs new file mode 100644 index 0000000000000..ff17377757653 --- /dev/null +++ b/tests/ui/consts/const-eval/static-promotion-issue-101363.rs @@ -0,0 +1,11 @@ +//@ check-pass +// Regression test for + +const OPTIONAL_SLICE_V1: Option<&'static [u8]> = Some(&{ + let array = [1, 2, 3]; + array +}); + +fn main() { + let _ = OPTIONAL_SLICE_V1; +} From d7184b76a74f495c6f4af7b9c69129f4fe59bfdb Mon Sep 17 00:00:00 2001 From: SynapLink Date: Mon, 27 Apr 2026 20:43:24 +0200 Subject: [PATCH 08/11] tests: remove obsolete class attribute tests --- tests/ui/attributes/class-attributes-1.rs | 19 -------------- tests/ui/attributes/class-attributes-2.rs | 31 ----------------------- 2 files changed, 50 deletions(-) delete mode 100644 tests/ui/attributes/class-attributes-1.rs delete mode 100644 tests/ui/attributes/class-attributes-2.rs diff --git a/tests/ui/attributes/class-attributes-1.rs b/tests/ui/attributes/class-attributes-1.rs deleted file mode 100644 index ba41bceb3c71d..0000000000000 --- a/tests/ui/attributes/class-attributes-1.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ check-pass -//@ pp-exact - Make sure we actually print the attributes - -#![feature(rustc_attrs)] - -struct Cat { - name: String, -} - -impl Drop for Cat { - #[rustc_dummy] - fn drop(&mut self) { println!("{} landed on hir feet" , self . name); } -} - - -#[rustc_dummy] -fn cat(name: String) -> Cat { Cat{name: name,} } - -fn main() { let _kitty = cat("Spotty".to_string()); } diff --git a/tests/ui/attributes/class-attributes-2.rs b/tests/ui/attributes/class-attributes-2.rs deleted file mode 100644 index 875f83cc2da00..0000000000000 --- a/tests/ui/attributes/class-attributes-2.rs +++ /dev/null @@ -1,31 +0,0 @@ -//@ check-pass - -#![feature(rustc_attrs)] - -struct Cat { - name: String, -} - -impl Drop for Cat { - #[rustc_dummy] - /** - Actually, cats don't always land on their feet when you drop them. - */ - fn drop(&mut self) { - println!("{} landed on hir feet", self.name); - } -} - -#[rustc_dummy] -/** -Maybe it should technically be a kitten_maker. -*/ -fn cat(name: String) -> Cat { - Cat { - name: name - } -} - -fn main() { - let _kitty = cat("Spotty".to_string()); -} From b7424bac39776f3fa3a116cae5599b626c204cc5 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 27 Apr 2026 00:06:10 +0000 Subject: [PATCH 09/11] slice::join: borrow only once during length calc This ensures the length calculation will always be self-consistent even if the real length changes when we actually come to use them. --- library/alloc/src/str.rs | 21 +++++++++++---------- library/alloctests/tests/str.rs | 8 ++++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index 98120896bc9b5..1f135a48224f1 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -135,13 +135,9 @@ macro_rules! copy_slice_and_advance { // // This implementation calls `borrow()` multiple times: // 1. To calculate `reserved_len`, all elements are borrowed once. -// 2. The first element is borrowed again when copied via `extend_from_slice`. -// 3. Subsequent elements are borrowed a second time when building the mapped iterator. +// 2. All elements, except the first, are borrowed a second time when building the mapped iterator. // // Risks and Mitigations: -// - If the first element GROWS on the second borrow, the length subtraction underflows. -// We mitigate this by doing a `checked_sub` to panic rather than allowing an underflow -// that fabricates a huge destination slice. // - If elements 2..N GROW on their second borrow, the target slice bounds set by `checked_sub` // means that `split_at_mut` inside `copy_slice_and_advance!` will correctly panic. // - If elements SHRINK on their second borrow, the spare space is never written, and the final @@ -157,8 +153,10 @@ where let mut iter = slice.iter(); // the first slice is the only one without a separator preceding it + // we take care to only borrow this once during the length calculation + // to avoid inconsistent Borrow implementations from breaking our assumptions let first = match iter.next() { - Some(first) => first, + Some(first) => first.borrow().as_ref(), None => return vec![], }; @@ -168,8 +166,11 @@ where // the entire Vec pre-allocated for safety let reserved_len = sep_len .checked_mul(iter.len()) + .and_then(|n| n.checked_add(first.len())) .and_then(|n| { - slice.iter().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add) + // iter starts from the second element as we've already taken the first + // it's cloned so we can reuse the same iterator below + iter.clone().map(|s| s.borrow().as_ref().len()).try_fold(n, usize::checked_add) }) .expect("attempt to join into collection with len > usize::MAX"); @@ -177,12 +178,12 @@ where let mut result = Vec::with_capacity(reserved_len); debug_assert!(result.capacity() >= reserved_len); - result.extend_from_slice(first.borrow().as_ref()); + result.extend_from_slice(first); unsafe { let pos = result.len(); - let target_len = reserved_len.checked_sub(pos).expect("inconsistent Borrow implementation"); - let target = result.spare_capacity_mut().get_unchecked_mut(..target_len); + debug_assert!(reserved_len >= pos); + let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); // Convert the separator and slices to slices of MaybeUninit // to simplify implementation in specialize_for_lengths. diff --git a/library/alloctests/tests/str.rs b/library/alloctests/tests/str.rs index 49baa53c9d3ed..f1bd5325da587 100644 --- a/library/alloctests/tests/str.rs +++ b/library/alloctests/tests/str.rs @@ -164,7 +164,7 @@ fn test_join_for_different_lengths_with_long_separator() { } #[test] -fn test_join_issue_80335() { +fn test_join_inconsistent_borrow_shrink() { use core::borrow::Borrow; use core::cell::Cell; @@ -191,12 +191,12 @@ fn test_join_issue_80335() { } let arr: [WeirdBorrow; 3] = Default::default(); - test_join!("0-0-0", arr, "-"); + test_join!("123456-0-0", arr, "-"); } #[test] -#[should_panic(expected = "inconsistent Borrow implementation")] -fn test_join_inconsistent_borrow() { +#[should_panic(expected = "mid > len")] +fn test_join_inconsistent_borrow_grow() { use std::borrow::Borrow; use std::cell::Cell; From 04874be3a2c7a4ff03dd6ab9472b066c7bc3498e Mon Sep 17 00:00:00 2001 From: Sidney Cammeresi Date: Sun, 26 Apr 2026 19:34:26 -0700 Subject: [PATCH 10/11] Adjust diagnostic items for mpmc/mpsc Receiver and Sender `MpscReceiver` aligns with `MpscSender`. The original name appears to not actually have been in use, for better or worse. Along the way, sprinkle the attribute onto `mpmc::Receiver` and `mpmc::Sender` too. --- library/std/src/sync/mpmc/mod.rs | 2 ++ library/std/src/sync/mpsc.rs | 2 +- src/tools/clippy/clippy_utils/src/sym.rs | 5 ++++- src/tools/clippy/clippy_utils/src/ty/mod.rs | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 16ae8a88370be..a687f39431697 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -297,6 +297,7 @@ pub fn sync_channel(cap: usize) -> (Sender, Receiver) { /// assert_eq!(3, msg + msg2); /// ``` #[unstable(feature = "mpmc_channel", issue = "126840")] +#[cfg_attr(not(test), rustc_diagnostic_item = "MpmcSender")] pub struct Sender { flavor: SenderFlavor, } @@ -722,6 +723,7 @@ impl fmt::Debug for Sender { /// rx_thread_2.join().unwrap(); /// ``` #[unstable(feature = "mpmc_channel", issue = "126840")] +#[cfg_attr(not(test), rustc_diagnostic_item = "MpmcReceiver")] pub struct Receiver { flavor: ReceiverFlavor, } diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index 460ad02c67d2c..8c40f07f0d17d 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -173,7 +173,7 @@ use crate::{error, fmt}; /// println!("{}", recv.recv().unwrap()); // Received after 2 seconds /// ``` #[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "Receiver")] +#[cfg_attr(not(test), rustc_diagnostic_item = "MpscReceiver")] pub struct Receiver { inner: mpmc::Receiver, } diff --git a/src/tools/clippy/clippy_utils/src/sym.rs b/src/tools/clippy/clippy_utils/src/sym.rs index 4eaeafe127078..87aac25f5bd12 100644 --- a/src/tools/clippy/clippy_utils/src/sym.rs +++ b/src/tools/clippy/clippy_utils/src/sym.rs @@ -90,6 +90,10 @@ generate! { MAX, MIN, MaybeDef, + MpmcReceiver, + MpmcSender, + MpscReceiver, + MpscSender, MsrvStack, Octal, OpenOptions, @@ -99,7 +103,6 @@ generate! { PathBuf, PathLookup, RangeBounds, - Receiver, RefCellRef, RefCellRefMut, Regex, diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 5c6fecde238a4..66d85b58eaae4 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -192,7 +192,8 @@ pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option< sym::HashMap, sym::PathBuf, sym::Path, - sym::Receiver, + sym::MpscReceiver, + sym::MpmcReceiver, ]; let ty_to_check = match probably_ref_ty.kind() { From cf8a60c20df5bbb5eb93f64e82fa91b2948a034f Mon Sep 17 00:00:00 2001 From: dianqk Date: Wed, 22 Apr 2026 20:30:52 +0800 Subject: [PATCH 11/11] Update LLVM to 22.1.4 --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 1cb4e3833c191..eaab4d9841b9a 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 1cb4e3833c1919c2e6fb579a23ac0e2b22587b7e +Subproject commit eaab4d9841b9a8a12783d927b2df2291c1c79269