@@ -19,36 +19,42 @@ use std::ptr::NonNull;
1919/// A Tree.
2020///
2121/// Wrapper around `tsk_tree_t`.
22- pub struct Tree {
22+ pub struct Tree < ' treeseq > {
2323 pub ( crate ) inner : mbox:: MBox < ll_bindings:: tsk_tree_t > ,
24+ // NOTE: this reference exists becaust tsk_tree_t
25+ // contains a NON-OWNING pointer to tsk_treeseq_t.
26+ // Thus, we could theoretically cause UB without
27+ // tying the rust-side object liftimes together.
28+ #[ allow( dead_code) ]
29+ treeseq : & ' treeseq TreeSequence ,
2430 api : TreeInterface ,
2531 current_tree : i32 ,
2632 advanced : bool ,
2733}
2834
29- impl Drop for Tree {
35+ impl < ' treeseq > Drop for Tree < ' treeseq > {
3036 fn drop ( & mut self ) {
3137 // SAFETY: Mbox<_> cannot hold a NULL ptr
3238 let rv = unsafe { tsk_tree_free ( self . inner . as_mut ( ) ) } ;
3339 assert_eq ! ( rv, 0 ) ;
3440 }
3541}
3642
37- impl Deref for Tree {
43+ impl < ' treeseq > Deref for Tree < ' treeseq > {
3844 type Target = TreeInterface ;
3945 fn deref ( & self ) -> & Self :: Target {
4046 & self . api
4147 }
4248}
4349
44- impl DerefMut for Tree {
50+ impl < ' treeseq > DerefMut for Tree < ' treeseq > {
4551 fn deref_mut ( & mut self ) -> & mut Self :: Target {
4652 & mut self . api
4753 }
4854}
4955
50- impl Tree {
51- fn new < F : Into < TreeFlags > > ( ts : & TreeSequence , flags : F ) -> Result < Self , TskitError > {
56+ impl < ' treeseq > Tree < ' treeseq > {
57+ fn new < F : Into < TreeFlags > > ( ts : & ' treeseq TreeSequence , flags : F ) -> Result < Self , TskitError > {
5258 let flags = flags. into ( ) ;
5359
5460 // SAFETY: this is the type we want :)
@@ -86,6 +92,7 @@ impl Tree {
8692 rv,
8793 Tree {
8894 inner: tree,
95+ treeseq: ts,
8996 current_tree: 0 ,
9097 advanced: false ,
9198 api
@@ -94,8 +101,8 @@ impl Tree {
94101 }
95102}
96103
97- impl streaming_iterator:: StreamingIterator for Tree {
98- type Item = Tree ;
104+ impl < ' ts > streaming_iterator:: StreamingIterator for Tree < ' ts > {
105+ type Item = Tree < ' ts > ;
99106 fn advance ( & mut self ) {
100107 let rv = if self . current_tree == 0 {
101108 unsafe { ll_bindings:: tsk_tree_first ( self . as_mut_ptr ( ) ) }
@@ -113,15 +120,15 @@ impl streaming_iterator::StreamingIterator for Tree {
113120 }
114121 }
115122
116- fn get ( & self ) -> Option < & Tree > {
123+ fn get ( & self ) -> Option < & Self :: Item > {
117124 match self . advanced {
118125 true => Some ( self ) ,
119126 false => None ,
120127 }
121128 }
122129}
123130
124- impl streaming_iterator:: DoubleEndedStreamingIterator for Tree {
131+ impl < ' ts > streaming_iterator:: DoubleEndedStreamingIterator for Tree < ' ts > {
125132 fn advance_back ( & mut self ) {
126133 let rv = if self . current_tree == 0 {
127134 unsafe { ll_bindings:: tsk_tree_last ( self . as_mut_ptr ( ) ) }
@@ -334,6 +341,21 @@ impl TreeSequence {
334341 /// }
335342 /// ```
336343 ///
344+ /// ## Coupled liftimes
345+ ///
346+ /// A `Tree`'s lifetime is tied to that of its tree sequence:
347+ ///
348+ /// ```{compile_fail}
349+ /// # use streaming_iterator::StreamingIterator;
350+ /// # use streaming_iterator::DoubleEndedStreamingIterator;
351+ /// # let mut tables = tskit::TableCollection::new(1000.).unwrap();
352+ /// # tables.build_index();
353+ /// let tree_sequence = tables.tree_sequence(tskit::TreeSequenceFlags::default()).unwrap();
354+ /// let mut tree_iterator = tree_sequence.tree_iterator(tskit::TreeFlags::default()).unwrap();
355+ /// drop(tree_sequence);
356+ /// while let Some(tree) = tree_iterator.next() { // compile fail.
357+ /// }
358+ /// ```
337359 /// # Warning
338360 ///
339361 /// The following code results in an infinite loop.
0 commit comments