From: Ian Jackson Date: Thu, 14 Nov 2024 21:27:29 +0000 (+0000) Subject: wip X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=99949819421cdacad0cc4a4a918a9b6e24bfa5e1;p=manually-boxed wip --- diff --git a/src/lib.rs b/src/lib.rs index 96abfe0..2f07b8f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,9 +1,6 @@ -#![allow(unused)] - use std::collections::HashSet; use std::fmt::{self, Debug}; -use std::hint::unreachable_unchecked; use std::marker::PhantomData; use std::ptr::NonNull; @@ -32,13 +29,13 @@ pub unsafe trait IsRefToken<'a>: Sized { pub unsafe trait IsMutToken<'a>: IsRefToken<'a> + Sized { /// Obtain a new ZST token from something that might be a real object. #[inline] - fn mut_token<'r>(mut self) -> MutToken<'r> + fn mut_token<'r>(self) -> MutToken<'r> where 'a: 'r, { MutToken(PhantomData) } - fn multi_static<'r>(mut self) -> MultiStatic<'r, ()> + fn multi_static<'r>(self) -> MultiStatic<'r, ()> where 'a: 'r, { MultiStatic { @@ -47,11 +44,11 @@ pub unsafe trait IsMutToken<'a>: IsRefToken<'a> + Sized { } } - fn multi_runtime<'r>(mut self) -> MultiRuntime<'r> + fn multi_runtime<'r>(self) -> MultiRuntime<'r> where 'a: 'r, { MultiRuntime { - tok: self.mut_token(), + _tok: self.mut_token(), ref_given: HashSet::new(), mut_given: HashSet::new(), } @@ -93,7 +90,7 @@ impl<'a> MutToken<'a> { /// /// SAFETY /// - fn new_unchecked() -> Self { MutToken(PhantomData) } + pub unsafe fn new_unchecked() -> Self { MutToken(PhantomData) } } pub struct Ptr { @@ -149,6 +146,7 @@ TODO lifetime is hard #[inline] pub fn borrow<'a>(self, tok: impl IsRefToken<'a>) -> &'a T { + let _ = tok; unsafe { // SAFETY // @@ -161,6 +159,7 @@ TODO lifetime is hard #[inline] pub fn borrow_mut<'a>(mut self, tok: impl IsMutToken<'a>) -> &'a mut T { + let _ = tok; unsafe { // SAFETY // @@ -193,6 +192,7 @@ TODO lifetime is hard /// (The compiler will check that no borrows are live.) #[inline] pub unsafe fn free_heap<'a>(self, tok: impl IsMutToken<'a>) -> T { + let _ = tok; let t: Box = unsafe { // SAFETY // @@ -237,6 +237,7 @@ impl NoAliasSingleton { pub unsafe fn init() -> Self { NoAliasSingleton {} } } +#[derive(Debug)] pub struct BorrowConflict; pub struct MultiStatic<'a, L> { @@ -254,10 +255,10 @@ pub unsafe trait MultiStaticList { fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict>; } unsafe impl MultiStaticList for () { - fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> { + fn alias_check_ref(&self, _: NonNull<()>) -> Result<(), BorrowConflict> { Ok(()) } - fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> { + fn alias_check_mut(&self, _: NonNull<()>) -> Result<(), BorrowConflict> { Ok(()) } } @@ -289,7 +290,7 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> { where 'a: 'r { match self.l.alias_check_ref(p.ptr.cast()) { - Err(e) => Err(self), + Err(BorrowConflict) => Err(self), Ok(()) => Ok(MultiStatic { tok: self.tok, l: (self.l, unsafe { p.ptr.as_ref() }), @@ -304,7 +305,7 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> { where 'a: 'r { match self.l.alias_check_mut(p.ptr.cast()) { - Err(e) => Err(self), + Err(BorrowConflict) => Err(self), Ok(()) => Ok(MultiStatic { tok: self.tok, l: (self.l, unsafe { p.ptr.as_mut() }), @@ -318,7 +319,7 @@ impl<'a, L: MultiStaticList> MultiStatic<'a, L> { } pub struct MultiRuntime<'a> { - tok: MutToken<'a>, + _tok: MutToken<'a>, ref_given: HashSet>, mut_given: HashSet>, } @@ -372,6 +373,8 @@ mod tests { mod list { use super::*; + use std::hint::unreachable_unchecked; + use std::iter; #[derive(Debug)] pub struct Node { @@ -394,6 +397,8 @@ mod tests { Both(T, T), } + type P = Ptr>; + impl List { pub fn new() -> Self { let noalias = unsafe { NoAliasSingleton::init() }; @@ -403,7 +408,7 @@ mod tests { pub fn check_consistency(&self) { dbg!(self); let tok = self.noalias.ref_token(); - let mut last: Option>> = None; + let mut last: Option> = None; let mut node = self.head; while let Some(node_) = node { dbg!(node_); @@ -475,12 +480,36 @@ mod tests { } } + pub fn all(&self) -> impl Iterator { + let tok = self.noalias.ref_token(); + Self::iter_ptrs(self.head, move |node| { + let node = node.borrow(tok); + (&node.data, node.next) + }) + } + + pub fn all_mut_safe(&mut self) -> impl Iterator { + let mut multi = self.noalias.multi_runtime(); + Self::iter_ptrs(self.head, move |node| { + let node = multi.borrow_mut(node).expect("untangled!"); + (&mut node.data, node.next) + }) + } + + pub fn all_mut_fast(&mut self) -> impl Iterator { + Self::iter_ptrs(self.head, |node| { + let tok = unsafe { MutToken::new_unchecked() }; + let node = node.borrow_mut(tok); + (&mut node.data, node.next) + }) + } + // We wouldn't do this, since it's daft, but // it lets us demonstrate passing a token. fn pop_front_inner<'a>( mut tok: MutToken<'a>, - head: &mut Option>>, - tail: &mut Option>>, + head: &mut Option>, + tail: &mut Option>, ) -> Option { let deleting = (*head)?; let new_head = deleting.borrow(&tok).next; @@ -493,6 +522,21 @@ mod tests { let deleted = unsafe { deleting.free_heap(&mut tok) }; Some(deleted.data) } + + fn iter_ptrs<'i, I: 'i>( + head: Option>, + mut node_map: impl FnMut(P) -> (I, Option>) + 'i, + ) -> impl Iterator + 'i + where T: 'i + { + let mut next = head; + iter::from_fn(move || { + let node = next?; + let item; + (item, next) = node_map(node); + Some(item) + }) + } } impl Drop for List {