Rollup merge of #151756 - Voultapher:fix-box-retag-in-sort, r=Mark-Simulacrum

Avoid miri error in `slice::sort` under Stacked Borrows

See comment in code.

Fixes: https://github.com/rust-lang/rust/issues/151728
This commit is contained in:
Stuart Cook 2026-02-02 10:28:29 +11:00 committed by GitHub
commit a57663ea65
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 14 additions and 3 deletions

View file

@ -362,6 +362,13 @@ fn sort_vs_sort_by_impl<S: Sort>() {
assert_eq!(input_sort_by, expected);
}
pub fn box_value_impl<S: Sort>() {
for len in [3, 9, 35, 56, 132] {
test_is_sorted::<Box<i32>, S>(len, Box::new, patterns::random);
test_is_sorted::<Box<i32>, S>(len, Box::new, |len| patterns::random_sorted(len, 80.0));
}
}
gen_sort_test_fns_with_default_patterns!(
correct_i32,
|len, pattern_fn| test_is_sorted::<i32, S>(len, |val| val, pattern_fn),
@ -967,6 +974,7 @@ define_instantiate_sort_tests!(
[miri_yes, fixed_seed_rand_vec_prefix],
[miri_yes, int_edge],
[miri_yes, sort_vs_sort_by],
[miri_yes, box_value],
[miri_yes, correct_i32_random],
[miri_yes, correct_i32_random_z1],
[miri_yes, correct_i32_random_d2],

View file

@ -1,6 +1,6 @@
//! This module contains a stable quicksort and partition implementation.
use crate::mem::{ManuallyDrop, MaybeUninit};
use crate::mem::MaybeUninit;
use crate::slice::sort::shared::FreezeMarker;
use crate::slice::sort::shared::pivot::choose_pivot;
use crate::slice::sort::shared::smallsort::StableSmallSortTypeImpl;
@ -41,8 +41,11 @@ pub fn quicksort<T, F: FnMut(&T, &T) -> bool>(
// SAFETY: We only access the temporary copy for Freeze types, otherwise
// self-modifications via `is_less` would not be observed and this would
// be unsound. Our temporary copy does not escape this scope.
let pivot_copy = unsafe { ManuallyDrop::new(ptr::read(&v[pivot_pos])) };
let pivot_ref = (!has_direct_interior_mutability::<T>()).then_some(&*pivot_copy);
// We use `MaybeUninit` to avoid re-tag issues. FIXME: use `MaybeDangling`.
let pivot_copy = unsafe { ptr::read((&raw const v[pivot_pos]).cast::<MaybeUninit<T>>()) };
let pivot_ref =
// SAFETY: We created the value in an init state.
(!has_direct_interior_mutability::<T>()).then_some(unsafe { &*pivot_copy.as_ptr() });
// We choose a pivot, and check if this pivot is equal to our left
// ancestor. If true, we do a partition putting equal elements on the