Skip to content

Commit d20005a

Browse files
committed
Use phantomdata in CopyOnDrop
1 parent 6236214 commit d20005a

File tree

1 file changed

+18
-10
lines changed

1 file changed

+18
-10
lines changed

src/slice/quicksort.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55
//! `rayon_core::join`.
66
77
use std::cmp;
8+
use std::marker::PhantomData;
89
use std::mem::{self, MaybeUninit};
910
use std::ptr;
1011

1112
/// When dropped, copies from `src` into `dest`.
12-
struct CopyOnDrop<T> {
13+
struct CopyOnDrop<'src, 'dest, T> {
1314
src: *const T,
1415
dest: *mut T,
16+
/// `src` is often a local pointer here, make sure we have appropriate
17+
/// PhantomData so that dropck can protect us.
18+
marker: PhantomData<(&'src T, &'dest mut T)>,
1519
}
1620

17-
impl<T> Drop for CopyOnDrop<T> {
21+
impl<T> Drop for CopyOnDrop<'_, '_, T> {
1822
fn drop(&mut self) {
1923
// SAFETY: This is a helper class.
2024
// Please refer to its usage for correctness.
@@ -26,7 +30,7 @@ impl<T> Drop for CopyOnDrop<T> {
2630
}
2731

2832
/// Shifts the first element to the right until it encounters a greater or equal element.
29-
fn shift_head<T, F>(v: &mut [T], is_less: &F)
33+
fn shift_head<'v, T, F>(v: &'v mut [T], is_less: &F)
3034
where
3135
F: Fn(&T, &T) -> bool,
3236
{
@@ -54,9 +58,10 @@ where
5458
// into the slice.
5559
let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
5660
let v = v.as_mut_ptr();
57-
let mut hole = CopyOnDrop {
61+
let mut hole = CopyOnDrop::<'_, 'v, _> {
5862
src: &*tmp,
5963
dest: v.add(1),
64+
marker: PhantomData,
6065
};
6166
ptr::copy_nonoverlapping(v.add(1), v.add(0), 1);
6267

@@ -75,7 +80,7 @@ where
7580
}
7681

7782
/// Shifts the last element to the left until it encounters a smaller or equal element.
78-
fn shift_tail<T, F>(v: &mut [T], is_less: &F)
83+
fn shift_tail<'v, T, F>(v: &'v mut [T], is_less: &F)
7984
where
8085
F: Fn(&T, &T) -> bool,
8186
{
@@ -103,9 +108,10 @@ where
103108
// into the slice.
104109
let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
105110
let v = v.as_mut_ptr();
106-
let mut hole = CopyOnDrop {
111+
let mut hole = CopyOnDrop::<'_, 'v, _> {
107112
src: &*tmp,
108113
dest: v.add(len - 2),
114+
marker: PhantomData,
109115
};
110116
ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1);
111117

@@ -495,7 +501,7 @@ where
495501
///
496502
/// 1. Number of elements smaller than `v[pivot]`.
497503
/// 2. True if `v` was already partitioned.
498-
fn partition<T, F>(v: &mut [T], pivot: usize, is_less: &F) -> (usize, bool)
504+
fn partition<'v, T, F>(v: &'v mut [T], pivot: usize, is_less: &F) -> (usize, bool)
499505
where
500506
F: Fn(&T, &T) -> bool,
501507
{
@@ -510,9 +516,10 @@ where
510516

511517
// SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe.
512518
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
513-
let _pivot_guard = CopyOnDrop {
519+
let _pivot_guard = CopyOnDrop::<'_, 'v, _> {
514520
src: &*tmp,
515521
dest: pivot,
522+
marker: PhantomData,
516523
};
517524
let pivot = &*tmp;
518525

@@ -556,7 +563,7 @@ where
556563
///
557564
/// Returns the number of elements equal to the pivot. It is assumed that `v` does not contain
558565
/// elements smaller than the pivot.
559-
fn partition_equal<T, F>(v: &mut [T], pivot: usize, is_less: &F) -> usize
566+
fn partition_equal<'v, T, F>(v: &'v mut [T], pivot: usize, is_less: &F) -> usize
560567
where
561568
F: Fn(&T, &T) -> bool,
562569
{
@@ -569,9 +576,10 @@ where
569576
// operation panics, the pivot will be automatically written back into the slice.
570577
// SAFETY: The pointer here is valid because it is obtained from a reference to a slice.
571578
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
572-
let _pivot_guard = CopyOnDrop {
579+
let _pivot_guard = CopyOnDrop::<'_, 'v, _> {
573580
src: &*tmp,
574581
dest: pivot,
582+
marker: PhantomData,
575583
};
576584
let pivot = &*tmp;
577585

0 commit comments

Comments
 (0)