chiark / gitweb /
wip
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 20:55:26 +0000 (20:55 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 21:49:40 +0000 (21:49 +0000)
src/lib.rs

index 444317a0775c37705e668d4d262f2d4b1e0fd409..96abfe0101b942f36b68f1a6e86182f487b5ca7c 100644 (file)
@@ -1,6 +1,7 @@
 
 #![allow(unused)]
 
+use std::collections::HashSet;
 use std::fmt::{self, Debug};
 use std::hint::unreachable_unchecked;
 use std::marker::PhantomData;
@@ -45,6 +46,16 @@ pub unsafe trait IsMutToken<'a>: IsRefToken<'a> + Sized {
             l: (),
         }
     }
+
+    fn multi_runtime<'r>(mut self) -> MultiRuntime<'r>
+    where 'a: 'r,
+    {
+        MultiRuntime {
+            tok: self.mut_token(),
+            ref_given: HashSet::new(),
+            mut_given: HashSet::new(),
+        }
+    }
 }
 unsafe impl<'a> IsRefToken<'a> for &'a NoAliasSingleton {}
 unsafe impl<'a> IsRefToken<'a> for &'a mut NoAliasSingleton {}
@@ -233,39 +244,38 @@ pub struct MultiStatic<'a, L> {
     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) }
+fn forbid_alias<T>(this: &T, new: NonNull<()>) -> Result<(), BorrowConflict> {
+    if NonNull::from(this) == new.cast() { return Err(BorrowConflict) }
     Ok(())
 }
 
 pub unsafe trait MultiStaticList {
-    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict>;
-    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict>;
+    fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict>;
+    fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict>;
 }
 unsafe impl MultiStaticList for () {
-    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         Ok(())
     }
-    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         Ok(())
     }
 }
 unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
-    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         self.0.alias_check_ref(p)
     }
-    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         forbid_alias(self.1, p)?;
         self.0.alias_check_mut(p)
     }
 }
 unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &mut T) {
-    fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         forbid_alias(&*self.1, p)?;
         self.0.alias_check_ref(p)
     }
-    fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+    fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         forbid_alias(&*self.1, p)?;
         self.0.alias_check_mut(p)
     }
@@ -278,7 +288,7 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> {
     >
     where 'a: 'r
     {
-        match self.l.alias_check_ref(p.ptr.as_ptr() as *const ()) {
+        match self.l.alias_check_ref(p.ptr.cast()) {
             Err(e) => Err(self),
             Ok(()) => Ok(MultiStatic {
                 tok: self.tok,
@@ -293,7 +303,7 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> {
     >
     where 'a: 'r
     {
-        match self.l.alias_check_mut(p.ptr.as_ptr() as *const ()) {
+        match self.l.alias_check_mut(p.ptr.cast()) {
             Err(e) => Err(self),
             Ok(()) => Ok(MultiStatic {
                 tok: self.tok,
@@ -307,6 +317,54 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> {
     }
 }
 
+pub struct MultiRuntime<'a> {
+    tok: MutToken<'a>,
+    ref_given: HashSet<NonNull<()>>,
+    mut_given: HashSet<NonNull<()>>,
+}
+
+impl<'a> MultiRuntime<'a> {
+    #[inline]
+    pub fn borrow<'r, T>(&mut self, p: Ptr<T>) 
+        -> Result<&'r T, BorrowConflict>
+    where 'a: 'r
+    {
+        self.borrow_inner_check(p.ptr.cast())?;
+        Ok(unsafe { p.ptr.as_ref() })
+    }
+
+    fn borrow_inner_check(&mut self, p: NonNull<()>)
+                          -> Result<(), BorrowConflict>
+    {
+        if self.mut_given.contains(&p) {
+            return Err(BorrowConflict)
+        }
+        self.ref_given.insert(p);
+        Ok(())
+    }
+
+    #[inline]
+    pub fn borrow_mut<'r, T>(&mut self, mut p: Ptr<T>)
+        -> Result<&'r mut T, BorrowConflict>
+    where 'a: 'r
+    {
+        self.borrow_mut_inner_check(p.ptr.cast())?;
+        Ok(unsafe { p.ptr.as_mut() })
+    }
+
+    fn borrow_mut_inner_check(&mut self, p: NonNull<()>)
+                          -> Result<(), BorrowConflict> 
+{
+        if self.ref_given.contains(&p) {
+            return Err(BorrowConflict)
+        }
+        if !self.mut_given.insert(p) {
+            return Err(BorrowConflict)
+        }
+        Ok(())
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -478,3 +536,4 @@ mod tests {
 }
 
 
+