From: Ian Jackson Date: Thu, 14 Nov 2024 18:33:05 +0000 (+0000) Subject: multi 1 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=ef17440e8be879d5b54c482870b834d45f3e5f1f;p=manually-boxed multi 1 --- diff --git a/src/lib.rs b/src/lib.rs index d7549d3..cd6b173 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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 { /// # 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 OptionPtrExt for Option> { } } -/*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(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 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 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) -> 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) -> 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::*;