proof.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. use core::{marker::PhantomData, ptr::NonNull};
  2. /// A proof of mutable access to a position in memory with lifetime `'pos`.
  3. ///
  4. /// Note that this is just the proof of access, we aren't actually permitted
  5. /// to mutate the memory location.
  6. ///
  7. /// We can choose whether to check the validity of the proof or not at runtime.
  8. pub struct ProofMut<'pos, T>
  9. where
  10. T: ?Sized,
  11. {
  12. pub(super) address: NonNull<T>,
  13. _phantom: PhantomData<&'pos ()>,
  14. }
  15. /// A proof of immutable access to a position in memory with lifetime `'pos`.
  16. ///
  17. /// We can choose whether to check the validity of the proof or not at runtime.
  18. pub struct Proof<'pos, T>
  19. where
  20. T: ?Sized,
  21. {
  22. pub(super) address: NonNull<T>,
  23. _phantom: PhantomData<&'pos ()>,
  24. }
  25. unsafe impl<T: ?Sized> Send for Proof<'_, T> {}
  26. unsafe impl<T: ?Sized> Send for ProofMut<'_, T> {}
  27. /// A trait for types that can be converted to a proof of mutable access.
  28. ///
  29. /// This is used to prove that a mutable reference is valid for the lifetime `'pos`
  30. /// through this object with lifetime `'guard`.
  31. ///
  32. /// ## Safety
  33. /// This trait is unsafe because it allows the caller to create a proof of access
  34. /// to a memory location that may not be valid for the lifetime `'pos`. The implementer
  35. /// must ensure that the access to the memory location is valid for the lifetime `'pos`
  36. /// during the lifetime of the returned `Proof`. This is typically done by using a lock
  37. /// or other synchronization mechanism to ensure that the memory location is not accessed
  38. /// by others while the proof is being created.
  39. pub unsafe trait AsProofMut<'guard, 'pos, T>: 'guard
  40. where
  41. T: ?Sized,
  42. {
  43. fn prove_mut(&self) -> ProofMut<'pos, T>
  44. where
  45. 'guard: 'pos;
  46. }
  47. /// A trait for types that can be converted to a proof of immutable access.
  48. ///
  49. /// This is used to prove that an immutable reference is valid for the lifetime `'pos`
  50. /// through this object with lifetime `'guard`.
  51. ///
  52. /// ## Safety
  53. /// This trait is unsafe because it allows the caller to create a proof of access
  54. /// to a memory location that may not be valid for the lifetime `'pos`. The implementer
  55. /// must ensure that the access to the memory location is valid for the lifetime `'pos`
  56. /// during the lifetime of the returned `Proof`. This is typically done by using a lock
  57. /// or other synchronization mechanism to ensure that the memory location is not accessed
  58. /// by others while the proof is being created.
  59. pub unsafe trait AsProof<'guard, 'pos, T>: 'guard
  60. where
  61. T: ?Sized,
  62. {
  63. fn prove(&self) -> Proof<'pos, T>
  64. where
  65. 'guard: 'pos;
  66. }
  67. impl<T> Proof<'_, T>
  68. where
  69. T: ?Sized,
  70. {
  71. /// # Safety
  72. /// The caller must ensure valid access for at least the lifetime `'pos`.
  73. pub const unsafe fn new(address: *const T) -> Self {
  74. Self {
  75. // SAFETY: The validity of the reference is guaranteed by the caller.
  76. address: unsafe { NonNull::new_unchecked(address as *mut _) },
  77. _phantom: PhantomData,
  78. }
  79. }
  80. }
  81. impl<T> ProofMut<'_, T>
  82. where
  83. T: ?Sized,
  84. {
  85. /// # Safety
  86. /// The caller must ensure valid access for at least the lifetime `'pos`.
  87. pub const unsafe fn new(address: *mut T) -> Self {
  88. Self {
  89. // SAFETY: The validity of the reference is guaranteed by the caller.
  90. address: unsafe { NonNull::new_unchecked(address as *mut _) },
  91. _phantom: PhantomData,
  92. }
  93. }
  94. }
  95. /// Proof of mutable access to a position in memory can be duplicated.
  96. impl<T> Copy for ProofMut<'_, T> where T: ?Sized {}
  97. /// Proof of mutable access to a position in memory can be duplicated.
  98. impl<T> Clone for ProofMut<'_, T>
  99. where
  100. T: ?Sized,
  101. {
  102. fn clone(&self) -> Self {
  103. Self {
  104. address: self.address,
  105. _phantom: self._phantom,
  106. }
  107. }
  108. }
  109. /// Proof of immutable access to a position in memory can be duplicated.
  110. impl<T> Copy for Proof<'_, T> where T: ?Sized {}
  111. /// Proof of immutable access to a position in memory can be duplicated.
  112. impl<T> Clone for Proof<'_, T>
  113. where
  114. T: ?Sized,
  115. {
  116. fn clone(&self) -> Self {
  117. Self {
  118. address: self.address,
  119. _phantom: self._phantom,
  120. }
  121. }
  122. }
  123. /// SAFETY: The reference is valid for the lifetime `'guard`. So the access must be
  124. /// valid for the lifetime `'pos` that is shorter than `'guard`.
  125. unsafe impl<'guard, 'pos, T> AsProofMut<'guard, 'pos, T> for &'guard mut T
  126. where
  127. T: ?Sized,
  128. {
  129. fn prove_mut(&self) -> ProofMut<'pos, T>
  130. where
  131. 'guard: 'pos,
  132. {
  133. ProofMut {
  134. // SAFETY: The validity of the reference is guaranteed by the borrow checker.
  135. address: unsafe { NonNull::new_unchecked(&raw const **self as *mut _) },
  136. _phantom: PhantomData,
  137. }
  138. }
  139. }
  140. /// SAFETY: The reference is valid for the lifetime `'guard`. So the access must be
  141. /// valid for the lifetime `'pos` that is shorter than `'guard`.
  142. unsafe impl<'guard, 'pos, T> AsProof<'guard, 'pos, T> for &'guard T
  143. where
  144. T: ?Sized,
  145. {
  146. fn prove(&self) -> Proof<'pos, T>
  147. where
  148. 'guard: 'pos,
  149. {
  150. Proof {
  151. address: unsafe { NonNull::new_unchecked(&raw const **self as *mut _) },
  152. _phantom: PhantomData,
  153. }
  154. }
  155. }
  156. /// SAFETY: The reference is valid for the lifetime `'guard`. So the access must be
  157. /// valid for the lifetime `'pos` that is shorter than `'guard`.
  158. unsafe impl<'guard, 'pos, T> AsProof<'guard, 'pos, T> for &'guard mut T
  159. where
  160. T: ?Sized,
  161. {
  162. fn prove(&self) -> Proof<'pos, T>
  163. where
  164. 'guard: 'pos,
  165. {
  166. Proof {
  167. address: unsafe { NonNull::new_unchecked(&raw const **self as *mut _) },
  168. _phantom: PhantomData,
  169. }
  170. }
  171. }