refactor: simplify lifetime of cursor

This commit is contained in:
Zixuan Chen 2022-10-09 20:23:37 +08:00
parent 95b63e7f47
commit 41167b4af0
8 changed files with 71 additions and 79 deletions

View file

@ -1,4 +1,3 @@
use crdt_list::crdt::ListCrdt;
use rle::HasLength;
use crate::{

View file

@ -18,7 +18,7 @@ pub(super) struct ContentMap(RleTree<YSpan, YSpanTreeTrait>);
struct CursorWithId<'tree> {
id: ID,
cursor: UnsafeCursor<'tree, 'static, YSpan, YSpanTreeTrait>,
cursor: UnsafeCursor<'tree, YSpan, YSpanTreeTrait>,
}
impl ContentMap {
@ -37,7 +37,7 @@ impl ContentMap {
/// When we insert a new [YSpan] at given position, we need to calculate its `originLeft` and `originRight`
fn get_sibling_at(&self, pos: usize) -> (Option<CursorWithId<'_>>, Option<CursorWithId<'_>>) {
if let Some(cursor) = self.get(pos) {
let cursor: SafeCursor<'_, 'static, YSpan, YSpanTreeTrait> =
let cursor: SafeCursor<'_, YSpan, YSpanTreeTrait> =
// SAFETY: we only change the lifetime of the cursor; the returned lifetime is kinda wrong in this situation
// because Bumpalo's lifetime is static due to the self-referential structure limitation; Maybe there is a better way?
unsafe { std::mem::transmute(cursor) };
@ -153,8 +153,8 @@ impl DerefMut for ContentMap {
}
}
pub(super) fn change_status<'a, 'b: 'a>(
cursor: &mut SafeCursorMut<'a, 'b, YSpan, YSpanTreeTrait>,
pub(super) fn change_status(
cursor: &mut SafeCursorMut<'_, YSpan, YSpanTreeTrait>,
change: StatusChange,
) {
let value = cursor.as_mut();

View file

@ -25,7 +25,7 @@ pub(super) enum Marker {
}
impl Marker {
pub fn as_cursor(&self, id: ID) -> Option<SafeCursor<'_, 'static, YSpan, YSpanTreeTrait>> {
pub fn as_cursor(&self, id: ID) -> Option<SafeCursor<'static, YSpan, YSpanTreeTrait>> {
match self {
Marker::Insert { ptr, len: _ } => {
// SAFETY: tree data is always valid
@ -53,7 +53,7 @@ impl Marker {
pub fn as_cursor_mut(
&mut self,
id: ID,
) -> Option<SafeCursorMut<'_, 'static, YSpan, YSpanTreeTrait>> {
) -> Option<SafeCursorMut<'static, YSpan, YSpanTreeTrait>> {
match self {
Marker::Insert { ptr, len: _ } => {
// SAFETY: tree data is always valid

View file

@ -52,9 +52,9 @@ impl ListCrdt for YataImpl {
type Set = OpSpanSet;
type Cursor<'a> = SafeCursorMut<'a, 'static, YSpan, YSpanTreeTrait>;
type Cursor<'a> = SafeCursorMut<'a, YSpan, YSpanTreeTrait>;
type Iterator<'a> = IterMut<'a, 'static, YSpan, YSpanTreeTrait>;
type Iterator<'a> = IterMut<'a, YSpan, YSpanTreeTrait>;
fn iter(
container: &mut Self::Container,
@ -173,6 +173,7 @@ mod test {
#[cfg(feature = "fuzzing")]
pub mod fuzz {
#![allow(unused_imports)]
use crdt_list::{
test::{Action, TestFramework},
yata::Yata,

View file

@ -60,7 +60,7 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
/// return a cursor at the given index
#[inline]
pub fn get(&self, mut index: A::Int) -> Option<SafeCursor<'_, '_, T, A>> {
pub fn get(&self, mut index: A::Int) -> Option<SafeCursor<'_, T, A>> {
self.with_node(|mut node| {
loop {
match node {
@ -97,7 +97,7 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
/// return the first valid cursor after the given index
#[inline]
fn get_cursor_ge(&self, mut index: A::Int) -> Option<SafeCursor<'_, '_, T, A>> {
fn get_cursor_ge(&self, mut index: A::Int) -> Option<SafeCursor<'_, T, A>> {
self.with_node(|mut node| {
loop {
match node {
@ -133,24 +133,24 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
}
#[inline]
pub fn get_mut(&mut self, index: A::Int) -> Option<SafeCursorMut<'_, '_, T, A>> {
pub fn get_mut(&mut self, index: A::Int) -> Option<SafeCursorMut<'_, T, A>> {
let cursor = self.get(index);
cursor.map(|x| SafeCursorMut(x.0))
}
#[inline]
pub fn iter(&self) -> iter::Iter<'_, '_, T, A> {
pub fn iter(&self) -> iter::Iter<'_, T, A> {
// SAFETY: the cursor and iter cannot outlive self
self.with_node(|node| unsafe {
std::mem::transmute(iter::Iter::new(node.get_first_leaf()))
iter::Iter::new(std::mem::transmute(node.get_first_leaf()))
})
}
#[inline]
pub fn iter_mut(&mut self) -> iter::IterMut<'_, '_, T, A> {
pub fn iter_mut(&mut self) -> iter::IterMut<'_, T, A> {
// SAFETY: the cursor and iter cannot outlive self
self.with_node_mut(|node| unsafe {
std::mem::transmute(iter::IterMut::new(node.get_first_leaf_mut()))
iter::IterMut::new(std::mem::transmute(node.get_first_leaf_mut()))
})
}
@ -161,9 +161,9 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
pub fn iter_mut_in(
&mut self,
start: Option<SafeCursor<'_, '_, T, A>>,
end: Option<SafeCursor<'_, '_, T, A>>,
) -> iter::IterMut<'_, '_, T, A> {
start: Option<SafeCursor<'_, T, A>>,
end: Option<SafeCursor<'_, T, A>>,
) -> iter::IterMut<'_, T, A> {
if self.empty() || (start.is_none() && end.is_none()) {
self.iter_mut()
} else {
@ -174,10 +174,10 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
let start = start.unwrap_or_else(|| {
std::mem::transmute(SafeCursor::new(leaf, 0, 0, Position::Start, 0))
});
let start: SafeCursorMut<'_, '_, T, A> = SafeCursorMut(start.0);
std::mem::transmute::<_, iter::IterMut<'_, '_, T, A>>(iter::IterMut::from_cursor(
std::mem::transmute::<_, SafeCursorMut<'_, '_, T, A>>(start),
std::mem::transmute(end),
let start: SafeCursorMut<'_, T, A> = SafeCursorMut(start.0);
std::mem::transmute::<_, iter::IterMut<'_, T, A>>(iter::IterMut::from_cursor(
std::mem::transmute::<_, SafeCursorMut<'_, T, A>>(start),
end,
))
})
}
@ -204,7 +204,7 @@ impl<T: Rle, A: RleTreeTrait<T>> RleTree<T, A> {
})
}
pub fn iter_range(&self, start: A::Int, end: Option<A::Int>) -> iter::Iter<'_, '_, T, A> {
pub fn iter_range(&self, start: A::Int, end: Option<A::Int>) -> iter::Iter<'_, T, A> {
let cursor_from = self.get_cursor_ge(start);
if cursor_from.is_none() {
return iter::Iter::new(None);

View file

@ -6,8 +6,8 @@ use super::{node::LeafNode, tree_trait::Position};
/// when len > 0, it acts as a selection. When iterating the tree, the len should be the size of the element.
#[derive(PartialEq, Eq, Debug)]
pub struct UnsafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> {
pub leaf: NonNull<LeafNode<'bump, T, A>>,
pub struct UnsafeCursor<'tree, T: Rle, A: RleTreeTrait<T>> {
pub leaf: NonNull<LeafNode<'tree, T, A>>,
pub index: usize,
pub offset: usize,
pub pos: Position,
@ -15,7 +15,7 @@ pub struct UnsafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> {
_phantom: PhantomData<&'tree usize>,
}
impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> Clone for UnsafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> Clone for UnsafeCursor<'tree, T, A> {
#[inline]
fn clone(&self) -> Self {
Self {
@ -29,32 +29,28 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> Clone for UnsafeCursor<'tree, 'bu
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Copy for UnsafeCursor<'tree, 'bump, T, A> {}
impl<'tree, T: Rle, A: RleTreeTrait<T>> Copy for UnsafeCursor<'tree, T, A> {}
#[repr(transparent)]
#[derive(Debug)]
pub struct SafeCursor<'tree, 'bump, T: Rle, A: RleTreeTrait<T>>(
pub(crate) UnsafeCursor<'tree, 'bump, T, A>,
);
pub struct SafeCursor<'tree, T: Rle, A: RleTreeTrait<T>>(pub(crate) UnsafeCursor<'tree, T, A>);
#[repr(transparent)]
#[derive(Debug)]
pub struct SafeCursorMut<'tree, 'bump, T: Rle, A: RleTreeTrait<T>>(
pub(crate) UnsafeCursor<'tree, 'bump, T, A>,
);
pub struct SafeCursorMut<'tree, T: Rle, A: RleTreeTrait<T>>(pub(crate) UnsafeCursor<'tree, T, A>);
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Clone for SafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> Clone for SafeCursor<'tree, T, A> {
fn clone(&self) -> Self {
Self(self.0)
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Copy for SafeCursor<'tree, 'bump, T, A> {}
impl<'tree, T: Rle, A: RleTreeTrait<T>> Copy for SafeCursor<'tree, T, A> {}
impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, T, A> {
#[inline]
pub(crate) fn new(
leaf: NonNull<LeafNode<'bump, T, A>>,
leaf: NonNull<LeafNode<'tree, T, A>>,
index: usize,
offset: usize,
pos: Position,
@ -71,7 +67,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump, T, A>
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, T, A> {
/// # Safety
///
/// we need to make sure that the cursor is still valid
@ -209,7 +205,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> UnsafeCursor<'tree, 'bump,
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursor<'tree, T, A> {
#[inline]
fn as_ref(&self) -> &'tree T {
// SAFETY: SafeCursor is a shared reference to the tree
@ -217,13 +213,13 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursor<'t
}
}
impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
/// # Safety
///
/// Users should make sure aht leaf is pointing to a valid LeafNode with 'bump lifetime, and index is inbound
#[inline]
pub unsafe fn new(
leaf: NonNull<LeafNode<'bump, T, A>>,
leaf: NonNull<LeafNode<'tree, T, A>>,
index: usize,
offset: usize,
pos: Position,
@ -233,7 +229,7 @@ impl<'tree, 'bump, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T, A> {
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, T, A> {
#[inline]
pub fn as_tree_ref(&self) -> &'tree T {
// SAFETY: SafeCursor is a shared reference to the tree
@ -253,7 +249,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T
}
#[inline]
pub fn leaf(&self) -> &'tree LeafNode<'bump, T, A> {
pub fn leaf(&self) -> &'tree LeafNode<'tree, T, A> {
// SAFETY: SafeCursor has shared reference lifetime to the tree
unsafe { self.0.leaf.as_ref() }
}
@ -274,14 +270,12 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursor<'tree, 'bump, T
}
#[inline]
pub fn unwrap(self) -> UnsafeCursor<'tree, 'bump, T, A> {
pub fn unwrap(self) -> UnsafeCursor<'tree, T, A> {
self.0
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T>
for SafeCursorMut<'tree, 'bump, T, A>
{
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T> for SafeCursorMut<'tree, T, A> {
#[inline]
fn as_ref(&self) -> &T {
// SAFETY: SafeCursorMut is a exclusive reference to the tree
@ -289,7 +283,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsRef<T>
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, T, A> {
#[inline]
pub fn as_ref_(&self) -> &'tree T {
// SAFETY: SafeCursorMut is a exclusive reference to the tree
@ -297,13 +291,13 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
}
#[inline]
pub fn leaf(&self) -> &'tree LeafNode<'bump, T, A> {
pub fn leaf(&self) -> &'tree LeafNode<'tree, T, A> {
// SAFETY: SafeCursorMut is a exclusive reference to the tree
unsafe { self.0.leaf.as_ref() }
}
#[inline]
pub fn leaf_mut(&mut self) -> &'tree mut LeafNode<'bump, T, A> {
pub fn leaf_mut(&mut self) -> &'tree mut LeafNode<'tree, T, A> {
// SAFETY: SafeCursorMut is a exclusive reference to the tree
unsafe { self.0.leaf.as_mut() }
}
@ -314,13 +308,13 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, T, A> {
/// # Safety
///
/// User must be sure that there is not exclusive reference to the tree and leaf pointer is valid
#[inline]
pub unsafe fn new(
leaf: NonNull<LeafNode<'bump, T, A>>,
leaf: NonNull<LeafNode<'tree, T, A>>,
index: usize,
offset: usize,
pos: Position,
@ -353,7 +347,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
}
#[inline]
pub fn unwrap(self) -> UnsafeCursor<'tree, 'bump, T, A> {
pub fn unwrap(self) -> UnsafeCursor<'tree, T, A> {
self.0
}
@ -410,9 +404,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> SafeCursorMut<'tree, 'bump
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T>
for SafeCursorMut<'tree, 'bump, T, A>
{
impl<'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T> for SafeCursorMut<'tree, T, A> {
#[inline]
fn as_mut(&mut self) -> &mut T {
// SAFETY: SafeCursorMut is a exclusive reference to the tree so we are safe to
@ -421,7 +413,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> AsMut<T>
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Deref for SafeCursor<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> Deref for SafeCursor<'tree, T, A> {
type Target = T;
fn deref(&self) -> &Self::Target {
@ -429,7 +421,7 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Deref for SafeCursor<'tree
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Deref for SafeCursorMut<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> Deref for SafeCursorMut<'tree, T, A> {
type Target = T;
fn deref(&self) -> &Self::Target {

View file

@ -7,19 +7,19 @@ use super::{
};
/// cursor's and `end_cursor`'s length means nothing in this context
pub struct Iter<'some, 'bump, T: Rle, A: RleTreeTrait<T>> {
cursor: Option<UnsafeCursor<'some, 'bump, T, A>>,
end_cursor: Option<UnsafeCursor<'some, 'bump, T, A>>,
pub struct Iter<'some, T: Rle, A: RleTreeTrait<T>> {
cursor: Option<UnsafeCursor<'some, T, A>>,
end_cursor: Option<UnsafeCursor<'some, T, A>>,
}
pub struct IterMut<'some, 'bump, T: Rle, A: RleTreeTrait<T>> {
cursor: Option<UnsafeCursor<'some, 'bump, T, A>>,
end_cursor: Option<UnsafeCursor<'some, 'bump, T, A>>,
pub struct IterMut<'some, T: Rle, A: RleTreeTrait<T>> {
cursor: Option<UnsafeCursor<'some, T, A>>,
end_cursor: Option<UnsafeCursor<'some, T, A>>,
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, T, A> {
#[inline]
pub fn new(node: Option<&'tree mut LeafNode<'bump, T, A>>) -> Self {
pub fn new(node: Option<&'tree mut LeafNode<'tree, T, A>>) -> Self {
if node.is_none() {
return Self {
cursor: None,
@ -36,8 +36,8 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, 'bump, T, A
#[inline]
pub fn from_cursor(
mut start: SafeCursorMut<'tree, 'bump, T, A>,
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
mut start: SafeCursorMut<'tree, T, A>,
mut end: Option<SafeCursor<'tree, T, A>>,
) -> Self {
if start.0.pos == Position::After {
match start.next_elem_start() {
@ -70,9 +70,9 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> IterMut<'tree, 'bump, T, A
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iter<'tree, 'bump, T, A> {
impl<'tree, T: Rle, A: RleTreeTrait<T>> Iter<'tree, T, A> {
#[inline]
pub fn new(node: Option<&'tree LeafNode<'bump, T, A>>) -> Self {
pub fn new(node: Option<&'tree LeafNode<'tree, T, A>>) -> Self {
if node.is_none() {
return Self {
cursor: None,
@ -89,8 +89,8 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iter<'tree, 'bump, T, A> {
#[inline]
pub fn from_cursor(
mut start: SafeCursor<'tree, 'bump, T, A>,
mut end: Option<SafeCursor<'tree, 'bump, T, A>>,
mut start: SafeCursor<'tree, T, A>,
mut end: Option<SafeCursor<'tree, T, A>>,
) -> Option<Self> {
if start.0.pos == Position::After {
start = start.next_elem_start()?
@ -109,8 +109,8 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iter<'tree, 'bump, T, A> {
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iterator for Iter<'tree, 'bump, T, A> {
type Item = SafeCursor<'tree, 'bump, T, A>;
impl<'tree, T: Rle, A: RleTreeTrait<T>> Iterator for Iter<'tree, T, A> {
type Item = SafeCursor<'tree, T, A>;
fn next(&mut self) -> Option<Self::Item> {
self.cursor?;
@ -184,8 +184,8 @@ impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iterator for Iter<'tree, '
}
}
impl<'tree, 'bump: 'tree, T: Rle, A: RleTreeTrait<T>> Iterator for IterMut<'tree, 'bump, T, A> {
type Item = SafeCursorMut<'tree, 'bump, T, A>;
impl<'tree, T: Rle, A: RleTreeTrait<T>> Iterator for IterMut<'tree, T, A> {
type Item = SafeCursorMut<'tree, T, A>;
fn next(&mut self) -> Option<Self::Item> {
self.cursor?;

View file

@ -50,7 +50,7 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
}
#[inline]
pub fn get_cursor<'tree>(&'tree self, pos: A::Int) -> SafeCursor<'tree, 'bump, T, A> {
pub fn get_cursor<'tree>(&'tree self, pos: A::Int) -> SafeCursor<'bump, T, A> {
let result = A::find_pos_leaf(self, pos);
assert!(result.found);
// SAFETY: result.found is true
@ -66,7 +66,7 @@ impl<'bump, T: Rle, A: RleTreeTrait<T>> LeafNode<'bump, T, A> {
}
#[inline]
pub fn get_cursor_mut<'b>(&'b mut self, pos: A::Int) -> SafeCursorMut<'b, 'bump, T, A> {
pub fn get_cursor_mut<'b>(&'b mut self, pos: A::Int) -> SafeCursorMut<'bump, T, A> {
let result = A::find_pos_leaf(self, pos);
assert!(result.found);
// SAFETY: result.found is true