chiark / gitweb /
ergonomic
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 22:07:27 +0000 (22:07 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 14 Nov 2024 22:07:27 +0000 (22:07 +0000)
src/lib.rs
src/test/demo.rs

index 6b886fbdec4daffac53681e09a1381eb3202a586..d1c43849446f2414ca8846f46fec790fec3c1852 100644 (file)
@@ -248,8 +248,10 @@ pub struct MultiStatic<'a, L> {
     l: L,
 }
 
-fn forbid_alias<T>(this: &T, new: NonNull<()>) -> Result<(), BorrowConflict> {
-    if NonNull::from(this) == new.cast() { return Err(BorrowConflict) }
+fn forbid_alias(this: *const (), new: NonNull<()>)
+                -> Result<(), BorrowConflict>
+{
+    if this == new.as_ptr() { return Err(BorrowConflict) }
     Ok(())
 }
 
@@ -265,7 +267,7 @@ unsafe impl MultiStaticList for () {
         Ok(())
     }
 }
-unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
+unsafe impl<L: MultiStaticList> MultiStaticList for (L, *const ()) {
     fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
         self.0.alias_check_ref(p)
     }
@@ -274,51 +276,53 @@ unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
         self.0.alias_check_mut(p)
     }
 }
-unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &mut T) {
+unsafe impl<L: MultiStaticList> MultiStaticList for (L, NonNull<()>) {
     fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
-        forbid_alias(&*self.1, p)?;
+        forbid_alias(self.1.as_ptr(), p)?;
         self.0.alias_check_ref(p)
     }
     fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
-        forbid_alias(&*self.1, p)?;
+        forbid_alias(self.1.as_ptr(), 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)>,
+        (&'r T, MultiStatic<'a, (L, *const ())>),
         Self
     >
     where 'a: 'r
     {
         match self.l.alias_check_ref(p.ptr.cast()) {
             Err(BorrowConflict) => Err(self),
-            Ok(()) => Ok(MultiStatic {
-                tok: self.tok,
-                l: (self.l, unsafe { p.ptr.as_ref() }),
-            })
+            Ok(()) => Ok((
+                unsafe { p.ptr.as_ref() },
+                MultiStatic {
+                    tok: self.tok,
+                    l: (self.l, p.ptr.cast().as_ptr()),
+                }
+            ))
         }
     }
 
     pub fn borrow_mut<'r, T>(self, mut p: Ptr<T>) -> Result<
-        MultiStatic<'a, (L, &'r mut T)>,
+        (&'r mut T, MultiStatic<'a, (L, NonNull<()>)>),
         Self
     >
     where 'a: 'r
     {
         match self.l.alias_check_mut(p.ptr.cast()) {
             Err(BorrowConflict) => Err(self),
-            Ok(()) => Ok(MultiStatic {
-                tok: self.tok,
-                l: (self.l, unsafe { p.ptr.as_mut() }),
-            })
+            Ok(()) => Ok((
+                unsafe { p.ptr.as_mut() },
+                MultiStatic {
+                    tok: self.tok,
+                    l: (self.l, p.ptr.cast()),
+                },
+            ))
         }
     }
-
-    pub fn finish(self) -> L {
-        self.l
-    }
 }
 
 pub struct MultiRuntime<'a> {
index 5514e751eb6d0d8902e44dd87bc1ba71f12b6449..5d57cb093ed8b27a5c21980933409ae3ba875041 100644 (file)
@@ -89,21 +89,15 @@ impl<T: Debug> List<T> {
 
         let multi = self.noalias.mut_token().multi_static();
 
-        let Ok(multi) = multi.borrow_mut(head)
+        let Ok((head, multi)) = multi.borrow_mut(head)
         else { unsafe { unreachable_unchecked() } };
 
         let tail = unsafe { self.tail.unwrap_unchecked() };
 
-        match multi.borrow_mut(tail) {
-            Ok(y) => {
-                let (((), head), tail) = y.finish();
-                HeadAndTail::Both(&mut head.data, &mut tail.data)
-            },
-            Err(n) => {
-                let ((), head) = n.finish();
-                HeadAndTail::One(&mut head.data)
-            }
-        }
+        let Ok((tail, _)) = multi.borrow_mut(tail)
+        else { return HeadAndTail::One(&mut head.data) };
+
+        HeadAndTail::Both(&mut head.data, &mut tail.data)
     }
 
     pub fn all(&self) -> impl Iterator<Item = &T> {