updated docs

Changed files
+49 -15
lifetime-guard
src
+49 -15
lifetime-guard/src/lib.rs
··· 27 27 //! 28 28 //! # Safety 29 29 //! 30 - //! You *may not* leak any instance of either `ValueGuard` or `RefGuard`. 30 + //! You *may not* leak any instance of either `ValueGuard` or `RefGuard` to the 31 + //! stack using `mem::forget()` or any other mechanism that causes thier 32 + //! contents to be overwritten without `Drop::drop()` running. 33 + //! Doing so creates unsoundness that likely will lead to dereferencing a null 34 + //! pointer. 31 35 //! 32 36 //! Doing so creates unsoundness that likely will lead to dereferencing a null 33 37 //! pointer. See the 34 38 //! [Forget marker trait](https://github.com/rust-lang/rfcs/pull/3782) rfc for 35 39 //! progress on making interfaces that rely on not being leaked sound. 40 + //! 41 + //! Note that it is sound to leak `ValueGuard` and `RefGuard` to the heap using 42 + //! methods including `Box::leak()` because heap allocated data will never be 43 + //! overwritten if it is never freed. 36 44 37 45 use std::{cell::Cell, marker::PhantomPinned, pin::Pin, ptr::NonNull}; 38 46 ··· 42 50 /// A `ValueGuard`:`RefGuard` relationship is exclusive, and behaves similarly 43 51 /// to a single `Rc` and `Weak` pair, but notably does not require heap 44 52 /// allocation. `ValueGuard::registration` creates a `GuardRegistration`, which 45 - /// provides a movable wrapper for safetly creating the circular references 53 + /// provides a movable wrapper for safety creating the circular references 46 54 /// between two pinned self referential structs. 47 55 /// 48 56 /// # Safety 49 57 /// 50 - /// This struct *must* not be leaked, using `mem::forget`, `Rc`, `Arc`, etc. 51 - /// 58 + /// This struct *must* not be leaked to the stack using `mem::forget` or any 59 + /// other mechanism that causes the contents of `Self` to be overwritten 60 + /// without `Drop::drop()` running. 52 61 /// Doing so creates unsoundness that likely will lead to dereferencing a null 53 - /// pointer. See the 54 - /// [Forget marker trait](https://github.com/rust-lang/rfcs/pull/3782) rfc for 55 - /// progress on making interfaces that rely on not being leaked sound. 62 + /// pointer. 63 + /// 64 + /// Note that it is sound to leak `Self` to the heap using methods including 65 + /// `Box::leak()` because heap allocated data will never be overwritten if it 66 + /// is never freed. 56 67 pub struct ValueGuard<T> { 57 68 /// Contains the value being immutably accessed by `RefGuard` and 58 69 /// mutably accessed by `Self` ··· 78 89 } 79 90 } 80 91 81 - /// Returns a `GuardRegistration`, which can be used to safetly link `Self` 92 + /// Returns a `GuardRegistration`, which can be used to safety link `Self` 82 93 /// to a `RefGuard`. 83 94 #[inline] 84 95 pub fn registration<'a>(self: Pin<&'a Self>) -> GuardRegistration<'a, T> { ··· 119 130 /// 120 131 /// # Safety 121 132 /// 122 - /// This struct *must* not be leaked, using `mem::forget`, `Rc`, `Arc`, etc. 123 - /// 133 + /// This struct *must* not be leaked to the stack using `mem::forget` or any 134 + /// other mechanism that causes the contents of `Self` to be overwritten 135 + /// without `Drop::drop()` running. 124 136 /// Doing so creates unsoundness that likely will lead to dereferencing a null 125 - /// pointer. See the 126 - /// [Forget marker trait](https://github.com/rust-lang/rfcs/pull/3782) rfc for 127 - /// progress on making interfaces that rely on not being leaked sound. 128 - 137 + /// pointer. 138 + /// 139 + /// Note that it is sound to leak `Self` to the heap using methods including 140 + /// `Box::leak()` because heap allocated data will never be overwritten if it 141 + /// is never freed. 129 142 pub struct RefGuard<T> { 130 143 value_guard: Cell<Option<NonNull<ValueGuard<T>>>>, 131 144 _marker: PhantomPinned, ··· 165 178 if let Some(guard) = self.value_guard.get() { 166 179 invalidate_value_guard(guard); 167 180 } 181 + } 182 + } 183 + 184 + impl<T> Default for RefGuard<T> { 185 + #[inline] 186 + fn default() -> Self { 187 + Self::new() 168 188 } 169 189 } 170 190 ··· 210 230 211 231 #[cfg(test)] 212 232 mod test { 213 - use std::pin; 233 + use std::{mem, pin}; 214 234 215 235 use super::*; 216 236 ··· 262 282 263 283 assert_eq!(weak1.get(), None); 264 284 assert_eq!(weak2.get(), None); 285 + } 286 + 287 + #[test] 288 + #[cfg_attr(miri, ignore)] 289 + fn safe_leak() { 290 + let strong = Box::pin(ValueGuard::new(10)); 291 + let weak = pin::pin!(RefGuard::new()); 292 + strong.as_ref().registration().register(weak.as_ref()); 293 + 294 + // strong is now a ValueGuard on the heap that will never be freed 295 + // this is sound because it will never be overwritten 296 + mem::forget(strong); 297 + 298 + assert_eq!(weak.get(), Some(10)); 265 299 } 266 300 }