From d35be39f561ff29a0441085ba65999dc2b675510 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Thu, 14 Nov 2024 19:04:17 +0000 Subject: [PATCH] trouble --- src/lib.rs | 75 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 17 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index cd6b173..65d4f20 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,6 +2,7 @@ #![allow(unused)] use std::fmt::{self, Debug}; +use std::hint::unreachable_unchecked; use std::marker::PhantomData; use std::ptr::NonNull; @@ -237,11 +238,11 @@ fn forbid_alias(this: &T, new: *const ()) -> Result<(), BorrowConflict> { Ok(()) } -pub trait MultiStaticList { +pub unsafe trait MultiStaticList { fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict>; fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict>; } -impl MultiStaticList for () { +unsafe impl MultiStaticList for () { fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> { Ok(()) } @@ -249,7 +250,7 @@ impl MultiStaticList for () { Ok(()) } } -impl MultiStaticList for (L, &T) { +unsafe impl MultiStaticList for (L, &T) { fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> { self.0.alias_check_ref(p) } @@ -258,7 +259,7 @@ impl MultiStaticList for (L, &T) { self.0.alias_check_mut(p) } } -impl MultiStaticList for (L, &mut T) { +unsafe impl 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) @@ -272,28 +273,36 @@ impl MultiStaticList for (L, &mut T) { impl<'a, L: MultiStaticList> MultiStatic<'a, L> { pub fn borrow<'r, T>(self, p: Ptr) -> Result< MultiStatic<'a, (L, &'r T)>, - BorrowConflict + Self > 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() }), - }) + match self.l.alias_check_ref(p.ptr.as_ptr() as *const ()) { + Err(e) => Err(self), + Ok(()) => Ok(MultiStatic { + tok: self.tok, + l: (self.l, unsafe { p.ptr.as_ref() }), + }) + } } pub fn borrow_mut<'r, T>(self, mut p: Ptr) -> Result< MultiStatic<'a, (L, &'r mut T)>, - BorrowConflict + Self > 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() }), - }) + match self.l.alias_check_mut(p.ptr.as_ptr() as *const ()) { + Err(e) => Err(self), + Ok(()) => Ok(MultiStatic { + tok: self.tok, + l: (self.l, unsafe { p.ptr.as_mut() }), + }) + } + } + + pub fn finish(self) -> L { + self.l } } @@ -319,6 +328,13 @@ mod tests { noalias: NoAliasSingleton, } + #[derive(Debug, Eq, PartialEq)] + pub enum HeadAndTail { + None, + One(T), + Both(T, T), + } + impl List { pub fn new() -> Self { let noalias = unsafe { NoAliasSingleton::init() }; @@ -377,6 +393,29 @@ mod tests { ) } + pub fn head_and_tail_mut(&mut self) -> HeadAndTail<&mut T> { + let Some(head) = self.head + else { return HeadAndTail::None }; + + let multi = self.noalias.mut_token().multi_static(); + + let Ok(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) + } + } + } + // We wouldn't do this, since it's daft, but // it lets us demonstrate passing a token. fn pop_front_inner<'a>( @@ -410,7 +449,7 @@ mod tests { #[test] fn demo() { - use list::List; + use list::{List, HeadAndTail}; let s = |s: &str| format!("{s}"); @@ -420,6 +459,8 @@ mod tests { drop(l); let mut l = List::new(); l.check_consistency(); + assert_eq!(l.head_and_tail_mut(), HeadAndTail::None); + l.append(s("hi")); l.check_consistency(); l.append(s("ho")); l.check_consistency(); -- 2.30.2