#![allow(unused)]
+use std::collections::HashSet;
use std::fmt::{self, Debug};
use std::hint::unreachable_unchecked;
use std::marker::PhantomData;
l: (),
}
}
+
+ fn multi_runtime<'r>(mut self) -> MultiRuntime<'r>
+ where 'a: 'r,
+ {
+ MultiRuntime {
+ tok: self.mut_token(),
+ ref_given: HashSet::new(),
+ mut_given: HashSet::new(),
+ }
+ }
}
unsafe impl<'a> IsRefToken<'a> for &'a NoAliasSingleton {}
unsafe impl<'a> IsRefToken<'a> for &'a mut NoAliasSingleton {}
l: L,
}
-fn forbid_alias<T>(this: &T, new: *const ()) -> Result<(), BorrowConflict> {
- let this = this as *const T as *const ();
- if this == new { return Err(BorrowConflict) }
+fn forbid_alias<T>(this: &T, new: NonNull<()>) -> Result<(), BorrowConflict> {
+ if NonNull::from(this) == new.cast() { return Err(BorrowConflict) }
Ok(())
}
pub unsafe trait MultiStaticList {
- fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict>;
- fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict>;
+ fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict>;
+ fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict>;
}
unsafe impl MultiStaticList for () {
- fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
Ok(())
}
- fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
Ok(())
}
}
unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &T) {
- fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
self.0.alias_check_ref(p)
}
- fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
forbid_alias(self.1, p)?;
self.0.alias_check_mut(p)
}
}
unsafe impl<T, L: MultiStaticList> MultiStaticList for (L, &mut T) {
- fn alias_check_ref(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_ref(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
forbid_alias(&*self.1, p)?;
self.0.alias_check_ref(p)
}
- fn alias_check_mut(&self, p: *const ()) -> Result<(), BorrowConflict> {
+ fn alias_check_mut(&self, p: NonNull<()>) -> Result<(), BorrowConflict> {
forbid_alias(&*self.1, p)?;
self.0.alias_check_mut(p)
}
>
where 'a: 'r
{
- match self.l.alias_check_ref(p.ptr.as_ptr() as *const ()) {
+ match self.l.alias_check_ref(p.ptr.cast()) {
Err(e) => Err(self),
Ok(()) => Ok(MultiStatic {
tok: self.tok,
>
where 'a: 'r
{
- match self.l.alias_check_mut(p.ptr.as_ptr() as *const ()) {
+ match self.l.alias_check_mut(p.ptr.cast()) {
Err(e) => Err(self),
Ok(()) => Ok(MultiStatic {
tok: self.tok,
}
}
+pub struct MultiRuntime<'a> {
+ tok: MutToken<'a>,
+ ref_given: HashSet<NonNull<()>>,
+ mut_given: HashSet<NonNull<()>>,
+}
+
+impl<'a> MultiRuntime<'a> {
+ #[inline]
+ pub fn borrow<'r, T>(&mut self, p: Ptr<T>)
+ -> Result<&'r T, BorrowConflict>
+ where 'a: 'r
+ {
+ self.borrow_inner_check(p.ptr.cast())?;
+ Ok(unsafe { p.ptr.as_ref() })
+ }
+
+ fn borrow_inner_check(&mut self, p: NonNull<()>)
+ -> Result<(), BorrowConflict>
+ {
+ if self.mut_given.contains(&p) {
+ return Err(BorrowConflict)
+ }
+ self.ref_given.insert(p);
+ Ok(())
+ }
+
+ #[inline]
+ pub fn borrow_mut<'r, T>(&mut self, mut p: Ptr<T>)
+ -> Result<&'r mut T, BorrowConflict>
+ where 'a: 'r
+ {
+ self.borrow_mut_inner_check(p.ptr.cast())?;
+ Ok(unsafe { p.ptr.as_mut() })
+ }
+
+ fn borrow_mut_inner_check(&mut self, p: NonNull<()>)
+ -> Result<(), BorrowConflict>
+{
+ if self.ref_given.contains(&p) {
+ return Err(BorrowConflict)
+ }
+ if !self.mut_given.insert(p) {
+ return Err(BorrowConflict)
+ }
+ Ok(())
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
}
+