chiark / gitweb /
docs
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 15 Nov 2024 01:32:53 +0000 (01:32 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Fri, 15 Nov 2024 01:32:53 +0000 (01:32 +0000)
src/lib.rs

index 4efe5d39e86e65a3cacc3bc809be7cdad96949df..4f442f29251ea989cda6e1dcf89610d0d7d20a7f 100644 (file)
 //!
 //!  * Following Rust's aliasing rules,
 //!    which are (for our purposes) stricter than C's.
-//!    The library should prevent accidental creation
+//!    This library aims to prevent accidental creation
 //!    of overlapping `&mut`, for example.
 //!
 //!  * Threadsafety; `Send` and `Sync`.
 //!    (The caller must still make sure not to free an object
 //!    that another thread may be using, of course.)
 //!
-//!  * Soundness in the face of panics, including in methods
+//!  * Soundness in the face of panics, including panics from methods
 //!    of the contained type `T`, eg `T`'s `Drop` impl.
 //!
-//!  * "`Drop` footguns", and others, sometimes found in unsafe code.
+//!  * "`Drop` footguns", and the like, which lurk in Unsafe Rust.
 //!
 //! ### Soundness
 //!
@@ -48,8 +48,8 @@
 //! than is usual for a Rust API.
 //!
 //! In practice this means that in a real program,
-//! correctness is likely to depend on the behaviour
-//! of even nominally "safe" code.
+//! memory-safety is likely to depend on the correctness
+//! of much nominally "safe" code.
 //! The rules have been chosen pragmatically,
 //! to minimise the proportion of the caller that needs
 //! to be *actually marked* with `unsafe`.
@@ -85,10 +85,16 @@ use std::ptr::NonNull;
 /// To mutably access the data of more than one node at once,
 /// use
 /// [`IsTokenMut::multi_static`],
-/// [`IsTokenMut::multi_dynamic`],
-/// or for manual aliasing checks,
+/// [`IsTokenMut::multi_dynamic`].
+///
+/// To avoid runtime aliasing checks, and take manual control of aliasing,
+/// you can
 /// [`.borrow_mut()`](Ptr::borrow_mut()) with
 /// [`TokenMut::new_unchecked()`].
+/// Or,
+/// `p`[`.as_ptr()`](Ptr::as_ptr)[`.as_ref()`](NonNull::as_ref())
+/// /
+/// `p`[`.as_ptr()`](Ptr::as_ptr)[`.as_mut()`](NonNull::as_mut()).
 ///
 /// This type is `Copy`.  Copying it (or, indeed, cloning it)
 /// does not copy the underlying data.
@@ -169,15 +175,20 @@ impl<'a> TokenMut<'a> {
     /// [`Ptr::borrow()`]/[`borrow_mut()`](Ptr::borrow_mut)
     /// multiple times, retaining and using all the resulting references.
     ///
+    /// For another approach,
+    /// see [`Ptr::as_ptr()`].
+    ///
     /// # SAFETY
     ///
     /// The calls to `borrow[_mut]` that this enables must not violate
     /// Rust's rules.  Checking that is up to you.
-    /// 
+    ///
     /// So, all of the `Ptr` you `borrow_mut` must be distinct,
     /// and they must be distinct from your `borrow`s.
     /// Violating this rule is instant undefined behaviour,
     /// even if you never read or write the resulting reference(s).
+    /// 
+    /// Also, it is up to you to make sure you don't free the data to soon.
     pub unsafe fn new_unchecked() -> Self { TokenMut(PhantomData) }
 }
 
@@ -316,6 +327,23 @@ impl<T: ?Sized> Ptr<T> {
     /// If `Ptr` was made with `new_heap` or `From<Box<_>>`,
     /// this pointer has the same properties as `Box`'s.
     /// But of course many copies may exist.
+    ///
+    /// # Obtaining references
+    ///
+    /// You may call
+    /// [`.as_ref()`](NonNull::as_ref)
+    /// or
+    /// [`.as_mut()`](NonNull::as_mut)
+    /// on the returned `NonNull`,
+    /// to get `&T` or `&mut T`.
+    ///
+    /// This is sound iff there are no conflicting borrows,
+    /// and you know you won't be freeing the data too soon.
+    /// If you do this, you take responsibility
+    /// for following Rust's aliasing rules.
+    ///
+    /// This approach is semantically equivalent to using
+    /// [`TokenMut::new_unchecked()`].
     pub fn as_ptr(self) -> NonNull<T> {
         self.ptr
     }