|
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