|
5 | 5 | //! `rayon_core::join`.
|
6 | 6 |
|
7 | 7 | use std::cmp;
|
| 8 | +use std::marker::PhantomData; |
8 | 9 | use std::mem::{self, MaybeUninit};
|
9 | 10 | use std::ptr;
|
10 | 11 |
|
11 | 12 | /// When dropped, copies from `src` into `dest`.
|
12 |
| -struct CopyOnDrop<T> { |
| 13 | +#[must_use] |
| 14 | +struct CopyOnDrop<'a, T> { |
13 | 15 | src: *const T,
|
14 | 16 | 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>, |
15 | 20 | }
|
16 | 21 |
|
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> { |
18 | 36 | fn drop(&mut self) {
|
19 | 37 | // SAFETY: This is a helper class.
|
20 | 38 | // Please refer to its usage for correctness.
|
|
54 | 72 | // into the slice.
|
55 | 73 | let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(0)));
|
56 | 74 | 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)); |
61 | 76 | ptr::copy_nonoverlapping(v.add(1), v.add(0), 1);
|
62 | 77 |
|
63 | 78 | for i in 2..len {
|
@@ -103,10 +118,7 @@ where
|
103 | 118 | // into the slice.
|
104 | 119 | let tmp = mem::ManuallyDrop::new(ptr::read(v.get_unchecked(len - 1)));
|
105 | 120 | 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)); |
110 | 122 | ptr::copy_nonoverlapping(v.add(len - 2), v.add(len - 1), 1);
|
111 | 123 |
|
112 | 124 | for i in (0..len - 2).rev() {
|
@@ -510,10 +522,7 @@ where
|
510 | 522 |
|
511 | 523 | // SAFETY: `pivot` is a reference to the first element of `v`, so `ptr::read` is safe.
|
512 | 524 | 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) }; |
517 | 526 | let pivot = &*tmp;
|
518 | 527 |
|
519 | 528 | // Find the first pair of out-of-order elements.
|
@@ -569,10 +578,7 @@ where
|
569 | 578 | // operation panics, the pivot will be automatically written back into the slice.
|
570 | 579 | // SAFETY: The pointer here is valid because it is obtained from a reference to a slice.
|
571 | 580 | 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) }; |
576 | 582 | let pivot = &*tmp;
|
577 | 583 |
|
578 | 584 | // Now partition the slice.
|
|
0 commit comments