chiark / gitweb /
multi 1
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 18:33:05 +0000 (18:33 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 21:49:40 +0000 (21:49 +0000)
src/lib.rs

index d7549d3c6297ec333abb1a57f2e8160d012a91b9..cd6b173a48a4b615121d97a292178af134ac213d 100644 (file)
@@ -17,6 +17,7 @@ pub struct NoAliasSingleton {
 /// and `&`-references to them.
 pub unsafe trait IsRefToken<'a> {
     /// Obtain a new ZST token from something that might be a real object.
+    #[inline]
     fn ref_token(&'a self) -> RefToken<'a> {
         RefToken(PhantomData)
     }
@@ -28,11 +29,21 @@ pub unsafe trait IsRefToken<'a> {
 /// and `&mut`-references to them.
 pub unsafe trait IsMutToken<'a>: IsRefToken<'a> {
     /// Obtain a new ZST token from something that might be a real object.
+    #[inline]
     fn mut_token<'r, 's>(&'s mut self) -> MutToken<'r>
     where 's: 'r, 'a: 'r,
     {
         MutToken(PhantomData)
     }
+
+    fn multi_static<'r, 's>(&'s mut self) -> MultiStatic<'r, ()>
+    where 's: 'r, 'a: 'r,
+    {
+        MultiStatic {
+            tok: self.mut_token(),
+            l: (),
+        }
+    }
 }
 unsafe impl<'a> IsRefToken<'a> for NoAliasSingleton {}
 unsafe impl<'a> IsMutToken<'a> for NoAliasSingleton {}
@@ -64,6 +75,14 @@ pub struct MutToken<'a>(
     PhantomData<&'a mut NoAliasSingleton>,
 );
 
+impl<'a> MutToken<'a> {
+    ///
+    ///
+    /// SAFETY
+    ///
+    fn new_unchecked() -> Self { MutToken(PhantomData) }
+}
+
 pub struct Ptr<T> {
     /// # SAFETY
     ///
@@ -144,10 +163,12 @@ TODO lifetime is hard
         self.ptr
     }
 
-    /// 
+    /// Frees a `Ptr` that was made with `new_heap`
     ///
     /// # SAFETY
     ///
+    /// `self` must have come from `new_heap`.
+    ///
     /// All copies of `self` will be invalidated.
     ///
     /// So either no copies may exist any longer,
@@ -183,9 +204,6 @@ impl<T> OptionPtrExt<T> for Option<Ptr<T>> {
     }
 }
 
-/*struct MultiAccessor<'a, R, const N: usize> {
-}*/
-
 impl NoAliasSingleton {
     /// Initialise by creating the singleton for alias checking
     ///
@@ -206,6 +224,79 @@ impl NoAliasSingleton {
     pub unsafe fn init() -> Self { NoAliasSingleton {} }
 }
 
+pub struct BorrowConflict;
+
+pub struct MultiStatic<'a, L> {
+    tok: MutToken<'a>,
+    l: L,
+}
+
+fn forbid_alias<T>(this: &T, new: *const ()) -> Result<(), BorrowConflict> {
+    let this = this as *const T as *const ();
+    if this == new { return Err(BorrowConflict) }
+    Ok(())
+}
+
+pub trait MultiStaticList {
+    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict>;
+    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict>;
+}
+impl MultiStaticList for () {
+    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        Ok(())
+    }
+    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        Ok(())
+    }
+}
+impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
+    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        self.0.alias_check_ref(p)
+    }
+    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        forbid_alias(self.1, p)?;
+        self.0.alias_check_mut(p)
+    }
+}
+impl<T, L: MultiStaticList> MultiStaticList for (L, &mut T) {
+    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        forbid_alias(&*self.1, p)?;
+        self.0.alias_check_ref(p)
+    }
+    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+        forbid_alias(&*self.1, p)?;
+        self.0.alias_check_mut(p)
+    }
+}
+
+impl<'a, L: MultiStaticList> MultiStatic<'a, L> {
+    pub fn borrow<'r, T>(self, p: Ptr<T>) -> Result<
+        MultiStatic<'a, (L, &'r T)>,
+        BorrowConflict
+    >
+    where 'a: 'r
+    {
+        self.l.alias_check_ref(p.ptr.as_ptr() as *const ())?;
+        Ok(MultiStatic {
+            tok: self.tok,
+            l: (self.l, unsafe { p.ptr.as_ref() }),
+        })
+    }
+
+    pub fn borrow_mut<'r, T>(self, mut p: Ptr<T>) -> Result<
+        MultiStatic<'a, (L, &'r mut T)>,
+        BorrowConflict
+    >
+    where 'a: 'r
+    {
+        self.l.alias_check_mut(p.ptr.as_ptr() as *const ())?;
+        Ok(MultiStatic {
+            tok: self.tok,
+            l: (self.l, unsafe { p.ptr.as_mut() }),
+        })
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;