From 3c25ec61f973c27cf30f629cd914dde5770da7b0 Mon Sep 17 00:00:00 2001 From: orxfun Date: Thu, 4 Dec 2025 18:32:50 +0100 Subject: [PATCH 01/69] initiate test for walk with --- tests/node_ref_lifetime.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 tests/node_ref_lifetime.rs diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs new file mode 100644 index 0000000..00d9287 --- /dev/null +++ b/tests/node_ref_lifetime.rs @@ -0,0 +1,21 @@ +use orx_tree::traversal::*; +use orx_tree::*; + +fn find_node<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +where + V::Item: Eq, +{ + let mut traverser = Dfs::::new(); + let root_node = tree.get_root().unwrap(); + let node = { + let mut walker = root_node.walk_with(&mut traverser); + let x = walker.find(|v| v.data() == predicate); + // drop(walker); + // drop(traverser); + x + }; + + // ERROR: cannot return value referencing local variable `traverser` + // return node; + None +} From 45c67c68461e4382de4c36b93e5e3d2677ad32b2 Mon Sep 17 00:00:00 2001 From: orxfun Date: Thu, 4 Dec 2025 18:33:57 +0100 Subject: [PATCH 02/69] revise root method lifetimes --- src/tree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 14a36ff..cffcb7e 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -213,7 +213,7 @@ where /// tree.push_root('a'); /// assert_eq!(tree.root().data(), &'a'); /// ``` - pub fn root(&self) -> Node<'_, V, M, P> { + pub fn root<'a>(&'a self) -> Node<'a, V, M, P> { self.root_ptr() .map(|p| Node::new(&self.0, p)) .expect("Tree is empty and has no root. You may use `push_root` to add a root and/or `get_root` to safely access the root if it exists.") @@ -284,7 +284,7 @@ where /// tree.push_root('a'); /// assert_eq!(tree.root().data(), &'a'); /// ``` - pub fn get_root(&self) -> Option> { + pub fn get_root<'a>(&'a self) -> Option> { self.root_ptr().map(|p| Node::new(&self.0, p)) } From 3770a5da04290f9bec9ba0f058ffcd43838604f5 Mon Sep 17 00:00:00 2001 From: orxfun Date: Thu, 4 Dec 2025 18:36:02 +0100 Subject: [PATCH 03/69] fix root_mut method lifetimes --- src/tree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index cffcb7e..33bff6c 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -257,7 +257,7 @@ where /// tree.node_mut(b).push_child('d'); /// tree.node_mut(c).push_children(['e', 'f']); /// ``` - pub fn root_mut(&mut self) -> NodeMut<'_, V, M, P> { + pub fn root_mut<'a>(&'a mut self) -> NodeMut<'a, V, M, P> { self.root_ptr() .map(|p| NodeMut::new(&mut self.0, p)) .expect("Tree is empty and has no root. You may use `push_root` to add a root and/or `get_root` to safely access the root if it exists.") @@ -309,7 +309,7 @@ where /// tree.clear(); /// assert_eq!(tree.get_root_mut(), None); /// ``` - pub fn get_root_mut(&mut self) -> Option> { + pub fn get_root_mut<'a>(&'a mut self) -> Option> { self.root_ptr().map(|p| NodeMut::new(&mut self.0, p)) } From 3bd229ecf09e2325987ad3a062348281ed7d585f Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:00:56 +0100 Subject: [PATCH 04/69] clippy fix --- src/tree.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index 33bff6c..b0b3aba 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -405,7 +405,7 @@ where /// ``` #[inline(always)] pub fn node(&self, node_idx: NodeIdx) -> Node<'_, V, M, P> { - assert!(self.is_node_idx_valid(node_idx), "{}", INVALID_IDX_ERROR); + assert!(self.is_node_idx_valid(node_idx), "{INVALID_IDX_ERROR}"); Node::new(&self.0, node_idx.0.node_ptr()) } @@ -459,7 +459,7 @@ where /// ``` #[inline(always)] pub fn node_mut(&mut self, node_idx: NodeIdx) -> NodeMut<'_, V, M, P> { - assert!(self.is_node_idx_valid(node_idx), "{}", INVALID_IDX_ERROR); + assert!(self.is_node_idx_valid(node_idx), "{INVALID_IDX_ERROR}"); NodeMut::new(&mut self.0, node_idx.0.node_ptr()) } From 466c0070f03554bb15e4a6e0d566520ca1dd74d6 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:02:55 +0100 Subject: [PATCH 05/69] explicit lifetimes for all node getters from Tree --- src/tree.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/tree.rs b/src/tree.rs index b0b3aba..b840ada 100644 --- a/src/tree.rs +++ b/src/tree.rs @@ -404,7 +404,7 @@ where /// assert_eq!(bfs_values, [1, 2, 3, 4, 5]); /// ``` #[inline(always)] - pub fn node(&self, node_idx: NodeIdx) -> Node<'_, V, M, P> { + pub fn node<'a>(&'a self, node_idx: NodeIdx) -> Node<'a, V, M, P> { assert!(self.is_node_idx_valid(node_idx), "{INVALID_IDX_ERROR}"); Node::new(&self.0, node_idx.0.node_ptr()) } @@ -458,7 +458,7 @@ where /// assert_eq!(bfs_values, [1, 2, 3, 4, 5]); /// ``` #[inline(always)] - pub fn node_mut(&mut self, node_idx: NodeIdx) -> NodeMut<'_, V, M, P> { + pub fn node_mut<'a>(&'a mut self, node_idx: NodeIdx) -> NodeMut<'a, V, M, P> { assert!(self.is_node_idx_valid(node_idx), "{INVALID_IDX_ERROR}"); NodeMut::new(&mut self.0, node_idx.0.node_ptr()) } @@ -481,7 +481,7 @@ where /// [`NodeIdxError::RemovedNode`]: crate::NodeIdxError::RemovedNode /// [`NodeIdxError::ReorganizedCollection`]: crate::NodeIdxError::ReorganizedCollection #[inline(always)] - pub fn get_node(&self, node_idx: NodeIdx) -> Option> { + pub fn get_node<'a>(&'a self, node_idx: NodeIdx) -> Option> { self.is_node_idx_valid(node_idx) .then(|| Node::new(&self.0, node_idx.0.node_ptr())) } @@ -504,7 +504,7 @@ where /// [`NodeIdxError::RemovedNode`]: crate::NodeIdxError::RemovedNode /// [`NodeIdxError::ReorganizedCollection`]: crate::NodeIdxError::ReorganizedCollection #[inline(always)] - pub fn get_node_mut(&mut self, node_idx: NodeIdx) -> Option> { + pub fn get_node_mut<'a>(&'a mut self, node_idx: NodeIdx) -> Option> { self.is_node_idx_valid(node_idx) .then(|| NodeMut::new(&mut self.0, node_idx.0.node_ptr())) } @@ -525,7 +525,7 @@ where /// [`NodeIdxError::RemovedNode`]: crate::NodeIdxError::RemovedNode /// [`NodeIdxError::ReorganizedCollection`]: crate::NodeIdxError::ReorganizedCollection #[inline(always)] - pub fn try_node(&self, node_idx: NodeIdx) -> Result, NodeIdxError> { + pub fn try_node<'a>(&'a self, node_idx: NodeIdx) -> Result, NodeIdxError> { self.0 .try_get_ptr(node_idx.0) .map(|ptr| Node::new(&self.0, ptr)) @@ -547,10 +547,10 @@ where /// [`NodeIdxError::RemovedNode`]: crate::NodeIdxError::RemovedNode /// [`NodeIdxError::ReorganizedCollection`]: crate::NodeIdxError::ReorganizedCollection #[inline(always)] - pub fn try_node_mut( - &mut self, + pub fn try_node_mut<'a>( + &'a mut self, node_idx: NodeIdx, - ) -> Result, NodeIdxError> { + ) -> Result, NodeIdxError> { self.0 .try_get_ptr(node_idx.0) .map(|ptr| NodeMut::new(&mut self.0, ptr)) @@ -566,7 +566,7 @@ where /// [`node`]: Self::node /// [`is_node_idx_valid`]: Self::is_node_idx_valid #[inline(always)] - pub unsafe fn node_unchecked(&self, node_idx: NodeIdx) -> Node<'_, V, M, P> { + pub unsafe fn node_unchecked<'a>(&'a self, node_idx: NodeIdx) -> Node<'a, V, M, P> { Node::new(&self.0, node_idx.0.node_ptr()) } @@ -580,7 +580,10 @@ where /// [`node_mut`]: Self::node_mut /// [`is_node_idx_valid`]: Self::is_node_idx_valid #[inline(always)] - pub unsafe fn node_mut_unchecked(&mut self, node_idx: NodeIdx) -> NodeMut<'_, V, M, P> { + pub unsafe fn node_mut_unchecked<'a>( + &'a mut self, + node_idx: NodeIdx, + ) -> NodeMut<'a, V, M, P> { NodeMut::new(&mut self.0, node_idx.0.node_ptr()) } From 88ad2fbc4e39801cd6bb513c8723c86381ca70af Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:09:32 +0100 Subject: [PATCH 06/69] remove lifetime bound from noderef references, as it is already a reference with a specific lifetime --- src/node_ref.rs | 2 +- src/traversal/breadth_first/traverser_core.rs | 4 ++-- src/traversal/depth_first/traverser_core.rs | 4 ++-- src/traversal/post_order/traverser_core.rs | 4 ++-- src/traversal/traverser_core.rs | 5 +++-- tests/node_ref_lifetime.rs | 2 +- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index f0d733b..2dbc062 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1137,7 +1137,7 @@ where /// ); /// ``` fn walk_with<'t, T, O>( - &'a self, + &self, traverser: &'t mut T, ) -> impl Iterator> where diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index 1b68856..2979c57 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -40,7 +40,7 @@ impl TraverserCore for Bfs { } fn iter_with_storage<'a, V, M, P>( - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where @@ -55,7 +55,7 @@ impl TraverserCore for Bfs { fn iter<'a, V, M, P>( &'a mut self, - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> where V: TreeVariant + 'a, diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index af74c62..22cc833 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -40,7 +40,7 @@ impl TraverserCore for Dfs { } fn iter_with_storage<'a, V, M, P>( - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where @@ -55,7 +55,7 @@ impl TraverserCore for Dfs { fn iter<'a, V, M, P>( &'a mut self, - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> where V: TreeVariant + 'a, diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index ad64a69..bdd1fd4 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -40,7 +40,7 @@ impl TraverserCore for PostOrder { } fn iter_with_storage<'a, V, M, P>( - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where @@ -55,7 +55,7 @@ impl TraverserCore for PostOrder { fn iter<'a, V, M, P>( &'a mut self, - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> where V: TreeVariant + 'a, diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 0ce4b82..8592230 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -29,7 +29,7 @@ where V: TreeVariant + 'a; fn iter_with_storage<'a, V, M, P>( - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where @@ -76,12 +76,13 @@ where /// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode fn iter<'a, V, M, P>( &'a mut self, - node: &'a impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage; + fn iter_mut_with_storage<'a, V, M, P, MO>( node_mut: &'a mut NodeMut<'a, V, M, P, MO>, storage: impl SoM>, diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index 00d9287..d29894b 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -6,8 +6,8 @@ where V::Item: Eq, { let mut traverser = Dfs::::new(); - let root_node = tree.get_root().unwrap(); let node = { + let root_node = tree.get_root().unwrap(); let mut walker = root_node.walk_with(&mut traverser); let x = walker.find(|v| v.data() == predicate); // drop(walker); From e1010a083c131f3d8b5200a185add80338a1ff1b Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:18:19 +0100 Subject: [PATCH 07/69] define lifetime relations of traverser, node reference and returned iterator --- src/node_ref.rs | 6 +++--- src/traversal/breadth_first/traverser_core.rs | 9 +++++---- src/traversal/depth_first/traverser_core.rs | 9 +++++---- src/traversal/post_order/traverser_core.rs | 9 +++++---- src/traversal/traverser_core.rs | 11 ++++++----- tests/node_ref_lifetime.rs | 2 +- 6 files changed, 25 insertions(+), 21 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 2dbc062..297deb9 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1137,14 +1137,14 @@ where /// ); /// ``` fn walk_with<'t, T, O>( - &self, + &'t self, traverser: &'t mut T, - ) -> impl Iterator> + ) -> impl Iterator> + 't where O: Over, T: Traverser, Self: Sized, - 't: 'a, + 'a: 't, { traverser.iter(self) } diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index 2979c57..edd3c3d 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -53,14 +53,15 @@ impl TraverserCore for Bfs { BfsIterRef::<'_, _, M, P, _, _, _>::from((node.col(), iter)) } - fn iter<'a, V, M, P>( - &'a mut self, - node: &impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + fn iter<'t, 'a, V, M, P>( + &'t mut self, + node: &'t impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + 'a: 't, { let queue = self.queue.for_variant::(); Self::iter_with_storage(node, queue) diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index 22cc833..77044e0 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -53,14 +53,15 @@ impl TraverserCore for Dfs { DfsIterRef::<'_, _, M, P, _, _, _>::from((node.col(), iter)) } - fn iter<'a, V, M, P>( - &'a mut self, - node: &impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + fn iter<'t, 'a, V, M, P>( + &'t mut self, + node: &'t impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + 'a: 't, { let stack = self.stack.for_variant::(); Self::iter_with_storage(node, stack) diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index bdd1fd4..40b6fd7 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -53,14 +53,15 @@ impl TraverserCore for PostOrder { PostOrderIterRef::from((node.col(), iter_ptr)) } - fn iter<'a, V, M, P>( - &'a mut self, - node: &impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + fn iter<'t, 'a, V, M, P>( + &'t mut self, + node: &'t impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + 'a: 't, { let states = self.states.for_variant::(); Self::iter_with_storage(node, states) diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 8592230..44d10a8 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -74,14 +74,15 @@ where /// [`OverDepthNode`]: crate::traversal::OverDepthNode /// [`OverSiblingIdxNode`]: crate::traversal::OverSiblingIdxNode /// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode - fn iter<'a, V, M, P>( - &'a mut self, - node: &impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + fn iter<'t, 'a, V, M, P>( + &'t mut self, + node: &'t impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, - P: PinnedStorage; + P: PinnedStorage, + 'a: 't; fn iter_mut_with_storage<'a, V, M, P, MO>( node_mut: &'a mut NodeMut<'a, V, M, P, MO>, diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index d29894b..8635417 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -16,6 +16,6 @@ where }; // ERROR: cannot return value referencing local variable `traverser` - // return node; + return node; None } From 213305f72fae2a3a393377418662845d7112bb1d Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:22:02 +0100 Subject: [PATCH 08/69] add node_ref_lifetime_tests --- tests/node_ref_lifetime.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index 8635417..c0e655a 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -1,21 +1,31 @@ use orx_tree::traversal::*; use orx_tree::*; -fn find_node<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +/* +These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues/188. + +They are expected to compile. +*/ + +/// This method returns a Node that is referencing the `tree`. +/// +/// It must not fail to compile by due to errors: +/// * referencing local variable `traverser`, or +/// * referencing local variable `root_node`. +fn find_walk_with<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq, { let mut traverser = Dfs::::new(); - let node = { - let root_node = tree.get_root().unwrap(); - let mut walker = root_node.walk_with(&mut traverser); - let x = walker.find(|v| v.data() == predicate); - // drop(walker); - // drop(traverser); - x - }; + let root_node = tree.get_root()?; + let mut walker = root_node.walk_with(&mut traverser); + walker.find(|v| v.data() == predicate) +} + +#[test] +fn node_ref_lifetime_tests() { + let tree = DynTree::new(42); - // ERROR: cannot return value referencing local variable `traverser` - return node; - None + let node = find_walk_with(&tree, &33); + assert_eq!(node, None); } From f13e846ab4d8b5008bbd1cfa906fb9faf27bc7dc Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:35:21 +0100 Subject: [PATCH 09/69] define explicit lifetimes for NodeRef::walk and traversers --- src/node_ref.rs | 10 ++++++---- src/traversal/traverser_core.rs | 12 +++++++----- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 297deb9..12be46b 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -962,10 +962,11 @@ where /// let post_order: Vec<_> = n2.walk::().copied().collect(); /// assert_eq!(post_order, [8, 4, 5, 2]); /// ``` - fn walk(&'a self) -> impl Iterator + fn walk<'t, T>(&'t self) -> impl Iterator + 't where - T: Traverser, + T: Traverser + 'a, Self: Sized, + 'a: 't, { T::iter_with_owned_storage::(self) } @@ -985,11 +986,12 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn walk_par(&'a self) -> impl ParIter + fn walk_par<'t, T>(&'t self) -> impl ParIter where - T: Traverser, + T: Traverser + 'a, Self: Sized, V::Item: Send + Sync, + 'a: 't, { self.walk::().collect::>().into_par() } diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 44d10a8..6281a0c 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -28,8 +28,8 @@ where where V: TreeVariant + 'a; - fn iter_with_storage<'a, V, M, P>( - node: &impl NodeRef<'a, V, M, P>, + fn iter_with_storage<'t, 'a, V, M, P>( + node: &'t impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where @@ -223,13 +223,15 @@ where Self::iter_ptr_with_storage(node_ptr, Self::Storage::default()) } - fn iter_with_owned_storage<'a, V, M, P>( - node: &'a impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + fn iter_with_owned_storage<'t, 'a, V, M, P>( + node: &'t impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + 'a: 't, + Self: 't, { Self::iter_with_storage(node, Self::Storage::default()) } From 0c806e5307f6035009800710ca36333e929c64c6 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:35:31 +0100 Subject: [PATCH 10/69] add find_walk lifetime test --- tests/node_ref_lifetime.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index c0e655a..3ae4e2d 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -7,6 +7,20 @@ These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues They are expected to compile. */ +/// This method returns a Node that is referencing the `tree`. +/// +/// It must not fail to compile by due to errors: +/// * referencing local variable `traverser`, or +/// * referencing local variable `root_node`. +fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq, +{ + let root_node = tree.get_root()?; + let mut walker = root_node.walk::(); + walker.find(|v| v == &predicate) +} + /// This method returns a Node that is referencing the `tree`. /// /// It must not fail to compile by due to errors: @@ -26,6 +40,9 @@ where fn node_ref_lifetime_tests() { let tree = DynTree::new(42); + let node = find_walk(&tree, &33); + assert_eq!(node, None); + let node = find_walk_with(&tree, &33); assert_eq!(node, None); } From 340f7f4cc464f9c09011d27487558488e856f657 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:39:05 +0100 Subject: [PATCH 11/69] add find_walk_par lifetime test --- tests/node_ref_lifetime.rs | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index 3ae4e2d..c1e2962 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -5,13 +5,17 @@ use orx_tree::*; These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues/188. They are expected to compile. + +The `find` methods below return a node referencing the `tree`, which must be independent +of the root node or traverser if provided externally. + +The methods must NOT fail to compile due to the following errors: +* referencing local variable `traverser`, or +* referencing local variable `root_node`. + +These are temporary references. The output's lifetime must not depend on these temporary values. */ -/// This method returns a Node that is referencing the `tree`. -/// -/// It must not fail to compile by due to errors: -/// * referencing local variable `traverser`, or -/// * referencing local variable `root_node`. fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq, @@ -21,11 +25,15 @@ where walker.find(|v| v == &predicate) } -/// This method returns a Node that is referencing the `tree`. -/// -/// It must not fail to compile by due to errors: -/// * referencing local variable `traverser`, or -/// * referencing local variable `root_node`. +fn find_walk_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root_node = tree.get_root()?; + let walker = root_node.walk_par::(); + walker.find(|v| v == &predicate) +} + fn find_walk_with<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq, @@ -43,6 +51,9 @@ fn node_ref_lifetime_tests() { let node = find_walk(&tree, &33); assert_eq!(node, None); + let node = find_walk_par(&tree, &33); + assert_eq!(node, None); + let node = find_walk_with(&tree, &33); assert_eq!(node, None); } From 86b050a7bdddd36941591de665a3ec471aff5784 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:44:11 +0100 Subject: [PATCH 12/69] define custom_walk lifetimes --- src/node_ref.rs | 5 +++-- tests/node_ref_lifetime.rs | 25 +++++++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 12be46b..7f719b7 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -856,9 +856,10 @@ where /// let values: Vec<_> = tree.node(id3).custom_walk(next_node).copied().collect(); /// assert_eq!(values, [3, 6, 7, 10, 11]); /// ``` - fn custom_walk(&self, next_node: F) -> impl Iterator + fn custom_walk<'t, F>(&'t self, next_node: F) -> impl Iterator + 't where - F: Fn(Node<'a, V, M, P>) -> Option>, + F: Fn(Node<'a, V, M, P>) -> Option> + 't, + 'a: 't, { let iter_ptr = CustomWalkIterPtr::new(self.col(), Some(self.node_ptr()), next_node); iter_ptr.map(|ptr| { diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index c1e2962..03f4e07 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -16,6 +16,19 @@ The methods must NOT fail to compile due to the following errors: These are temporary references. The output's lifetime must not depend on these temporary values. */ +fn find_custom_walk<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option<&'a V::Item> +where + V::Item: Eq, +{ + let custom_walk = |node: Node<'a, V>| node.get_child(0); + let root_node = tree.get_root()?; + let mut walker = root_node.custom_walk(custom_walk); + walker.find(|v| v == &predicate) +} + fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq, @@ -48,12 +61,8 @@ where fn node_ref_lifetime_tests() { let tree = DynTree::new(42); - let node = find_walk(&tree, &33); - assert_eq!(node, None); - - let node = find_walk_par(&tree, &33); - assert_eq!(node, None); - - let node = find_walk_with(&tree, &33); - assert_eq!(node, None); + assert_eq!(find_custom_walk(&tree, &33), None); + assert_eq!(find_walk(&tree, &33), None); + assert_eq!(find_walk_par(&tree, &33), None); + assert_eq!(find_walk_with(&tree, &33), None); } From 79d67df8ca02db7fbcdb631cc3fe310cd00deedc Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:45:11 +0100 Subject: [PATCH 13/69] add find_custom_walk_par lifetime tests --- src/node_ref.rs | 5 +++-- tests/node_ref_lifetime.rs | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 7f719b7..add789a 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -881,10 +881,11 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn custom_walk_par(&self, next_node: F) -> impl ParIter + fn custom_walk_par<'t, F>(&'t self, next_node: F) -> impl ParIter + 't where - F: Fn(Node<'a, V, M, P>) -> Option>, + F: Fn(Node<'a, V, M, P>) -> Option> + 't, V::Item: Send + Sync, + 'a: 't, { self.custom_walk(next_node) .collect::>() diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index 03f4e07..82a3bcc 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -29,6 +29,19 @@ where walker.find(|v| v == &predicate) } +fn find_custom_walk_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let custom_walk = |node: Node<'a, V>| node.get_child(0); + let root_node = tree.get_root()?; + let walker = root_node.custom_walk_par(custom_walk); + walker.find(|v| v == &predicate) +} + fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq, @@ -62,6 +75,7 @@ fn node_ref_lifetime_tests() { let tree = DynTree::new(42); assert_eq!(find_custom_walk(&tree, &33), None); + assert_eq!(find_custom_walk_par(&tree, &33), None); assert_eq!(find_walk(&tree, &33), None); assert_eq!(find_walk_par(&tree, &33), None); assert_eq!(find_walk_with(&tree, &33), None); From 22e99250fe2c8900a77abc95afe3856b9540ad81 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 10:47:10 +0100 Subject: [PATCH 14/69] explicit lifetime relations for walk_with_par --- src/node_ref.rs | 4 ++-- tests/node_ref_lifetime.rs | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index add789a..8a3d3c1 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1166,15 +1166,15 @@ where /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] fn walk_with_par<'t, T, O>( - &'a self, + &'t self, traverser: &'t mut T, ) -> impl ParIter> where O: Over, T: Traverser, Self: Sized, - 't: 'a, OverItem<'a, V, O, M, P>: Send + Sync, + 'a: 't, { self.walk_with(traverser) .collect::>() diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs index 82a3bcc..5cd6bb3 100644 --- a/tests/node_ref_lifetime.rs +++ b/tests/node_ref_lifetime.rs @@ -70,6 +70,19 @@ where walker.find(|v| v.data() == predicate) } +fn find_walk_with_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root_node = tree.get_root()?; + let walker = root_node.walk_with_par(&mut traverser); + walker.find(|v| v.data() == predicate) +} + #[test] fn node_ref_lifetime_tests() { let tree = DynTree::new(42); @@ -79,4 +92,5 @@ fn node_ref_lifetime_tests() { assert_eq!(find_walk(&tree, &33), None); assert_eq!(find_walk_par(&tree, &33), None); assert_eq!(find_walk_with(&tree, &33), None); + assert_eq!(find_walk_with_par(&tree, &33), None); } From 5d76250881af986679fd251b6da116a1ae20a4dd Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:07:29 +0100 Subject: [PATCH 15/69] explicit lifetimes for paths, leaves and indices iterators of NodeRef and NodeMut --- src/node_mut.rs | 6 +- src/node_ref.rs | 22 +++-- src/traversal/traverser_core.rs | 11 +-- tests/iterator_lifetimes.rs | 141 ++++++++++++++++++++++++++++++++ tests/node_ref_lifetime.rs | 96 ---------------------- 5 files changed, 166 insertions(+), 110 deletions(-) create mode 100644 tests/iterator_lifetimes.rs delete mode 100644 tests/node_ref_lifetime.rs diff --git a/src/node_mut.rs b/src/node_mut.rs index b900672..c8c32af 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -2598,9 +2598,11 @@ where /// let leaves: Vec<_> = n3.leaves::().copied().collect(); /// assert_eq!(leaves, [209, 210, 211]); /// ``` - pub fn leaves_mut(&'a mut self) -> impl Iterator + pub fn leaves_mut<'t, T>(&'t mut self) -> impl Iterator + 't where - T: Traverser, + T: Traverser + 't, + ::Storage: 't, + 'a: 't, { T::iter_ptr_with_owned_storage(self.node_ptr()) .filter(|x: &NodePtr| unsafe { &*x.ptr() }.next().is_empty()) diff --git a/src/node_ref.rs b/src/node_ref.rs index 8a3d3c1..e934f5f 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1282,9 +1282,13 @@ where /// .unwrap(); /// assert_eq!(max_label_path, vec![9, 6, 3, 1]); /// ``` - fn paths(&'a self) -> impl Iterator + Clone> + fn paths<'t, T>( + &'t self, + ) -> impl Iterator + Clone> + 't where - T: Traverser, + T: Traverser + 't, + ::Storage: 't, + 'a: 't, { let node_ptr = self.node_ptr(); T::iter_ptr_with_owned_storage(node_ptr) @@ -1762,9 +1766,11 @@ where /// .collect(); /// assert_eq!(bfs_leaves, [5, 8, 9, 10, 11]); /// ``` - fn leaves(&'a self) -> impl Iterator + fn leaves<'t, T>(&'t self) -> impl Iterator + 't where - T: Traverser, + T: Traverser + 't, + ::Storage: 't, + 'a: 't, { T::iter_ptr_with_owned_storage(self.node_ptr()) .filter(|x: &NodePtr| unsafe { &*x.ptr() }.next().is_empty()) @@ -1983,10 +1989,12 @@ where /// assert_eq!(a.node(dfs_indices[2]).data(), &3); /// assert_eq!(a.node(dfs_indices[3]).data(), &7); /// ``` - fn indices(&self) -> impl Iterator> + fn indices<'t, T>(&'t self) -> impl Iterator> + 't where - T: Traverser, - V: 'static, + T: Traverser + 't, + ::Storage: 't, + V: 't, + 'a: 't, { let node_ptr = self.node_ptr(); let state = self.col().memory_state(); diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 6281a0c..93a89aa 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -21,12 +21,12 @@ where fn storage_mut(&mut self) -> &mut Self::Storage; - fn iter_ptr_with_storage<'a, V>( + fn iter_ptr_with_storage<'t, V>( node_ptr: NodePtr, - storage: impl SoM>, + storage: impl SoM> + 't, ) -> impl Iterator::Item>> where - V: TreeVariant + 'a; + V: TreeVariant + 't; fn iter_with_storage<'t, 'a, V, M, P>( node: &'t impl NodeRef<'a, V, M, P>, @@ -214,11 +214,12 @@ where // provided - fn iter_ptr_with_owned_storage<'a, V>( + fn iter_ptr_with_owned_storage<'t, V>( node_ptr: NodePtr, ) -> impl Iterator::Item>> where - V: TreeVariant + 'a, + V: TreeVariant + 't, + >::Storage: 't, { Self::iter_ptr_with_storage(node_ptr, Self::Storage::default()) } diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs new file mode 100644 index 0000000..a5ff881 --- /dev/null +++ b/tests/iterator_lifetimes.rs @@ -0,0 +1,141 @@ +use orx_tree::traversal::*; +use orx_tree::*; + +/* +These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues/188. + +They are expected to compile. + +The `find` methods below return a node referencing the `tree`, which must be independent +of the root node or traverser if provided externally. + +The methods must NOT fail to compile due to the following errors: +* referencing local variable `traverser`, or +* referencing local variable `root`. + +These are temporary references. The output's lifetime must not depend on these temporary values. +*/ + +fn find_custom_walk<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option<&'a V::Item> +where + V::Item: Eq, +{ + let custom_walk = |node: Node<'a, V>| node.get_child(0); + let root = tree.get_root()?; + let mut walker = root.custom_walk(custom_walk); + walker.find(|v| v == &predicate) +} + +fn find_custom_walk_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let custom_walk = |node: Node<'a, V>| node.get_child(0); + let root = tree.get_root()?; + let walker = root.custom_walk_par(custom_walk); + walker.find(|v| v == &predicate) +} + +fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq, +{ + let root = tree.get_root()?; + let mut walker = root.walk::(); + walker.find(|v| v == &predicate) +} + +fn find_walk_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + let walker = root.walk_par::(); + walker.find(|v| v == &predicate) +} + +fn find_walk_with<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +where + V::Item: Eq, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + let mut walker = root.walk_with(&mut traverser); + walker.find(|v| v.data() == predicate) +} + +fn find_walk_with_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + let walker = root.walk_with_par(&mut traverser); + walker.find(|v| v.data() == predicate) +} + +fn find_paths<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.paths::() + .find(|x| x.clone().collect::>().contains(&predicate)) + .and_then(|mut x| x.next()) +} + +fn find_leaves<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.leaves::().find(|v| v == &predicate) +} + +fn find_indices<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.indices::() + .find(|v| tree.node(*v).data() == predicate) +} + +// mut + +fn find_leaves_mut<'a, V: TreeVariant>( + tree: &'a mut Tree, + predicate: &V::Item, +) -> Option<&'a mut V::Item> +where + V::Item: Eq + Sync + Send, +{ + let mut root = tree.get_root_mut()?; + root.leaves_mut::().find(|v| v == &predicate) +} + +#[test] +fn node_ref_lifetime_tests() { + let mut tree = DynTree::new(42); + + assert_eq!(find_custom_walk(&tree, &7), None); + assert_eq!(find_custom_walk_par(&tree, &7), None); + assert_eq!(find_walk(&tree, &7), None); + assert_eq!(find_walk_par(&tree, &7), None); + assert_eq!(find_walk_with(&tree, &7), None); + assert_eq!(find_walk_with_par(&tree, &7), None); + assert_eq!(find_paths(&tree, &7), None); + assert_eq!(find_leaves(&tree, &7), None); + assert_eq!(find_indices(&tree, &7), None); + + assert_eq!(find_leaves_mut(&mut tree, &7), None); + diff --git a/tests/node_ref_lifetime.rs b/tests/node_ref_lifetime.rs deleted file mode 100644 index 5cd6bb3..0000000 --- a/tests/node_ref_lifetime.rs +++ /dev/null @@ -1,96 +0,0 @@ -use orx_tree::traversal::*; -use orx_tree::*; - -/* -These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues/188. - -They are expected to compile. - -The `find` methods below return a node referencing the `tree`, which must be independent -of the root node or traverser if provided externally. - -The methods must NOT fail to compile due to the following errors: -* referencing local variable `traverser`, or -* referencing local variable `root_node`. - -These are temporary references. The output's lifetime must not depend on these temporary values. -*/ - -fn find_custom_walk<'a, V: TreeVariant>( - tree: &'a Tree, - predicate: &V::Item, -) -> Option<&'a V::Item> -where - V::Item: Eq, -{ - let custom_walk = |node: Node<'a, V>| node.get_child(0); - let root_node = tree.get_root()?; - let mut walker = root_node.custom_walk(custom_walk); - walker.find(|v| v == &predicate) -} - -fn find_custom_walk_par<'a, V: TreeVariant>( - tree: &'a Tree, - predicate: &V::Item, -) -> Option<&'a V::Item> -where - V::Item: Eq + Sync + Send, -{ - let custom_walk = |node: Node<'a, V>| node.get_child(0); - let root_node = tree.get_root()?; - let walker = root_node.custom_walk_par(custom_walk); - walker.find(|v| v == &predicate) -} - -fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> -where - V::Item: Eq, -{ - let root_node = tree.get_root()?; - let mut walker = root_node.walk::(); - walker.find(|v| v == &predicate) -} - -fn find_walk_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> -where - V::Item: Eq + Sync + Send, -{ - let root_node = tree.get_root()?; - let walker = root_node.walk_par::(); - walker.find(|v| v == &predicate) -} - -fn find_walk_with<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> -where - V::Item: Eq, -{ - let mut traverser = Dfs::::new(); - let root_node = tree.get_root()?; - let mut walker = root_node.walk_with(&mut traverser); - walker.find(|v| v.data() == predicate) -} - -fn find_walk_with_par<'a, V: TreeVariant>( - tree: &'a Tree, - predicate: &V::Item, -) -> Option> -where - V::Item: Eq + Sync + Send, -{ - let mut traverser = Dfs::::new(); - let root_node = tree.get_root()?; - let walker = root_node.walk_with_par(&mut traverser); - walker.find(|v| v.data() == predicate) -} - -#[test] -fn node_ref_lifetime_tests() { - let tree = DynTree::new(42); - - assert_eq!(find_custom_walk(&tree, &33), None); - assert_eq!(find_custom_walk_par(&tree, &33), None); - assert_eq!(find_walk(&tree, &33), None); - assert_eq!(find_walk_par(&tree, &33), None); - assert_eq!(find_walk_with(&tree, &33), None); - assert_eq!(find_walk_with_par(&tree, &33), None); -} From 5e54ca809fd5a1532e8161f731745ef56d6bbe33 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:07:43 +0100 Subject: [PATCH 16/69] fix --- tests/iterator_lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index a5ff881..d1f4bfc 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -138,4 +138,4 @@ fn node_ref_lifetime_tests() { assert_eq!(find_indices(&tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); - +} From acd8dbd301a1fe8b9654f44e17c42cd98cc37bad Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:08:58 +0100 Subject: [PATCH 17/69] explicit lifetimes for find_paths_par --- src/node_ref.rs | 3 ++- tests/iterator_lifetimes.rs | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index e934f5f..12fd5f1 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1387,10 +1387,11 @@ where /// assert_eq!(best_path, expected.iter().collect::>()); /// ``` #[cfg(feature = "parallel")] - fn paths_par(&'a self) -> impl ParIter + Clone> + fn paths_par<'t, T>(&'t self) -> impl ParIter + Clone> where T: Traverser, V::Item: Send + Sync, + 'a: 't, { let node_ptr = self.node_ptr(); let node_ptrs: alloc::vec::Vec<_> = T::iter_ptr_with_owned_storage(node_ptr) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index d1f4bfc..800bb92 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -93,6 +93,16 @@ where .and_then(|mut x| x.next()) } +fn find_paths_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.paths_par::() + .find(|x| x.clone().collect::>().contains(&predicate)) + .and_then(|mut x| x.next()) +} + fn find_leaves<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq + Sync + Send, @@ -134,6 +144,7 @@ fn node_ref_lifetime_tests() { assert_eq!(find_walk_with(&tree, &7), None); assert_eq!(find_walk_with_par(&tree, &7), None); assert_eq!(find_paths(&tree, &7), None); + assert_eq!(find_paths_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); From 864c19ad44ded5209ee6bb327b56ee688cc65c48 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:11:05 +0100 Subject: [PATCH 18/69] explicit lifetimes for paths_with --- src/node_ref.rs | 11 ++++++----- tests/iterator_lifetimes.rs | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 12fd5f1..20b4dab 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1495,13 +1495,14 @@ where /// ] /// ); /// ``` - fn paths_with( - &'a self, - traverser: &'a mut T, - ) -> impl Iterator::NodeItem<'a, V, M, P>> + Clone> + fn paths_with<'t, T, O>( + &'t self, + traverser: &'t mut T, + ) -> impl Iterator::NodeItem<'a, V, M, P>> + Clone> + 't where O: Over, - T: Traverser, + T: Traverser + 't, + 'a: 't, { let node_ptr = self.node_ptr(); T::iter_ptr_with_storage(node_ptr, TraverserCore::storage_mut(traverser)) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 800bb92..b9e015a 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -93,6 +93,25 @@ where .and_then(|mut x| x.next()) } +fn find_paths_with<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + root.paths_with(&mut traverser) + .find(|x| { + x.clone() + .map(|x| x.data()) + .collect::>() + .contains(&predicate) + }) + .and_then(|mut x| x.next()) +} + fn find_paths_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq + Sync + Send, @@ -144,6 +163,7 @@ fn node_ref_lifetime_tests() { assert_eq!(find_walk_with(&tree, &7), None); assert_eq!(find_walk_with_par(&tree, &7), None); assert_eq!(find_paths(&tree, &7), None); + assert_eq!(find_paths_with(&tree, &7), None); assert_eq!(find_paths_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); From af1d74c6e367c6688eb74dab7111c1f77b98b41d Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:12:49 +0100 Subject: [PATCH 19/69] define explicit lifetime relations for paths_par_with iterator --- src/node_ref.rs | 11 ++++++----- tests/iterator_lifetimes.rs | 22 +++++++++++++++++++++- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 20b4dab..07c9f52 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1608,15 +1608,16 @@ where /// assert_eq!(best_path, expected.iter().collect::>()); /// ``` #[cfg(feature = "parallel")] - fn paths_with_par( - &'a self, - traverser: &'a mut T, - ) -> impl ParIter::NodeItem<'a, V, M, P>> + Clone> + fn paths_with_par<'t, T, O>( + &'t self, + traverser: &'t mut T, + ) -> impl ParIter::NodeItem<'a, V, M, P>> + Clone> + 't where O: Over, - T: Traverser, + T: Traverser + 't, V::Item: Send + Sync, Self: Sync, + 'a: 't, { let node_ptr = self.node_ptr(); diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index b9e015a..e3678fc 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -112,6 +112,25 @@ where .and_then(|mut x| x.next()) } +fn find_paths_with_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + root.paths_with_par(&mut traverser) + .find(|x| { + x.clone() + .map(|x| x.data()) + .collect::>() + .contains(&predicate) + }) + .and_then(|mut x| x.next()) +} + fn find_paths_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq + Sync + Send, @@ -163,8 +182,9 @@ fn node_ref_lifetime_tests() { assert_eq!(find_walk_with(&tree, &7), None); assert_eq!(find_walk_with_par(&tree, &7), None); assert_eq!(find_paths(&tree, &7), None); - assert_eq!(find_paths_with(&tree, &7), None); assert_eq!(find_paths_par(&tree, &7), None); + assert_eq!(find_paths_with(&tree, &7), None); + assert_eq!(find_paths_with_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); From dfc9ef5cb4c866b948c9c8a6e5959276d559ffce Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:14:06 +0100 Subject: [PATCH 20/69] explicit leaves_par lifetime relations --- src/node_ref.rs | 5 +++-- tests/iterator_lifetimes.rs | 12 ++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 07c9f52..a7c9f1e 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1797,10 +1797,11 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn leaves_par(&'a self) -> impl ParIter + fn leaves_par<'t, T>(&'t self) -> impl ParIter + 't where - T: Traverser, + T: Traverser + 't, V::Item: Send + Sync, + 'a: 't, { self.leaves::() .collect::>() diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index e3678fc..bf2f29f 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -149,6 +149,17 @@ where root.leaves::().find(|v| v == &predicate) } +fn find_leaves_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option<&'a V::Item> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.leaves_par::().find(|v| v == &predicate) +} + fn find_indices<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, @@ -186,6 +197,7 @@ fn node_ref_lifetime_tests() { assert_eq!(find_paths_with(&tree, &7), None); assert_eq!(find_paths_with_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); + assert_eq!(find_leaves_par(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); From be8e7117ac99f033b81c88df7781c6deec431a43 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:18:06 +0100 Subject: [PATCH 21/69] explicit lifetimes for NodeRef::leaves_with and leaves_with_par --- src/node_ref.rs | 26 ++++++++++++++------------ tests/iterator_lifetimes.rs | 28 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index a7c9f1e..1906ef9 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -966,7 +966,7 @@ where /// ``` fn walk<'t, T>(&'t self) -> impl Iterator + 't where - T: Traverser + 'a, + T: Traverser + 't, Self: Sized, 'a: 't, { @@ -990,7 +990,7 @@ where #[cfg(feature = "parallel")] fn walk_par<'t, T>(&'t self) -> impl ParIter where - T: Traverser + 'a, + T: Traverser + 't, Self: Sized, V::Item: Send + Sync, 'a: 't, @@ -1501,7 +1501,7 @@ where ) -> impl Iterator::NodeItem<'a, V, M, P>> + Clone> + 't where O: Over, - T: Traverser + 't, + T: Traverser, 'a: 't, { let node_ptr = self.node_ptr(); @@ -1614,7 +1614,7 @@ where ) -> impl ParIter::NodeItem<'a, V, M, P>> + Clone> + 't where O: Over, - T: Traverser + 't, + T: Traverser, V::Item: Send + Sync, Self: Sync, 'a: 't, @@ -1799,7 +1799,7 @@ where #[cfg(feature = "parallel")] fn leaves_par<'t, T>(&'t self) -> impl ParIter + 't where - T: Traverser + 't, + T: Traverser, V::Item: Send + Sync, 'a: 't, { @@ -1887,13 +1887,14 @@ where /// assert_eq!(sibling_idx, 0); /// assert_eq!(leaf.data(), &8); /// ``` - fn leaves_with( - &'a self, - traverser: &'a mut T, - ) -> impl Iterator> + fn leaves_with<'t, T, O>( + &'t self, + traverser: &'t mut T, + ) -> impl Iterator> + 't where O: Over, T: Traverser, + 'a: 't, { T::iter_ptr_with_storage(self.node_ptr(), traverser.storage_mut()) .filter(|x| { @@ -1920,14 +1921,15 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn leaves_with_par( - &'a self, - traverser: &'a mut T, + fn leaves_with_par<'t, T, O>( + &'t self, + traverser: &'t mut T, ) -> impl ParIter> where O: Over, T: Traverser, OverItem<'a, V, O, M, P>: Send + Sync, + 'a: 't, { self.leaves_with(traverser) .collect::>() diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index bf2f29f..8d18e84 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -160,6 +160,32 @@ where root.leaves_par::().find(|v| v == &predicate) } +fn find_leaves_with<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + root.leaves_with(&mut traverser) + .find(|v| v.data() == predicate) +} + +fn find_leaves_with_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + root.leaves_with_par(&mut traverser) + .find(|v| v.data() == predicate) +} + fn find_indices<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, @@ -198,6 +224,8 @@ fn node_ref_lifetime_tests() { assert_eq!(find_paths_with_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); assert_eq!(find_leaves_par(&tree, &7), None); + assert_eq!(find_leaves_with(&tree, &7), None); + assert_eq!(find_leaves_with_par(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); From cd0016c0887e1bd9ef7a2c59ede053c75f916b5e Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:19:47 +0100 Subject: [PATCH 22/69] explicit lifetimes for NodeRef::indices_with --- src/node_ref.rs | 11 +++++------ tests/iterator_lifetimes.rs | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 1906ef9..f24a872 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1999,7 +1999,6 @@ where where T: Traverser + 't, ::Storage: 't, - V: 't, 'a: 't, { let node_ptr = self.node_ptr(); @@ -2028,15 +2027,15 @@ where /// This method additionally allow for yielding node depths and sibling indices in addition to node indices. /// /// [`indices_with`]: crate::NodeRef::indices_with - fn indices_with( - &self, - traverser: &mut T, - ) -> impl Iterator::Item>> + fn indices_with<'t, T, O>( + &'t self, + traverser: &'t mut T, + ) -> impl Iterator::Item>> + 't where O: Over, T: Traverser, - V: 'static, Self: Sized, + 'a: 't, { let node_ptr = self.node_ptr(); let state = self.col().memory_state(); diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 8d18e84..2ca470b 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -195,6 +195,19 @@ where .find(|v| tree.node(*v).data() == predicate) } +fn find_indices_with<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let root = tree.get_root()?; + root.indices_with(&mut traverser) + .find(|v| tree.node(*v).data() == predicate) +} + // mut fn find_leaves_mut<'a, V: TreeVariant>( @@ -227,6 +240,7 @@ fn node_ref_lifetime_tests() { assert_eq!(find_leaves_with(&tree, &7), None); assert_eq!(find_leaves_with_par(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); + assert_eq!(find_indices_with(&tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); } From d1936a6027dd69ba383c9f3f4bd4d6d1984ec409 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:22:04 +0100 Subject: [PATCH 23/69] explicit lifetime relations for NodeRef::children --- src/node_ref.rs | 5 ++++- tests/iterator_lifetimes.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index f24a872..3625b5a 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -295,7 +295,10 @@ where /// /// assert_eq!(data, ['a', 'c', 'd', 'e', 'b']); /// ``` - fn children(&'a self) -> impl ExactSizeIterator> { + fn children<'t>(&'t self) -> impl ExactSizeIterator> + 't + where + 'a: 't, + { self.node() .next() .children_ptr() diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 2ca470b..4d6f736 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -16,6 +16,14 @@ The methods must NOT fail to compile due to the following errors: These are temporary references. The output's lifetime must not depend on these temporary values. */ +fn find_children<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +where + V::Item: Eq, +{ + let root = tree.get_root()?; + root.children().find(|x| x.data() == predicate) +} + fn find_custom_walk<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -225,6 +233,7 @@ where fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); + assert_eq!(find_children(&tree, &7), None); assert_eq!(find_custom_walk(&tree, &7), None); assert_eq!(find_custom_walk_par(&tree, &7), None); assert_eq!(find_walk(&tree, &7), None); From 0a10d94e59346271ce7d6f38703403212f99e877 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:23:30 +0100 Subject: [PATCH 24/69] explicit lifetimes for NodeRef::children_par --- src/node_ref.rs | 3 ++- tests/iterator_lifetimes.rs | 20 ++++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 3625b5a..e22a30b 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -376,10 +376,11 @@ where /// assert_eq!(seq_value, par_value_4t); /// ``` #[cfg(feature = "parallel")] - fn children_par(&'a self) -> impl ParIter> + fn children_par<'t>(&'t self) -> impl ParIter> + 't where V::Item: Send + Sync, Self: Sync, + 'a: 't, { self.node() .next() diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 4d6f736..aaccbe3 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -18,18 +18,29 @@ These are temporary references. The output's lifetime must not depend on these t fn find_children<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where - V::Item: Eq, + V::Item: Eq + Sync + Send, { let root = tree.get_root()?; root.children().find(|x| x.data() == predicate) } +fn find_children_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.children_par().find(|x| x.data() == predicate) +} + fn find_custom_walk<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, ) -> Option<&'a V::Item> where - V::Item: Eq, + V::Item: Eq + Sync + Send, { let custom_walk = |node: Node<'a, V>| node.get_child(0); let root = tree.get_root()?; @@ -52,7 +63,7 @@ where fn find_walk<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where - V::Item: Eq, + V::Item: Eq + Sync + Send, { let root = tree.get_root()?; let mut walker = root.walk::(); @@ -70,7 +81,7 @@ where fn find_walk_with<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where - V::Item: Eq, + V::Item: Eq + Sync + Send, { let mut traverser = Dfs::::new(); let root = tree.get_root()?; @@ -234,6 +245,7 @@ fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); assert_eq!(find_children(&tree, &7), None); + assert_eq!(find_children_par(&tree, &7), None); assert_eq!(find_custom_walk(&tree, &7), None); assert_eq!(find_custom_walk_par(&tree, &7), None); assert_eq!(find_walk(&tree, &7), None); From ff426ac0cf3937880af05731db39aac061612094 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:24:20 +0100 Subject: [PATCH 25/69] simplify children lifetimes --- src/node_ref.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index e22a30b..c0279f0 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -295,10 +295,7 @@ where /// /// assert_eq!(data, ['a', 'c', 'd', 'e', 'b']); /// ``` - fn children<'t>(&'t self) -> impl ExactSizeIterator> + 't - where - 'a: 't, - { + fn children(&self) -> impl ExactSizeIterator> { self.node() .next() .children_ptr() @@ -376,11 +373,10 @@ where /// assert_eq!(seq_value, par_value_4t); /// ``` #[cfg(feature = "parallel")] - fn children_par<'t>(&'t self) -> impl ParIter> + 't + fn children_par(&self) -> impl ParIter> where V::Item: Send + Sync, Self: Sync, - 'a: 't, { self.node() .next() From 70c81864fc408865ac224e5c231ba55e606ccdd5 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:25:27 +0100 Subject: [PATCH 26/69] fix NodeRef::ancestors lifetime relations --- src/node_ref.rs | 2 +- tests/iterator_lifetimes.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index c0279f0..ac8994a 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -663,7 +663,7 @@ where /// let ancestors_data: Vec<_> = n4.ancestors().map(|x| *x.data()).collect(); /// assert_eq!(ancestors_data, [2, 1]); /// ``` - fn ancestors(&'a self) -> impl Iterator> { + fn ancestors(&self) -> impl Iterator> { let root_ptr = self.col().ends().get().expect("Tree is non-empty"); AncestorsIterPtr::new(root_ptr, self.node_ptr()) .skip(1) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index aaccbe3..81ca2c5 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -16,6 +16,14 @@ The methods must NOT fail to compile due to the following errors: These are temporary references. The output's lifetime must not depend on these temporary values. */ +fn find_ancestors<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.ancestors().find(|x| x.data() == predicate) +} + fn find_children<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, @@ -244,6 +252,7 @@ where fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); + assert_eq!(find_ancestors(&tree, &7), None); assert_eq!(find_children(&tree, &7), None); assert_eq!(find_children_par(&tree, &7), None); assert_eq!(find_custom_walk(&tree, &7), None); From 1dc5d07eb28b48abcc3104f667edcabb6d2d394d Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:26:16 +0100 Subject: [PATCH 27/69] fix ancestors_par lifetime relations --- src/node_ref.rs | 2 +- tests/iterator_lifetimes.rs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index ac8994a..8fef7fd 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -686,7 +686,7 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn ancestors_par(&'a self) -> impl ParIter> + fn ancestors_par(&self) -> impl ParIter> where V::Item: Send + Sync, { diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 81ca2c5..22bbf7b 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -24,6 +24,17 @@ where root.ancestors().find(|x| x.data() == predicate) } +fn find_ancestors_par<'a, V: TreeVariant>( + tree: &'a Tree, + predicate: &V::Item, +) -> Option> +where + V::Item: Eq + Sync + Send, +{ + let root = tree.get_root()?; + root.ancestors_par().find(|x| x.data() == predicate) +} + fn find_children<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, @@ -253,6 +264,7 @@ fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); assert_eq!(find_ancestors(&tree, &7), None); + assert_eq!(find_ancestors_par(&tree, &7), None); assert_eq!(find_children(&tree, &7), None); assert_eq!(find_children_par(&tree, &7), None); assert_eq!(find_custom_walk(&tree, &7), None); From a03888395b3e522e371442c604be1cdfb93dba6c Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:29:09 +0100 Subject: [PATCH 28/69] simplify NodeRef::custom_walk lifetimes --- src/node_ref.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 8fef7fd..0f1f6f1 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -856,10 +856,9 @@ where /// let values: Vec<_> = tree.node(id3).custom_walk(next_node).copied().collect(); /// assert_eq!(values, [3, 6, 7, 10, 11]); /// ``` - fn custom_walk<'t, F>(&'t self, next_node: F) -> impl Iterator + 't + fn custom_walk(&self, next_node: F) -> impl Iterator where - F: Fn(Node<'a, V, M, P>) -> Option> + 't, - 'a: 't, + F: Fn(Node<'a, V, M, P>) -> Option>, { let iter_ptr = CustomWalkIterPtr::new(self.col(), Some(self.node_ptr()), next_node); iter_ptr.map(|ptr| { @@ -881,11 +880,10 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn custom_walk_par<'t, F>(&'t self, next_node: F) -> impl ParIter + 't + fn custom_walk_par(&self, next_node: F) -> impl ParIter where - F: Fn(Node<'a, V, M, P>) -> Option> + 't, + F: Fn(Node<'a, V, M, P>) -> Option>, V::Item: Send + Sync, - 'a: 't, { self.custom_walk(next_node) .collect::>() From aa876c90cdd8b541f132e7a51891caca57626dee Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:31:17 +0100 Subject: [PATCH 29/69] simplify NodeRef::walk lifetimes --- src/node_ref.rs | 5 ++--- src/traversal/traverser_core.rs | 8 +++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 0f1f6f1..04ec0d8 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -962,11 +962,10 @@ where /// let post_order: Vec<_> = n2.walk::().copied().collect(); /// assert_eq!(post_order, [8, 4, 5, 2]); /// ``` - fn walk<'t, T>(&'t self) -> impl Iterator + 't + fn walk(&self) -> impl Iterator where - T: Traverser + 't, + T: Traverser, Self: Sized, - 'a: 't, { T::iter_with_owned_storage::(self) } diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 93a89aa..43ce4f7 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -224,15 +224,13 @@ where Self::iter_ptr_with_storage(node_ptr, Self::Storage::default()) } - fn iter_with_owned_storage<'t, 'a, V, M, P>( - node: &'t impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + 't + fn iter_with_owned_storage<'a, V, M, P>( + node: &impl NodeRef<'a, V, M, P>, + ) -> impl Iterator> where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, - 'a: 't, - Self: 't, { Self::iter_with_storage(node, Self::Storage::default()) } From 0fc5dda5b5b24a6e76774567235da5c2f0e32a23 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:31:41 +0100 Subject: [PATCH 30/69] simplify NodeRef::walk_par lifetimes --- src/node_ref.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 04ec0d8..3fe51d1 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -985,12 +985,11 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn walk_par<'t, T>(&'t self) -> impl ParIter + fn walk_par(&self) -> impl ParIter where - T: Traverser + 't, + T: Traverser, Self: Sized, V::Item: Send + Sync, - 'a: 't, { self.walk::().collect::>().into_par() } From fdc6856a0047d144835aa4ed5187d72d9780c075 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:36:49 +0100 Subject: [PATCH 31/69] simplify TraverserCore::iter_with_storage lifetimes --- src/traversal/traverser_core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 43ce4f7..5b5f1eb 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -28,8 +28,8 @@ where where V: TreeVariant + 't; - fn iter_with_storage<'t, 'a, V, M, P>( - node: &'t impl NodeRef<'a, V, M, P>, + fn iter_with_storage<'a, V, M, P>( + node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where From cc37b0e23b0f155abfde64f16dea170d9e6dbc40 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:42:17 +0100 Subject: [PATCH 32/69] define iter_with_owned_storage lifetime independent of the node ref lifetime --- src/node_ref.rs | 4 +++- src/traversal/breadth_first/traverser_core.rs | 4 +++- src/traversal/depth_first/traverser_core.rs | 4 +++- src/traversal/post_order/traverser_core.rs | 4 +++- src/traversal/traverser_core.rs | 10 +++++++--- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 3fe51d1..c67f6cc 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -962,10 +962,12 @@ where /// let post_order: Vec<_> = n2.walk::().copied().collect(); /// assert_eq!(post_order, [8, 4, 5, 2]); /// ``` - fn walk(&self) -> impl Iterator + fn walk<'t, T>(&self) -> impl Iterator where T: Traverser, + T::Storage: 't, Self: Sized, + 'a: 't, { T::iter_with_owned_storage::(self) } diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index edd3c3d..27d91ce 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -39,7 +39,7 @@ impl TraverserCore for Bfs { BfsIterPtr::<_, O::Enumeration, _>::from((storage, node_ptr)) } - fn iter_with_storage<'a, V, M, P>( + fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> @@ -47,6 +47,8 @@ impl TraverserCore for Bfs { V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + Self::Storage: 't, + 'a: 't, { let root = node.node_ptr(); let iter = BfsIterPtr::<_, O::Enumeration, _>::from((storage, root)); diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index 77044e0..eaee8d0 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -39,7 +39,7 @@ impl TraverserCore for Dfs { DfsIterPtr::<_, O::Enumeration, _>::from((storage, node_ptr)) } - fn iter_with_storage<'a, V, M, P>( + fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> @@ -47,6 +47,8 @@ impl TraverserCore for Dfs { V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + Self::Storage: 't, + 'a: 't, { let root = node.node_ptr(); let iter = DfsIterPtr::<_, O::Enumeration, _>::from((storage, root)); diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index 40b6fd7..4123531 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -39,7 +39,7 @@ impl TraverserCore for PostOrder { PostOrderIterPtr::<_, O::Enumeration, _>::from((storage, node_ptr)) } - fn iter_with_storage<'a, V, M, P>( + fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> @@ -47,6 +47,8 @@ impl TraverserCore for PostOrder { V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + Self::Storage: 't, + 'a: 't, { let root = node.node_ptr(); let iter_ptr = PostOrderIterPtr::::from((storage, root)); diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 5b5f1eb..c45b5da 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -28,14 +28,16 @@ where where V: TreeVariant + 't; - fn iter_with_storage<'a, V, M, P>( + fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, storage: impl SoM>, ) -> impl Iterator> where V: TreeVariant + 'a, M: MemoryPolicy, - P: PinnedStorage; + P: PinnedStorage, + Self::Storage: 't, + 'a: 't; /// Returns an iterator which yields all nodes including the `node` and all its descendants; i.e., /// all nodes of the subtree rooted at the given `node`. @@ -224,13 +226,15 @@ where Self::iter_ptr_with_storage(node_ptr, Self::Storage::default()) } - fn iter_with_owned_storage<'a, V, M, P>( + fn iter_with_owned_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + Self::Storage: 't, + 'a: 't, { Self::iter_with_storage(node, Self::Storage::default()) } From 883300a94e6985f49c8c1e980747886c626f47ab Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:44:51 +0100 Subject: [PATCH 33/69] fix lifetime of returned walk iterator --- src/node_ref.rs | 2 +- src/traversal/breadth_first/traverser_core.rs | 4 ++-- src/traversal/depth_first/traverser_core.rs | 4 ++-- src/traversal/post_order/traverser_core.rs | 4 ++-- src/traversal/traverser_core.rs | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index c67f6cc..ae90146 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -962,7 +962,7 @@ where /// let post_order: Vec<_> = n2.walk::().copied().collect(); /// assert_eq!(post_order, [8, 4, 5, 2]); /// ``` - fn walk<'t, T>(&self) -> impl Iterator + fn walk<'t, T>(&self) -> impl Iterator + 't where T: Traverser, T::Storage: 't, diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index 27d91ce..f0ffa56 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -41,8 +41,8 @@ impl TraverserCore for Bfs { fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, - storage: impl SoM>, - ) -> impl Iterator> + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index eaee8d0..ae2728d 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -41,8 +41,8 @@ impl TraverserCore for Dfs { fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, - storage: impl SoM>, - ) -> impl Iterator> + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index 4123531..f4fc15b 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -41,8 +41,8 @@ impl TraverserCore for PostOrder { fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, - storage: impl SoM>, - ) -> impl Iterator> + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index c45b5da..f9dd254 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -30,8 +30,8 @@ where fn iter_with_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, - storage: impl SoM>, - ) -> impl Iterator> + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, @@ -228,7 +228,7 @@ where fn iter_with_owned_storage<'t, 'a, V, M, P>( node: &impl NodeRef<'a, V, M, P>, - ) -> impl Iterator> + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, From e5bf719fe89390482303a0747680fd992a75aa2a Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 11:47:32 +0100 Subject: [PATCH 34/69] fix custom walk lifetimes --- src/node_ref.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index ae90146..7a9de16 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -856,12 +856,13 @@ where /// let values: Vec<_> = tree.node(id3).custom_walk(next_node).copied().collect(); /// assert_eq!(values, [3, 6, 7, 10, 11]); /// ``` - fn custom_walk(&self, next_node: F) -> impl Iterator + fn custom_walk<'t, F>(&self, next_node: F) -> impl Iterator + 't where - F: Fn(Node<'a, V, M, P>) -> Option>, + F: Fn(Node<'a, V, M, P>) -> Option> + 't, + 'a: 't, { let iter_ptr = CustomWalkIterPtr::new(self.col(), Some(self.node_ptr()), next_node); - iter_ptr.map(|ptr| { + iter_ptr.map(move |ptr| { let node = unsafe { &*ptr.ptr() }; node.data() .expect("node is returned by next_node and is active") @@ -880,10 +881,11 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn custom_walk_par(&self, next_node: F) -> impl ParIter + fn custom_walk_par<'t, F>(&self, next_node: F) -> impl ParIter + 't where - F: Fn(Node<'a, V, M, P>) -> Option>, + F: Fn(Node<'a, V, M, P>) -> Option> + 't, V::Item: Send + Sync, + 'a: 't, { self.custom_walk(next_node) .collect::>() From fdfba78c8118813509db53583b4ef9b1b2c030e6 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 12:42:13 +0100 Subject: [PATCH 35/69] revise walk_with lifetime relations with traverser --- src/node_ref.rs | 7 +++++-- src/traversal/breadth_first/traverser_core.rs | 2 +- src/traversal/depth_first/traverser_core.rs | 2 +- src/traversal/post_order/traverser_core.rs | 2 +- src/traversal/traverser_core.rs | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 7a9de16..be8d41e 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -989,11 +989,13 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn walk_par(&self) -> impl ParIter + fn walk_par<'t, T>(&self) -> impl ParIter + 't where T: Traverser, + T::Storage: 't, Self: Sized, V::Item: Send + Sync, + 'a: 't, { self.walk::().collect::>().into_par() } @@ -1141,12 +1143,13 @@ where /// ); /// ``` fn walk_with<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl Iterator> + 't where O: Over, T: Traverser, + T::Storage: 't, Self: Sized, 'a: 't, { diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index f0ffa56..f76fe6d 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -57,7 +57,7 @@ impl TraverserCore for Bfs { fn iter<'t, 'a, V, M, P>( &'t mut self, - node: &'t impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> + 't where V: TreeVariant + 'a, diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index ae2728d..5e853c6 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -57,7 +57,7 @@ impl TraverserCore for Dfs { fn iter<'t, 'a, V, M, P>( &'t mut self, - node: &'t impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> + 't where V: TreeVariant + 'a, diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index f4fc15b..d2bc85c 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -57,7 +57,7 @@ impl TraverserCore for PostOrder { fn iter<'t, 'a, V, M, P>( &'t mut self, - node: &'t impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> + 't where V: TreeVariant + 'a, diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index f9dd254..2dfff97 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -78,7 +78,7 @@ where /// [`OverDepthSiblingIdxNode`]: crate::traversal::OverDepthSiblingIdxNode fn iter<'t, 'a, V, M, P>( &'t mut self, - node: &'t impl NodeRef<'a, V, M, P>, + node: &impl NodeRef<'a, V, M, P>, ) -> impl Iterator> + 't where V: TreeVariant + 'a, From 05557f048f62016e6539e2aeb6f0b7406cbf10a7 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 12:44:58 +0100 Subject: [PATCH 36/69] relax lifetime requirement on NodeRef reference --- src/node_ref.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index be8d41e..35be335 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1169,9 +1169,9 @@ where /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] fn walk_with_par<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, - ) -> impl ParIter> + ) -> impl ParIter> + 't where O: Over, T: Traverser, @@ -1285,9 +1285,7 @@ where /// .unwrap(); /// assert_eq!(max_label_path, vec![9, 6, 3, 1]); /// ``` - fn paths<'t, T>( - &'t self, - ) -> impl Iterator + Clone> + 't + fn paths<'t, T>(&self) -> impl Iterator + Clone> + 't where T: Traverser + 't, ::Storage: 't, @@ -1390,7 +1388,9 @@ where /// assert_eq!(best_path, expected.iter().collect::>()); /// ``` #[cfg(feature = "parallel")] - fn paths_par<'t, T>(&'t self) -> impl ParIter + Clone> + fn paths_par<'t, T>( + &self, + ) -> impl ParIter + Clone> + 't where T: Traverser, V::Item: Send + Sync, From 7b70d21361b6e7d4c7d49681aae636417641646a Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 12:53:05 +0100 Subject: [PATCH 37/69] require tree variants to be Send and Sync --- src/dary/variant.rs | 6 ++++++ src/dyn/variant.rs | 10 ++++++++++ src/node_ref.rs | 16 ++++++++-------- src/tree_variant.rs | 2 +- 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/src/dary/variant.rs b/src/dary/variant.rs index 2d61f5e..68c23cb 100644 --- a/src/dary/variant.rs +++ b/src/dary/variant.rs @@ -8,6 +8,12 @@ pub struct Dary { p: PhantomData, } +/// Tree variants do not hold any data; and hence, safe to sync. +unsafe impl Sync for Dary {} + +/// Tree variants do not hold any data; and hence, safe to sync. +unsafe impl Send for Dary {} + impl Variant for Dary { type Item = T; diff --git a/src/dyn/variant.rs b/src/dyn/variant.rs index e4deb92..2e0b6a9 100644 --- a/src/dyn/variant.rs +++ b/src/dyn/variant.rs @@ -8,6 +8,16 @@ pub struct Dyn { p: PhantomData, } +/// # SAFETY +/// +/// Tree variants do not hold any data, safe to send or sync. +unsafe impl Sync for Dyn {} + +/// # SAFETY +/// +/// Tree variants do not hold any data, safe to send or sync. +unsafe impl Send for Dyn {} + impl Variant for Dyn { type Item = T; diff --git a/src/node_ref.rs b/src/node_ref.rs index 35be335..1d34331 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1499,7 +1499,7 @@ where /// ); /// ``` fn paths_with<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl Iterator::NodeItem<'a, V, M, P>> + Clone> + 't where @@ -1508,6 +1508,7 @@ where 'a: 't, { let node_ptr = self.node_ptr(); + let col = self.col(); T::iter_ptr_with_storage(node_ptr, TraverserCore::storage_mut(traverser)) .filter(|x| { let ptr: &NodePtr = O::Enumeration::node_data(x); @@ -1518,8 +1519,7 @@ where let iter = AncestorsIterPtr::new(node_ptr, *ptr); iter.map(|ptr: NodePtr| { O::Enumeration::from_element_ptr::<'a, V, M, P, O::NodeItem<'a, V, M, P>>( - self.col(), - ptr, + col, ptr, ) }) }) @@ -1612,7 +1612,7 @@ where /// ``` #[cfg(feature = "parallel")] fn paths_with_par<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl ParIter::NodeItem<'a, V, M, P>> + Clone> + 't where @@ -1620,9 +1620,12 @@ where T: Traverser, V::Item: Send + Sync, Self: Sync, + ::MemoryReclaimPolicy: Sync, +

::PinnedVec: Sync, 'a: 't, { let node_ptr = self.node_ptr(); + let col = self.col(); let node_ptrs: alloc::vec::Vec<_> = T::iter_ptr_with_storage(node_ptr, TraverserCore::storage_mut(traverser)) @@ -1631,10 +1634,7 @@ where node_ptrs.into_par().map(move |x| { let iter = AncestorsIterPtr::new(node_ptr, x); iter.map(|ptr: NodePtr| { - O::Enumeration::from_element_ptr::<'a, V, M, P, O::NodeItem<'a, V, M, P>>( - self.col(), - ptr, - ) + O::Enumeration::from_element_ptr::<'a, V, M, P, O::NodeItem<'a, V, M, P>>(col, ptr) }) }) } diff --git a/src/tree_variant.rs b/src/tree_variant.rs index 5ed9e54..e9f275f 100644 --- a/src/tree_variant.rs +++ b/src/tree_variant.rs @@ -7,7 +7,7 @@ use orx_selfref_col::{ /// Variant of a tree. pub trait TreeVariant: - Variant, Prev = RefsSingle, Next = Self::Children> + Variant, Prev = RefsSingle, Next = Self::Children> + Sync { /// Memory reclaimer of the tree. type Reclaimer: MemoryReclaimer; From 09d5e40e7364129e3fdb1f45c6d54c0f2ed314b9 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 12:53:58 +0100 Subject: [PATCH 38/69] require memory reclaimers to implement sync --- src/tree_variant.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tree_variant.rs b/src/tree_variant.rs index e9f275f..59cea4c 100644 --- a/src/tree_variant.rs +++ b/src/tree_variant.rs @@ -10,7 +10,7 @@ pub trait TreeVariant: Variant, Prev = RefsSingle, Next = Self::Children> + Sync { /// Memory reclaimer of the tree. - type Reclaimer: MemoryReclaimer; + type Reclaimer: MemoryReclaimer + Sync; /// Children references of the tree nodes. type Children: RefsChildren + Refs; From b905870fef96074ce19cc09e429ef2a707e2cc23 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 13:26:08 +0100 Subject: [PATCH 39/69] fix NodeRef self referene lifetimes for iterator creating methods --- Cargo.toml | 2 +- src/node_ref.rs | 1 - src/pinned_storage.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a0ef93f..fc89b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ orx-self-or = "1.2.0" serde = { version = "1.0.228", optional = true, default-features = false } orx-pinned-vec = { version = "3.21.0", default-features = false } orx-split-vec = { version = "3.22.0", default-features = false } -orx-selfref-col = { version = "3.0.0", default-features = false } +orx-selfref-col = { path = "../orx-selfref-col", default-features = false } orx-concurrent-iter = { version = "3.3.0", default-features = false } orx-parallel = { version = "3.4.0", default-features = false, optional = true } diff --git a/src/node_ref.rs b/src/node_ref.rs index 1d34331..ec95a45 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1620,7 +1620,6 @@ where T: Traverser, V::Item: Send + Sync, Self: Sync, - ::MemoryReclaimPolicy: Sync,

::PinnedVec: Sync, 'a: 't, { diff --git a/src/pinned_storage.rs b/src/pinned_storage.rs index f5e90e6..7278889 100644 --- a/src/pinned_storage.rs +++ b/src/pinned_storage.rs @@ -2,7 +2,7 @@ use crate::{TreeVariant, aliases::N}; use orx_split_vec::{PinnedVec, Recursive, SplitVec}; /// Trait defining the underlying pinned vector storage of the tree. -pub trait PinnedStorage: 'static { +pub trait PinnedStorage: 'static + Sync { /// The pinned vector for the given variant `V`. type PinnedVec: PinnedVec> where From 5c0417f26109db623c8462941821a6666bf55d78 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 13:27:06 +0100 Subject: [PATCH 40/69] relax NodeRef::clone_as_tree self reference lifetime --- src/node_ref.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index ec95a45..9950137 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1681,7 +1681,7 @@ where /// let bfs: Vec<_> = clone.root().walk::().copied().collect(); /// assert_eq!(bfs, [2, 5, 6, 8, 9, 10]); /// ``` - fn clone_as_tree(&'a self) -> Tree + fn clone_as_tree(&self) -> Tree where V2: TreeVariant + 'a, P::PinnedVec: Default, From 2c51c23558ce86a750d7a18455b9c1ef285b1481 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 13:29:19 +0100 Subject: [PATCH 41/69] break lifetime dependencies to NodeRef, link to tree lifetime instead --- src/node_ref.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 9950137..7453666 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1771,18 +1771,18 @@ where /// .collect(); /// assert_eq!(bfs_leaves, [5, 8, 9, 10, 11]); /// ``` - fn leaves<'t, T>(&'t self) -> impl Iterator + 't + fn leaves<'t, T>(&self) -> impl Iterator + 't where T: Traverser + 't, ::Storage: 't, 'a: 't, { + let col = self.col(); T::iter_ptr_with_owned_storage(self.node_ptr()) .filter(|x: &NodePtr| unsafe { &*x.ptr() }.next().is_empty()) .map(|x: NodePtr| { ::Enumeration::from_element_ptr::<'a, V, M, P, &'a V::Item>( - self.col(), - x, + col, x, ) }) } @@ -1799,7 +1799,7 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn leaves_par<'t, T>(&'t self) -> impl ParIter + 't + fn leaves_par<'t, T>(&self) -> impl ParIter + 't where T: Traverser, V::Item: Send + Sync, @@ -1890,7 +1890,7 @@ where /// assert_eq!(leaf.data(), &8); /// ``` fn leaves_with<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl Iterator> + 't where @@ -1898,16 +1898,14 @@ where T: Traverser, 'a: 't, { + let col = self.col(); T::iter_ptr_with_storage(self.node_ptr(), traverser.storage_mut()) .filter(|x| { let ptr: &NodePtr = O::Enumeration::node_data(x); unsafe { &*ptr.ptr() }.next().is_empty() }) .map(|x| { - O::Enumeration::from_element_ptr::<'a, V, M, P, O::NodeItem<'a, V, M, P>>( - self.col(), - x, - ) + O::Enumeration::from_element_ptr::<'a, V, M, P, O::NodeItem<'a, V, M, P>>(col, x) }) } @@ -1924,7 +1922,7 @@ where /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] fn leaves_with_par<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl ParIter> where @@ -1997,7 +1995,7 @@ where /// assert_eq!(a.node(dfs_indices[2]).data(), &3); /// assert_eq!(a.node(dfs_indices[3]).data(), &7); /// ``` - fn indices<'t, T>(&'t self) -> impl Iterator> + 't + fn indices<'t, T>(&self) -> impl Iterator> + 't where T: Traverser + 't, ::Storage: 't, @@ -2030,7 +2028,7 @@ where /// /// [`indices_with`]: crate::NodeRef::indices_with fn indices_with<'t, T, O>( - &'t self, + &self, traverser: &'t mut T, ) -> impl Iterator::Item>> + 't where From 19f0989e78b2ed358f490df50e61efdd81beafeb Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:47:42 +0100 Subject: [PATCH 42/69] remove lifetime from RefsChildren::ChildrenPtrIter items --- src/iter/children_mut.rs | 4 ++-- src/node_mut.rs | 4 ++-- src/node_ref.rs | 4 ++-- src/traversal/breadth_first/iter_ptr.rs | 2 +- src/traversal/depth_first/iter_ptr.rs | 2 +- src/tree_variant.rs | 12 +++++------- 6 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/iter/children_mut.rs b/src/iter/children_mut.rs index 5e71bd1..298d5ca 100644 --- a/src/iter/children_mut.rs +++ b/src/iter/children_mut.rs @@ -51,7 +51,7 @@ where type Item = NodeMut<'b, V, M, P, NodeMutDown>; fn next(&mut self) -> Option { - self.children_ptr.next().map(|p| self.next_child(*p)) + self.children_ptr.next().map(|p| self.next_child(p)) } fn size_hint(&self) -> (usize, Option) { @@ -79,6 +79,6 @@ where 'a: 'b, { fn next_back(&mut self) -> Option { - self.children_ptr.next_back().map(|p| self.next_child(*p)) + self.children_ptr.next_back().map(|p| self.next_child(p)) } } diff --git a/src/node_mut.rs b/src/node_mut.rs index c8c32af..ce53a80 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -1645,13 +1645,13 @@ where match parent_ptr { None => { - let first_child = self.node().next().children_ptr().next().cloned(); + let first_child = self.node().next().children_ptr().next(); self.col.ends_mut().set(first_child); } Some(parent_ptr) => { let parent = unsafe { &mut *parent_ptr.ptr_mut() }; parent.next_mut().remove_at(sibling_idx); - for child_ptr in self.node().next().children_ptr().rev().cloned() { + for child_ptr in self.node().next().children_ptr().rev() { parent.next_mut().insert(sibling_idx, child_ptr); } } diff --git a/src/node_ref.rs b/src/node_ref.rs index 7453666..72e3366 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -299,7 +299,7 @@ where self.node() .next() .children_ptr() - .map(|ptr| Node::new(self.col(), *ptr)) + .map(|ptr| Node::new(self.col(), ptr)) } /// Creates a **[parallel iterator]** of children nodes of this node. @@ -548,7 +548,7 @@ where .map(|parent| { let ptr = self.node_ptr(); let mut children = parent.next().children_ptr(); - children.position(|x| *x == ptr).expect("this node exists") + children.position(|x| x == ptr).expect("this node exists") }) .unwrap_or(0) } diff --git a/src/traversal/breadth_first/iter_ptr.rs b/src/traversal/breadth_first/iter_ptr.rs index 38e9b0c..64c588e 100644 --- a/src/traversal/breadth_first/iter_ptr.rs +++ b/src/traversal/breadth_first/iter_ptr.rs @@ -72,7 +72,7 @@ where self.stack.get_mut().pop_front().inspect(|element| { let node_ptr = E::node_value(element); let parent = unsafe { &*node_ptr.ptr() }; - let children_ptr = parent.next().children_ptr().cloned(); + let children_ptr = parent.next().children_ptr(); let children = E::children(element, children_ptr); self.stack.get_mut().extend(children); }) diff --git a/src/traversal/depth_first/iter_ptr.rs b/src/traversal/depth_first/iter_ptr.rs index 1cf2d6f..50095f1 100644 --- a/src/traversal/depth_first/iter_ptr.rs +++ b/src/traversal/depth_first/iter_ptr.rs @@ -72,7 +72,7 @@ where self.stack.get_mut().pop().inspect(|element| { let node_ptr = E::node_value(element); let parent = unsafe { &*node_ptr.ptr() }; - let children_ptr = parent.next().children_ptr().cloned(); + let children_ptr = parent.next().children_ptr(); let children = E::children(element, children_ptr).rev(); self.stack.get_mut().extend(children); }) diff --git a/src/tree_variant.rs b/src/tree_variant.rs index 59cea4c..541fc68 100644 --- a/src/tree_variant.rs +++ b/src/tree_variant.rs @@ -19,9 +19,7 @@ pub trait TreeVariant: // children pub trait RefsChildren { - type ChildrenPtrIter<'a>: ExactSizeIterator> - + DoubleEndedIterator - + Default + type ChildrenPtrIter<'a>: ExactSizeIterator> + DoubleEndedIterator + Default where V: 'a, Self: 'a; @@ -50,7 +48,7 @@ pub trait RefsChildren { impl RefsChildren for RefsVec { type ChildrenPtrIter<'a> - = core::slice::Iter<'a, NodePtr> + = core::iter::Copied>> where V: 'a, Self: 'a; @@ -62,7 +60,7 @@ impl RefsChildren for RefsVec { #[inline(always)] fn children_ptr(&self) -> Self::ChildrenPtrIter<'_> { - self.iter() + self.iter().copied() } #[cfg(feature = "parallel")] @@ -101,7 +99,7 @@ impl RefsChildren for RefsVec { impl RefsChildren for RefsArrayLeftMost { type ChildrenPtrIter<'a> - = ArrayLeftMostPtrIter<'a, V> + = core::iter::Copied> where V: 'a, Self: 'a; @@ -113,7 +111,7 @@ impl RefsChildren for RefsArrayLeftMost { #[inline(always)] fn children_ptr(&self) -> Self::ChildrenPtrIter<'_> { - self.iter() + self.iter().copied() } #[cfg(feature = "parallel")] From b758aa344418506c773389defdedd3210bad7abe Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:52:39 +0100 Subject: [PATCH 43/69] simplify parallel children iterator --- src/node_ref.rs | 2 +- src/tree_variant.rs | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 72e3366..46db900 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -381,7 +381,7 @@ where self.node() .next() .children_ptr_par() - .map(|ptr| Node::new(self.col(), *ptr)) + .map(|ptr| Node::new(self.col(), ptr)) } /// Returns the `child-index`-th child of the node; returns None if out of bounds. diff --git a/src/tree_variant.rs b/src/tree_variant.rs index 541fc68..570cc00 100644 --- a/src/tree_variant.rs +++ b/src/tree_variant.rs @@ -26,12 +26,11 @@ pub trait RefsChildren { fn num_children(&self) -> usize; - fn children_ptr(&self) -> Self::ChildrenPtrIter<'_>; + fn children_ptr<'a>(&'a self) -> Self::ChildrenPtrIter<'a>; #[cfg(feature = "parallel")] - fn children_ptr_par<'a>(&'a self) -> impl ParIter> + fn children_ptr_par(&self) -> impl ParIter> where - V: 'a, V::Item: Send + Sync; fn get_ptr(&self, i: usize) -> Option>; @@ -59,17 +58,16 @@ impl RefsChildren for RefsVec { } #[inline(always)] - fn children_ptr(&self) -> Self::ChildrenPtrIter<'_> { + fn children_ptr<'a>(&'a self) -> Self::ChildrenPtrIter<'a> { self.iter().copied() } #[cfg(feature = "parallel")] - fn children_ptr_par<'a>(&'a self) -> impl ParIter> + fn children_ptr_par(&self) -> impl ParIter> where - V: 'a, V::Item: Send + Sync, { - self.as_slice().par() + self.as_slice().par().copied() } #[inline(always)] @@ -110,20 +108,22 @@ impl RefsChildren for RefsArrayLeftMost { } #[inline(always)] - fn children_ptr(&self) -> Self::ChildrenPtrIter<'_> { + fn children_ptr<'a>(&'a self) -> Self::ChildrenPtrIter<'a> { self.iter().copied() } #[cfg(feature = "parallel")] - fn children_ptr_par<'a>(&'a self) -> impl ParIter> + fn children_ptr_par(&self) -> impl ParIter> where - V: 'a, V::Item: Send + Sync, { - self.as_slice().par().map(|x| { - x.as_ref() - .expect("all elements of RefsArrayLeftMost::as_slice are of Some variant") - }) + self.as_slice() + .par() + .map(|x| { + x.as_ref() + .expect("all elements of RefsArrayLeftMost::as_slice are of Some variant") + }) + .copied() } #[inline(always)] From 05c53fdd8c8713f79627e62f8ecfa675b651c3e9 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:54:55 +0100 Subject: [PATCH 44/69] fix children iterator's lifetime --- src/node_ref.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 46db900..db325a0 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -295,11 +295,15 @@ where /// /// assert_eq!(data, ['a', 'c', 'd', 'e', 'b']); /// ``` - fn children(&self) -> impl ExactSizeIterator> { + fn children<'t>(&self) -> impl ExactSizeIterator> + 't + where + 'a: 't, + { + let col = self.col(); self.node() .next() .children_ptr() - .map(|ptr| Node::new(self.col(), ptr)) + .map(move |ptr| Node::new(col, ptr)) } /// Creates a **[parallel iterator]** of children nodes of this node. From 4a4744e88b231d4cf5db930b2d481587aa29c106 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:56:52 +0100 Subject: [PATCH 45/69] fix children_par lifetime --- src/node_ref.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index db325a0..6223efc 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -377,15 +377,17 @@ where /// assert_eq!(seq_value, par_value_4t); /// ``` #[cfg(feature = "parallel")] - fn children_par(&self) -> impl ParIter> + fn children_par<'t>(&self) -> impl ParIter> + 't where V::Item: Send + Sync, - Self: Sync, +

::PinnedVec: Sync, + 'a: 't, { + let col = self.col(); self.node() .next() .children_ptr_par() - .map(|ptr| Node::new(self.col(), ptr)) + .map(move |ptr| Node::new(col, ptr)) } /// Returns the `child-index`-th child of the node; returns None if out of bounds. From 6ff140346d63b2b6083658c2da28201972c48b44 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:57:38 +0100 Subject: [PATCH 46/69] fix NodeRef::ancestors lifetime --- src/node_ref.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 6223efc..1485d0e 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -669,11 +669,15 @@ where /// let ancestors_data: Vec<_> = n4.ancestors().map(|x| *x.data()).collect(); /// assert_eq!(ancestors_data, [2, 1]); /// ``` - fn ancestors(&self) -> impl Iterator> { + fn ancestors<'t>(&self) -> impl Iterator> + 't + where + 'a: 't, + { let root_ptr = self.col().ends().get().expect("Tree is non-empty"); + let col = self.col(); AncestorsIterPtr::new(root_ptr, self.node_ptr()) .skip(1) - .map(|ptr| Node::new(self.col(), ptr)) + .map(|ptr| Node::new(col, ptr)) } /// Creates a **[parallel iterator]** starting from this node moving upwards until the root: From b91db7540daee28fb3d3d77a2f46cbcb3715cd16 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 14:57:58 +0100 Subject: [PATCH 47/69] fix ancestors_par lifetime --- src/node_ref.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index 1485d0e..a4e60d3 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -696,9 +696,10 @@ where /// [`num_threads`]: orx_parallel::ParIter::num_threads /// [`chunk_size`]: orx_parallel::ParIter::chunk_size #[cfg(feature = "parallel")] - fn ancestors_par(&self) -> impl ParIter> + fn ancestors_par<'t>(&self) -> impl ParIter> + 't where V::Item: Send + Sync, + 'a: 't, { self.ancestors().collect::>().into_par() } From 390c5e46a6df64aa8e9906fbc2e2ebc8113fe547 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 15:01:38 +0100 Subject: [PATCH 48/69] create find_custom_walk_mut lifetime test --- tests/iterator_lifetimes.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 22bbf7b..67faf93 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -248,6 +248,19 @@ where // mut +fn find_custom_walk_mut<'a, V: TreeVariant>( + tree: &'a mut Tree, + predicate: &V::Item, +) -> Option<&'a mut V::Item> +where + V::Item: Eq + Sync + Send, +{ + let custom_walk = |node: Node<'a, V>| node.get_child(0); + let mut root = tree.get_root_mut()?; + let mut walker = root.custom_walk_mut(custom_walk); + walker.find(|v| v == &predicate) +} + fn find_leaves_mut<'a, V: TreeVariant>( tree: &'a mut Tree, predicate: &V::Item, @@ -284,5 +297,6 @@ fn node_ref_lifetime_tests() { assert_eq!(find_indices(&tree, &7), None); assert_eq!(find_indices_with(&tree, &7), None); + assert_eq!(find_custom_walk_mut(&mut tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); } From 1622a5c6ec79907fe2298af5d0dfc3d957bd45ca Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 15:23:59 +0100 Subject: [PATCH 49/69] correct walk_mut lifetime relations --- src/node_mut.rs | 17 ++++++++++------ src/traversal/breadth_first/traverser_core.rs | 10 ++++++---- src/traversal/depth_first/traverser_core.rs | 10 ++++++---- src/traversal/post_order/traverser_core.rs | 10 ++++++---- src/traversal/traverser_core.rs | 20 +++++++++++-------- tests/iterator_lifetimes.rs | 13 ++++++++++++ 6 files changed, 54 insertions(+), 26 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index ce53a80..874a1d6 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -1769,9 +1769,13 @@ where /// assert_eq!(all_values, [101, 202, 303, 4, 5, 406, 507]); /// ``` #[allow(clippy::missing_panics_doc)] - pub fn custom_walk_mut(&mut self, next_node: F) -> impl Iterator + pub fn custom_walk_mut<'t, F>( + &mut self, + next_node: F, + ) -> impl Iterator + 't where - F: Fn(Node<'a, V, M, P>) -> Option>, + F: Fn(Node<'a, V, M, P>) -> Option> + 't, + 'a: 't, { let iter_ptr = CustomWalkIterPtr::new(self.col(), Some(self.node_ptr()), next_node); iter_ptr.map(|ptr| { @@ -2048,9 +2052,8 @@ where /// ``` pub fn children_mut( &mut self, - ) -> impl ExactSizeIterator> - + DoubleEndedIterator - + use<'_, 'a, V, M, P, MO> { + ) -> impl ExactSizeIterator> + DoubleEndedIterator + { ChildrenMutIter::new(self.col, unsafe { self.node_ptr.ptr() }) } @@ -2127,9 +2130,11 @@ where /// assert_eq!(post_order.next(), Some(&mut 4)); // ... /// } /// ``` - pub fn walk_mut(&'a mut self) -> impl Iterator + pub fn walk_mut<'t, T>(&'t mut self) -> impl Iterator + 't where T: Traverser, + T::Storage: 't, + 'a: 't, { T::iter_mut_with_owned_storage::(self) } diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index f76fe6d..6533aaa 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -99,16 +99,18 @@ impl TraverserCore for Bfs { Self::into_iter_with_storage(node_mut, queue) } - fn iter_mut_with_storage<'a, V, M, P, MO>( - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - storage: impl SoM>, - ) -> impl Iterator> + fn iter_mut_with_storage<'t, 'a, V, M, P, MO>( + node_mut: &mut NodeMut<'a, V, M, P, MO>, + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + Self::Storage: 't, + 'a: 't, { let root = node_mut.node_ptr(); let iter_ptr = BfsIterPtr::::from((storage, root)); diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index 5e853c6..bb6cd84 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -99,16 +99,18 @@ impl TraverserCore for Dfs { Self::into_iter_with_storage(node_mut, stack) } - fn iter_mut_with_storage<'a, V, M, P, MO>( - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - storage: impl SoM>, - ) -> impl Iterator> + fn iter_mut_with_storage<'t, 'a, V, M, P, MO>( + node_mut: &mut NodeMut<'a, V, M, P, MO>, + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + Self::Storage: 't, + 'a: 't, { let root = node_mut.node_ptr(); let iter_ptr = DfsIterPtr::::from((storage, root)); diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index d2bc85c..81a1a73 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -99,16 +99,18 @@ impl TraverserCore for PostOrder { Self::into_iter_with_storage(node_mut, states) } - fn iter_mut_with_storage<'a, V, M, P, MO>( - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - storage: impl SoM>, - ) -> impl Iterator> + fn iter_mut_with_storage<'t, 'a, V, M, P, MO>( + node_mut: &mut NodeMut<'a, V, M, P, MO>, + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + Self::Storage: 't, + 'a: 't, { let root = node_mut.node_ptr(); let iter_ptr = PostOrderIterPtr::::from((storage, root)); diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 2dfff97..e8564e4 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -86,16 +86,18 @@ where P: PinnedStorage, 'a: 't; - fn iter_mut_with_storage<'a, V, M, P, MO>( - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - storage: impl SoM>, - ) -> impl Iterator> + fn iter_mut_with_storage<'t, 'a, V, M, P, MO>( + node_mut: &mut NodeMut<'a, V, M, P, MO>, + storage: impl SoM> + 't, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, - O: OverMut; + O: OverMut, + Self::Storage: 't, + 'a: 't; /// Returns a mutable iterator which yields all nodes including the `node` and all its descendants; i.e., /// all nodes of the subtree rooted at the given `node`. @@ -239,15 +241,17 @@ where Self::iter_with_storage(node, Self::Storage::default()) } - fn iter_mut_with_owned_storage<'a, V, M, P, MO>( - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - ) -> impl Iterator> + fn iter_mut_with_owned_storage<'t, 'a, V, M, P, MO>( + node_mut: &mut NodeMut<'a, V, M, P, MO>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, + Self::Storage: 't, MO: NodeMutOrientation, O: OverMut, + 'a: 't, { Self::iter_mut_with_storage(node_mut, Self::Storage::default()) } diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 67faf93..ff7a7ea 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -261,6 +261,18 @@ where walker.find(|v| v == &predicate) } +fn find_walk_mut<'a, V: TreeVariant>( + tree: &'a mut Tree, + predicate: &V::Item, +) -> Option<&'a mut V::Item> +where + V::Item: Eq + Sync + Send, +{ + let mut root = tree.get_root_mut()?; + let mut walker = root.walk_mut::(); + walker.find(|v| v == &predicate) +} + fn find_leaves_mut<'a, V: TreeVariant>( tree: &'a mut Tree, predicate: &V::Item, @@ -298,5 +310,6 @@ fn node_ref_lifetime_tests() { assert_eq!(find_indices_with(&tree, &7), None); assert_eq!(find_custom_walk_mut(&mut tree, &7), None); + assert_eq!(find_walk_mut(&mut tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); } From 738253f548f9768c8c07ec80d689bbf5f45ae705 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:41:51 +0100 Subject: [PATCH 50/69] revise NodeMut self lifetimes --- src/node_mut.rs | 60 ++++++++++++++----- src/traversal/breadth_first/traverser_core.rs | 11 ++-- src/traversal/depth_first/traverser_core.rs | 11 ++-- src/traversal/post_order/traverser_core.rs | 11 ++-- src/traversal/traverser_core.rs | 11 ++-- tests/iterator_lifetimes.rs | 14 +++++ 6 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index 874a1d6..0b8265b 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -1770,7 +1770,7 @@ where /// ``` #[allow(clippy::missing_panics_doc)] pub fn custom_walk_mut<'t, F>( - &mut self, + &'t mut self, next_node: F, ) -> impl Iterator + 't where @@ -2130,7 +2130,7 @@ where /// assert_eq!(post_order.next(), Some(&mut 4)); // ... /// } /// ``` - pub fn walk_mut<'t, T>(&'t mut self) -> impl Iterator + 't + pub fn walk_mut<'t, T>(&mut self) -> impl Iterator + 't where T: Traverser, T::Storage: 't, @@ -2277,13 +2277,14 @@ where /// ] /// ); /// ``` - pub fn walk_mut_with( - &'a mut self, - traverser: &'a mut T, - ) -> impl Iterator> + pub fn walk_mut_with<'t, T, O>( + &mut self, + traverser: &'t mut T, + ) -> impl Iterator> + 't where O: OverMut, T: Traverser, + 'a: 't, { traverser.iter_mut(self) } @@ -2527,13 +2528,14 @@ where /// ] /// ); /// ``` - pub fn into_walk_with( + pub fn into_walk_with<'t, T, O>( self, - traverser: &'a mut T, - ) -> impl Iterator> + traverser: &'t mut T, + ) -> impl Iterator> + 't where O: OverMut, T: Traverser, + 'a: 't, { traverser.into_iter(self) } @@ -2741,14 +2743,17 @@ where /// [(2, &205), (3, &308), (3, &309), (3, &310), (3, &311)] /// ); /// ``` - pub fn leaves_mut_with( - &'a mut self, - traverser: &'a mut T, - ) -> impl Iterator> + pub fn leaves_mut_with<'t, T, O>( + &mut self, + traverser: &'t mut T, + ) -> impl Iterator> + 't where O: OverMut, T: Traverser, + >::Storage: 't, + 'a: 't, { + let col = self.col(); T::iter_ptr_with_storage(self.node_ptr(), traverser.storage_mut()) .filter(|x| { let ptr: &NodePtr = O::Enumeration::node_data(x); @@ -2756,8 +2761,7 @@ where }) .map(|x| { O::Enumeration::from_element_ptr_mut::<'a, V, M, P, O::NodeItemMut<'a, V, M, P>>( - self.col(), - x, + col, x, ) }) } @@ -3591,3 +3595,29 @@ where self.node().prev().get().map(|p| NodeMut::new(self.col, p)) } } + +#[test] +fn abc() { + use crate::*; + + let mut tree = DynTree::new(1); + let [id2, id3] = tree.root_mut().push_children([2, 3]); + let [id4, _] = tree.node_mut(id2).push_children([4, 5]); + tree.node_mut(id4).push_child(8); + let [id6, id7] = tree.node_mut(id3).push_children([6, 7]); + tree.node_mut(id6).push_child(9); + tree.node_mut(id7).push_children([10, 11]); + + // let's remove children of node 3 + let mut n3 = tree.node_mut(id3); + n3.remove_children(); + n3.push_children([6, 7]); + let n6 = n3.walk_mut::().next().unwrap(); + for x in n3.children_mut() { + x.prune(); + } + // *n6.data_mut() = 12; + + let bfs: Vec<_> = tree.root().walk::().copied().collect(); + assert_eq!(bfs, [1, 2, 3, 4, 5, 8]); +} diff --git a/src/traversal/breadth_first/traverser_core.rs b/src/traversal/breadth_first/traverser_core.rs index 6533aaa..588f087 100644 --- a/src/traversal/breadth_first/traverser_core.rs +++ b/src/traversal/breadth_first/traverser_core.rs @@ -69,19 +69,20 @@ impl TraverserCore for Bfs { Self::iter_with_storage(node, queue) } - fn iter_mut<'a, V, M, P, MO>( - &'a mut self, - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - ) -> impl Iterator> + fn iter_mut<'t, 'a, V, M, P, MO>( + &'t mut self, + node: &mut NodeMut<'a, V, M, P, MO>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + 'a: 't, { let queue = self.queue.for_variant::(); - Self::iter_mut_with_storage(node_mut, queue) + Self::iter_mut_with_storage(node, queue) } fn into_iter<'a, V, M, P, MO>( diff --git a/src/traversal/depth_first/traverser_core.rs b/src/traversal/depth_first/traverser_core.rs index bb6cd84..46a6be5 100644 --- a/src/traversal/depth_first/traverser_core.rs +++ b/src/traversal/depth_first/traverser_core.rs @@ -69,19 +69,20 @@ impl TraverserCore for Dfs { Self::iter_with_storage(node, stack) } - fn iter_mut<'a, V, M, P, MO>( - &'a mut self, - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - ) -> impl Iterator> + fn iter_mut<'t, 'a, V, M, P, MO>( + &'t mut self, + node: &mut NodeMut<'a, V, M, P, MO>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + 'a: 't, { let stack = self.stack.for_variant::(); - Self::iter_mut_with_storage(node_mut, stack) + Self::iter_mut_with_storage(node, stack) } fn into_iter<'a, V, M, P, MO>( diff --git a/src/traversal/post_order/traverser_core.rs b/src/traversal/post_order/traverser_core.rs index 81a1a73..fde3d49 100644 --- a/src/traversal/post_order/traverser_core.rs +++ b/src/traversal/post_order/traverser_core.rs @@ -69,19 +69,20 @@ impl TraverserCore for PostOrder { Self::iter_with_storage(node, states) } - fn iter_mut<'a, V, M, P, MO>( - &'a mut self, - node_mut: &'a mut NodeMut<'a, V, M, P, MO>, - ) -> impl Iterator> + fn iter_mut<'t, 'a, V, M, P, MO>( + &'t mut self, + node: &mut NodeMut<'a, V, M, P, MO>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, O: OverMut, + 'a: 't, { let states = self.states.for_variant::(); - Self::iter_mut_with_storage(node_mut, states) + Self::iter_mut_with_storage(node, states) } fn into_iter<'a, V, M, P, MO>( diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index e8564e4..2f19abc 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -129,16 +129,17 @@ where /// [`OverDepthData`]: crate::traversal::OverDepthData /// [`OverSiblingIdxData`]: crate::traversal::OverSiblingIdxData /// [`OverDepthSiblingIdxData`]: crate::traversal::OverDepthSiblingIdxData - fn iter_mut<'a, V, M, P, MO>( - &'a mut self, - node: &'a mut NodeMut<'a, V, M, P, MO>, - ) -> impl Iterator> + fn iter_mut<'t, 'a, V, M, P, MO>( + &'t mut self, + node: &mut NodeMut<'a, V, M, P, MO>, + ) -> impl Iterator> + 't where V: TreeVariant + 'a, M: MemoryPolicy, P: PinnedStorage, MO: NodeMutOrientation, - O: OverMut; + O: OverMut, + 'a: 't; fn into_iter_with_storage<'a, V, M, P, MO>( node_mut: NodeMut<'a, V, M, P, MO>, diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index ff7a7ea..28dee7c 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -284,6 +284,19 @@ where root.leaves_mut::().find(|v| v == &predicate) } +fn find_leaves_mut_with<'a, V: TreeVariant>( + tree: &'a mut Tree, + predicate: &V::Item, +) -> Option<&'a mut V::Item> +where + V::Item: Eq + Sync + Send, +{ + let mut traverser = Dfs::::new(); + let mut root = tree.get_root_mut()?; + root.leaves_mut_with(&mut traverser) + .find(|v| v == &predicate) +} + #[test] fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); @@ -312,4 +325,5 @@ fn node_ref_lifetime_tests() { assert_eq!(find_custom_walk_mut(&mut tree, &7), None); assert_eq!(find_walk_mut(&mut tree, &7), None); assert_eq!(find_leaves_mut(&mut tree, &7), None); + assert_eq!(find_leaves_mut_with(&mut tree, &7), None); } From 25f476d5cf8df62c4d355a875efb84ca3e2f096a Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:42:19 +0100 Subject: [PATCH 51/69] fix leaves_mut lifetime --- src/node_mut.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index 0b8265b..1958f0e 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -2605,12 +2605,13 @@ where /// let leaves: Vec<_> = n3.leaves::().copied().collect(); /// assert_eq!(leaves, [209, 210, 211]); /// ``` - pub fn leaves_mut<'t, T>(&'t mut self) -> impl Iterator + 't + pub fn leaves_mut<'t, T>(&mut self) -> impl Iterator + 't where T: Traverser + 't, ::Storage: 't, 'a: 't, { + let col = self.col(); T::iter_ptr_with_owned_storage(self.node_ptr()) .filter(|x: &NodePtr| unsafe { &*x.ptr() }.next().is_empty()) .map(|x: NodePtr| { @@ -2620,7 +2621,7 @@ where M, P, &'a mut V::Item, - >(self.col(), x) + >(col, x) }) } From cdcd23c6e7fae5a4a5c846d09ff8b0f7b6dab1d2 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:43:05 +0100 Subject: [PATCH 52/69] fix custom_walk_mut self lifetime --- src/node_mut.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index 1958f0e..01e4966 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -1770,7 +1770,7 @@ where /// ``` #[allow(clippy::missing_panics_doc)] pub fn custom_walk_mut<'t, F>( - &'t mut self, + &mut self, next_node: F, ) -> impl Iterator + 't where From 2416e397a4d83d47ae42f8d753e2f0b3bb97ad25 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:44:55 +0100 Subject: [PATCH 53/69] clean up --- src/node_mut.rs | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index 01e4966..7f21192 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -2944,13 +2944,14 @@ where /// /// assert!(tree.is_empty()); /// ``` - pub fn into_leaves_with( + pub fn into_leaves_with<'t, T, O>( self, - traverser: &'a mut T, - ) -> impl Iterator> + traverser: &'t mut T, + ) -> impl Iterator> + 't where O: OverMut, T: Traverser, + 'a: 't, { T::into_iter_with_storage_filtered(self, traverser.storage_mut(), |x| { let ptr = ::node_data(x); @@ -3596,29 +3597,3 @@ where self.node().prev().get().map(|p| NodeMut::new(self.col, p)) } } - -#[test] -fn abc() { - use crate::*; - - let mut tree = DynTree::new(1); - let [id2, id3] = tree.root_mut().push_children([2, 3]); - let [id4, _] = tree.node_mut(id2).push_children([4, 5]); - tree.node_mut(id4).push_child(8); - let [id6, id7] = tree.node_mut(id3).push_children([6, 7]); - tree.node_mut(id6).push_child(9); - tree.node_mut(id7).push_children([10, 11]); - - // let's remove children of node 3 - let mut n3 = tree.node_mut(id3); - n3.remove_children(); - n3.push_children([6, 7]); - let n6 = n3.walk_mut::().next().unwrap(); - for x in n3.children_mut() { - x.prune(); - } - // *n6.data_mut() = 12; - - let bfs: Vec<_> = tree.root().walk::().copied().collect(); - assert_eq!(bfs, [1, 2, 3, 4, 5, 8]); -} From a4b945245bfed5fb2268eb628c4f6923e6e1a56e Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:51:15 +0100 Subject: [PATCH 54/69] update selfref-col dependency to the develop branch --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index fc89b07..d41e7d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ orx-self-or = "1.2.0" serde = { version = "1.0.228", optional = true, default-features = false } orx-pinned-vec = { version = "3.21.0", default-features = false } orx-split-vec = { version = "3.22.0", default-features = false } -orx-selfref-col = { path = "../orx-selfref-col", default-features = false } +orx-selfref-col = { git = "https://github.com/orxfun/orx-selfref-col.git", branch = "require-sync-for-symbolic-types", default-features = false } orx-concurrent-iter = { version = "3.3.0", default-features = false } orx-parallel = { version = "3.4.0", default-features = false, optional = true } From 73ab996a5f0506430dd479ab06adbcfb77a03b62 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:53:48 +0100 Subject: [PATCH 55/69] update test documentation --- tests/iterator_lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 28dee7c..195956f 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -13,7 +13,7 @@ The methods must NOT fail to compile due to the following errors: * referencing local variable `traverser`, or * referencing local variable `root`. -These are temporary references. The output's lifetime must not depend on these temporary values. +These are temporary references, instead the output's lifetime must depend on the tree. */ fn find_ancestors<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> From 7f5b42f125f9ec0b979522b303152309aa65c03f Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 18:58:54 +0100 Subject: [PATCH 56/69] fix node_ref_lifetime_tests for no default fetaures case --- tests/iterator_lifetimes.rs | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 195956f..5e25488 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -24,6 +24,7 @@ where root.ancestors().find(|x| x.data() == predicate) } +#[cfg(feature = "parallel")] fn find_ancestors_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -43,6 +44,7 @@ where root.children().find(|x| x.data() == predicate) } +#[cfg(feature = "parallel")] fn find_children_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -67,6 +69,7 @@ where walker.find(|v| v == &predicate) } +#[cfg(feature = "parallel")] fn find_custom_walk_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -89,6 +92,7 @@ where walker.find(|v| v == &predicate) } +#[cfg(feature = "parallel")] fn find_walk_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq + Sync + Send, @@ -108,6 +112,7 @@ where walker.find(|v| v.data() == predicate) } +#[cfg(feature = "parallel")] fn find_walk_with_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -150,6 +155,7 @@ where .and_then(|mut x| x.next()) } +#[cfg(feature = "parallel")] fn find_paths_with_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -169,6 +175,7 @@ where .and_then(|mut x| x.next()) } +#[cfg(feature = "parallel")] fn find_paths_par<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option<&'a V::Item> where V::Item: Eq + Sync + Send, @@ -187,6 +194,7 @@ where root.leaves::().find(|v| v == &predicate) } +#[cfg(feature = "parallel")] fn find_leaves_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -211,6 +219,7 @@ where .find(|v| v.data() == predicate) } +#[cfg(feature = "parallel")] fn find_leaves_with_par<'a, V: TreeVariant>( tree: &'a Tree, predicate: &V::Item, @@ -302,25 +311,28 @@ fn node_ref_lifetime_tests() { let mut tree = DynTree::new(42); assert_eq!(find_ancestors(&tree, &7), None); - assert_eq!(find_ancestors_par(&tree, &7), None); assert_eq!(find_children(&tree, &7), None); - assert_eq!(find_children_par(&tree, &7), None); assert_eq!(find_custom_walk(&tree, &7), None); - assert_eq!(find_custom_walk_par(&tree, &7), None); assert_eq!(find_walk(&tree, &7), None); - assert_eq!(find_walk_par(&tree, &7), None); assert_eq!(find_walk_with(&tree, &7), None); - assert_eq!(find_walk_with_par(&tree, &7), None); assert_eq!(find_paths(&tree, &7), None); - assert_eq!(find_paths_par(&tree, &7), None); assert_eq!(find_paths_with(&tree, &7), None); - assert_eq!(find_paths_with_par(&tree, &7), None); assert_eq!(find_leaves(&tree, &7), None); - assert_eq!(find_leaves_par(&tree, &7), None); assert_eq!(find_leaves_with(&tree, &7), None); - assert_eq!(find_leaves_with_par(&tree, &7), None); assert_eq!(find_indices(&tree, &7), None); assert_eq!(find_indices_with(&tree, &7), None); + #[cfg(feature = "parallel")] + { + assert_eq!(find_ancestors_par(&tree, &7), None); + assert_eq!(find_children_par(&tree, &7), None); + assert_eq!(find_custom_walk_par(&tree, &7), None); + assert_eq!(find_walk_par(&tree, &7), None); + assert_eq!(find_walk_with_par(&tree, &7), None); + assert_eq!(find_paths_par(&tree, &7), None); + assert_eq!(find_paths_with_par(&tree, &7), None); + assert_eq!(find_leaves_par(&tree, &7), None); + assert_eq!(find_leaves_with_par(&tree, &7), None); + } assert_eq!(find_custom_walk_mut(&mut tree, &7), None); assert_eq!(find_walk_mut(&mut tree, &7), None); From b705aabce2fb458d262be62760259a138b3825d9 Mon Sep 17 00:00:00 2001 From: orxfun Date: Fri, 5 Dec 2025 19:02:54 +0100 Subject: [PATCH 57/69] clippy fixes --- tests/iterator_lifetimes.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 5e25488..80fb2cf 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -233,7 +233,7 @@ where .find(|v| v.data() == predicate) } -fn find_indices<'a, V: TreeVariant>(tree: &'a Tree, predicate: &V::Item) -> Option> +fn find_indices(tree: &Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, { @@ -242,10 +242,7 @@ where .find(|v| tree.node(*v).data() == predicate) } -fn find_indices_with<'a, V: TreeVariant>( - tree: &'a Tree, - predicate: &V::Item, -) -> Option> +fn find_indices_with(tree: &Tree, predicate: &V::Item) -> Option> where V::Item: Eq + Sync + Send, { From cdadb43410985d830936bddc8eb6250311b718c7 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 19:08:03 +0100 Subject: [PATCH 58/69] revision --- src/dary/variant.rs | 4 ++++ tests/iterator_lifetimes.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/dary/variant.rs b/src/dary/variant.rs index 68c23cb..4a42049 100644 --- a/src/dary/variant.rs +++ b/src/dary/variant.rs @@ -8,9 +8,13 @@ pub struct Dary { p: PhantomData, } +/// # SAFETY +/// /// Tree variants do not hold any data; and hence, safe to sync. unsafe impl Sync for Dary {} +/// # SAFETY +/// /// Tree variants do not hold any data; and hence, safe to sync. unsafe impl Send for Dary {} diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 80fb2cf..259c180 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -2,7 +2,7 @@ use orx_tree::traversal::*; use orx_tree::*; /* -These tests are created wrt the issue: https://github.com/orxfun/orx-tree/issues/188. +These tests are created with respect to the issue: https://github.com/orxfun/orx-tree/issues/188. They are expected to compile. From abfa8b4f0e6fe0679a4c5295cf8e9b01c0ec2d63 Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:08:50 +0100 Subject: [PATCH 59/69] Update tests/iterator_lifetimes.rs Co-authored-by: hasezoey --- tests/iterator_lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 259c180..93d661d 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -132,7 +132,7 @@ where { let root = tree.get_root()?; root.paths::() - .find(|x| x.clone().collect::>().contains(&predicate)) + .find(|x| x.clone().any(|x| x == predicate)) .and_then(|mut x| x.next()) } From fd1607c218f62003ac35053daa9306fac37e4b26 Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:09:08 +0100 Subject: [PATCH 60/69] Update tests/iterator_lifetimes.rs Co-authored-by: hasezoey --- tests/iterator_lifetimes.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 93d661d..a076bc4 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -147,10 +147,7 @@ where let root = tree.get_root()?; root.paths_with(&mut traverser) .find(|x| { - x.clone() - .map(|x| x.data()) - .collect::>() - .contains(&predicate) + x.clone().map(|x| x.data()).any(|x| x == predicate) }) .and_then(|mut x| x.next()) } From 252fa79a8f697f325a02ed4512a01ac856386cb8 Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:09:34 +0100 Subject: [PATCH 61/69] Update tests/iterator_lifetimes.rs Co-authored-by: hasezoey --- tests/iterator_lifetimes.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index a076bc4..2b42b8d 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -164,10 +164,7 @@ where let root = tree.get_root()?; root.paths_with_par(&mut traverser) .find(|x| { - x.clone() - .map(|x| x.data()) - .collect::>() - .contains(&predicate) + x.clone().map(|x| x.data()).any(|x| x == predicate) }) .and_then(|mut x| x.next()) } From 24f91435eed83ce8347da9a3ca8254752542fcac Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:09:49 +0100 Subject: [PATCH 62/69] Update tests/iterator_lifetimes.rs Co-authored-by: hasezoey --- tests/iterator_lifetimes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/iterator_lifetimes.rs b/tests/iterator_lifetimes.rs index 2b42b8d..4c04e0f 100644 --- a/tests/iterator_lifetimes.rs +++ b/tests/iterator_lifetimes.rs @@ -176,7 +176,7 @@ where { let root = tree.get_root()?; root.paths_par::() - .find(|x| x.clone().collect::>().contains(&predicate)) + .find(|x| x.clone().any(|x| x == predicate)) .and_then(|mut x| x.next()) } From d952f215f0f253db1308fa40a84924f63a3447cf Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:11:54 +0100 Subject: [PATCH 63/69] Update src/traversal/traverser_core.rs Co-authored-by: hasezoey --- src/traversal/traverser_core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 2f19abc..29e9e0a 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -87,7 +87,7 @@ where 'a: 't; fn iter_mut_with_storage<'t, 'a, V, M, P, MO>( - node_mut: &mut NodeMut<'a, V, M, P, MO>, + node: &mut NodeMut<'a, V, M, P, MO>, storage: impl SoM> + 't, ) -> impl Iterator> + 't where From 7f54c0daafd844796763ee40323b69f326119db2 Mon Sep 17 00:00:00 2001 From: Ugur Arikan Date: Sat, 6 Dec 2025 19:12:06 +0100 Subject: [PATCH 64/69] Update src/traversal/traverser_core.rs Co-authored-by: hasezoey --- src/traversal/traverser_core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 29e9e0a..9abf2d9 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -243,7 +243,7 @@ where } fn iter_mut_with_owned_storage<'t, 'a, V, M, P, MO>( - node_mut: &mut NodeMut<'a, V, M, P, MO>, + node: &mut NodeMut<'a, V, M, P, MO>, ) -> impl Iterator> + 't where V: TreeVariant + 'a, From 1788ae4b1d748c11e256913ca985e408d7c0bdbb Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 19:14:33 +0100 Subject: [PATCH 65/69] remove inherited lifetime constraint --- src/node_mut.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index 7f21192..ed14132 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -2608,7 +2608,6 @@ where pub fn leaves_mut<'t, T>(&mut self) -> impl Iterator + 't where T: Traverser + 't, - ::Storage: 't, 'a: 't, { let col = self.col(); @@ -2751,7 +2750,6 @@ where where O: OverMut, T: Traverser, - >::Storage: 't, 'a: 't, { let col = self.col(); From fb7154075775bf8d22ec5177e1651874d780dff0 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 19:15:30 +0100 Subject: [PATCH 66/69] consistent argument naming --- src/traversal/traverser_core.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/traversal/traverser_core.rs b/src/traversal/traverser_core.rs index 9abf2d9..e4edfc6 100644 --- a/src/traversal/traverser_core.rs +++ b/src/traversal/traverser_core.rs @@ -142,7 +142,7 @@ where 'a: 't; fn into_iter_with_storage<'a, V, M, P, MO>( - node_mut: NodeMut<'a, V, M, P, MO>, + node: NodeMut<'a, V, M, P, MO>, storage: impl SoM>, ) -> impl Iterator> where @@ -153,7 +153,7 @@ where O: Over; fn into_iter_with_storage_filtered<'a, V, M, P, MO, F>( - node_mut: NodeMut<'a, V, M, P, MO>, + node: NodeMut<'a, V, M, P, MO>, storage: impl SoM>, filter: F, ) -> impl Iterator> @@ -254,11 +254,11 @@ where O: OverMut, 'a: 't, { - Self::iter_mut_with_storage(node_mut, Self::Storage::default()) + Self::iter_mut_with_storage(node, Self::Storage::default()) } fn into_iter_with_owned_storage<'a, V, M, P, MO>( - node_mut: NodeMut<'a, V, M, P, MO>, + node: NodeMut<'a, V, M, P, MO>, ) -> impl Iterator> where V: TreeVariant + 'a, @@ -267,6 +267,6 @@ where MO: NodeMutOrientation, O: Over, { - Self::into_iter_with_storage(node_mut, Self::Storage::default()) + Self::into_iter_with_storage(node, Self::Storage::default()) } } From 17d11e14b128c2b9e8ccc53bb9cc50cfec13b6d2 Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 19:17:19 +0100 Subject: [PATCH 67/69] remove inherited lifetime bounds --- src/node_ref.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/node_ref.rs b/src/node_ref.rs index a4e60d3..dc26f87 100644 --- a/src/node_ref.rs +++ b/src/node_ref.rs @@ -1299,7 +1299,6 @@ where fn paths<'t, T>(&self) -> impl Iterator + Clone> + 't where T: Traverser + 't, - ::Storage: 't, 'a: 't, { let node_ptr = self.node_ptr(); @@ -1785,7 +1784,6 @@ where fn leaves<'t, T>(&self) -> impl Iterator + 't where T: Traverser + 't, - ::Storage: 't, 'a: 't, { let col = self.col(); @@ -2009,7 +2007,6 @@ where fn indices<'t, T>(&self) -> impl Iterator> + 't where T: Traverser + 't, - ::Storage: 't, 'a: 't, { let node_ptr = self.node_ptr(); From a90fd3d5c6550e2569509fb8105c5bb57e190aaf Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 19:25:38 +0100 Subject: [PATCH 68/69] explicit lifetimes for NodeMut::children_mut --- src/node_mut.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/node_mut.rs b/src/node_mut.rs index ed14132..89e9cc5 100644 --- a/src/node_mut.rs +++ b/src/node_mut.rs @@ -1697,7 +1697,7 @@ where /// let bfs: Vec<_> = tree.root().walk::().copied().collect(); /// assert_eq!(bfs, [1, 2, 3, 4, 5, 8]); /// ``` - pub fn remove_children(&mut self) { + pub fn remove_children(&'a mut self) { for c in self.children_mut() { _ = c.prune(); } @@ -2051,8 +2051,8 @@ where /// assert_eq!(dfs, [1, 2, 4, 8, 5, 9, 3, 6, 10, 7, 11, 12]); /// ``` pub fn children_mut( - &mut self, - ) -> impl ExactSizeIterator> + DoubleEndedIterator + &'a mut self, + ) -> impl ExactSizeIterator> + DoubleEndedIterator { ChildrenMutIter::new(self.col, unsafe { self.node_ptr.ptr() }) } From c8b75f29282bad69f5cb3a2ce09c25232c87027a Mon Sep 17 00:00:00 2001 From: orxfun Date: Sat, 6 Dec 2025 20:04:57 +0100 Subject: [PATCH 69/69] upgrade selfref-col dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d41e7d7..2c561e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ orx-self-or = "1.2.0" serde = { version = "1.0.228", optional = true, default-features = false } orx-pinned-vec = { version = "3.21.0", default-features = false } orx-split-vec = { version = "3.22.0", default-features = false } -orx-selfref-col = { git = "https://github.com/orxfun/orx-selfref-col.git", branch = "require-sync-for-symbolic-types", default-features = false } +orx-selfref-col = { version = "3.1.0", default-features = false } orx-concurrent-iter = { version = "3.3.0", default-features = false } orx-parallel = { version = "3.4.0", default-features = false, optional = true }