From c45fcefec13d23fe9696705f3fb345c30c0429f1 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 15 Nov 2024 01:32:53 +0000 Subject: [PATCH] docs --- src/lib.rs | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4efe5d3..4f442f2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,17 +23,17 @@ //! //! * 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 Ptr { /// If `Ptr` was made with `new_heap` or `From>`, /// 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 { self.ptr } -- 2.30.2