#![allow(unused)]
use std::fmt::{self, Debug};
+use std::hint::unreachable_unchecked;
use std::marker::PhantomData;
use std::ptr::NonNull;
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(())
}
Ok(())
}
}
-impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
+unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
self.0.alias_check_ref(p)
}
self.0.alias_check_mut(p)
}
}
-impl<T, L: MultiStaticList> MultiStaticList for (L, &mut T) {
+unsafe impl<T, L: MultiStaticList> 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)
impl<'a, L: MultiStaticList> MultiStatic<'a, L> {
pub fn borrow<'r, T>(self, p: Ptr<T>) -> 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<T>) -> 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
}
}
noalias: NoAliasSingleton,
}
+ #[derive(Debug, Eq, PartialEq)]
+ pub enum HeadAndTail<T> {
+ None,
+ One(T),
+ Both(T, T),
+ }
+
impl<T: Debug> List<T> {
pub fn new() -> Self {
let noalias = unsafe { NoAliasSingleton::init() };
)
}
+ 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>(
#[test]
fn demo() {
- use list::List;
+ use list::{List, HeadAndTail};
let s = |s: &str| format!("{s}");
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();