Skip to content

Commit 85e2e37

Browse files
committed
Use phantomdata in CopyOnDrop
1 parent 6236214 commit 85e2e37

File tree

1 file changed

+24
-18
lines changed

1 file changed

+24
-18
lines changed

src/slice/quicksort.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,34 @@
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+
#[must_use]
14+
struct CopyOnDrop<'a, T> {
1315
src: *const T,
1416
dest: *mut T,
17+
/// `src` is often a local pointer here, make sure we have appropriate
18+
/// PhantomData so that dropck can protect us.
19+
marker: PhantomData<&'a mut T>,
1520
}
1621

17-
impl<T> Drop for CopyOnDrop<T> {
22+
impl<'a, T> CopyOnDrop<'a, T> {
23+
/// Construct from a source pointer and a destination
24+
/// Assumes dest lives longer than src, since there is no easy way to
25+
/// copy down lifetime information from another pointer
26+
unsafe fn new(src: &'a T, dest: *mut T) -> Self {
27+
CopyOnDrop {
28+
src,
29+
dest,
30+
marker: PhantomData,
31+
}
32+
}
33+
}
34+
35+
impl<T> Drop for CopyOnDrop<'_, T> {
1836
fn drop(&mut self) {
1937
// SAFETY: This is a helper class.
2038
// Please refer to its usage for correctness.
@@ -54,10 +72,7 @@ where
5472
// into the slice.
5573
let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
5674
let v = v.as_mut_ptr();
57-
let mut hole = CopyOnDrop {
58-
src: &*tmp,
59-
dest: v.add(1),
60-
};
75+
let mut hole = CopyOnDrop::new(&*tmp, v.add(1));
6176
ptr::copy_nonoverlapping(v.add(1), v.add(0), 1);
6277

6378
for i in 2..len {
@@ -103,10 +118,7 @@ where
103118
// into the slice.
104119
let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
105120
let v = v.as_mut_ptr();
106-
let mut hole = CopyOnDrop {
107-
src: &*tmp,
108-
dest: v.add(len - 2),
109-
};
121+
let mut hole = CopyOnDrop::new(&*tmp, v.add(len - 2));
110122
ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1);
111123

112124
for i in (0..len - 2).rev() {
@@ -510,10 +522,7 @@ where
510522

511523
// SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe.
512524
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
513-
let _pivot_guard = CopyOnDrop {
514-
src: &*tmp,
515-
dest: pivot,
516-
};
525+
let _pivot_guard = unsafe { CopyOnDrop::new(&*tmp, pivot) };
517526
let pivot = &*tmp;
518527

519528
// Find the first pair of out-of-order elements.
@@ -569,10 +578,7 @@ where
569578
// operation panics, the pivot will be automatically written back into the slice.
570579
// SAFETY: The pointer here is valid because it is obtained from a reference to a slice.
571580
let tmp = mem::ManuallyDrop::new(unsafe { ptr::read(pivot) });
572-
let _pivot_guard = CopyOnDrop {
573-
src: &*tmp,
574-
dest: pivot,
575-
};
581+
let _pivot_guard = unsafe { CopyOnDrop::new(&*tmp, pivot) };
576582
let pivot = &*tmp;
577583

578584
// Now partition the slice.

0 commit comments

Comments
 (0)