@@ -19,36 +19,42 @@ use std::ptr::NonNull;
19
19
/// A Tree.
20
20
///
21
21
/// Wrapper around `tsk_tree_t`.
22
- pub struct Tree {
22
+ pub struct Tree < ' treeseq > {
23
23
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 ,
24
30
api : TreeInterface ,
25
31
current_tree : i32 ,
26
32
advanced : bool ,
27
33
}
28
34
29
- impl Drop for Tree {
35
+ impl < ' treeseq > Drop for Tree < ' treeseq > {
30
36
fn drop ( & mut self ) {
31
37
// SAFETY: Mbox<_> cannot hold a NULL ptr
32
38
let rv = unsafe { tsk_tree_free ( self . inner . as_mut ( ) ) } ;
33
39
assert_eq ! ( rv, 0 ) ;
34
40
}
35
41
}
36
42
37
- impl Deref for Tree {
43
+ impl < ' treeseq > Deref for Tree < ' treeseq > {
38
44
type Target = TreeInterface ;
39
45
fn deref ( & self ) -> & Self :: Target {
40
46
& self . api
41
47
}
42
48
}
43
49
44
- impl DerefMut for Tree {
50
+ impl < ' treeseq > DerefMut for Tree < ' treeseq > {
45
51
fn deref_mut ( & mut self ) -> & mut Self :: Target {
46
52
& mut self . api
47
53
}
48
54
}
49
55
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 > {
52
58
let flags = flags. into ( ) ;
53
59
54
60
// SAFETY: this is the type we want :)
@@ -86,6 +92,7 @@ impl Tree {
86
92
rv,
87
93
Tree {
88
94
inner: tree,
95
+ treeseq: ts,
89
96
current_tree: 0 ,
90
97
advanced: false ,
91
98
api
@@ -94,8 +101,8 @@ impl Tree {
94
101
}
95
102
}
96
103
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 > ;
99
106
fn advance ( & mut self ) {
100
107
let rv = if self . current_tree == 0 {
101
108
unsafe { ll_bindings:: tsk_tree_first ( self . as_mut_ptr ( ) ) }
@@ -113,15 +120,15 @@ impl streaming_iterator::StreamingIterator for Tree {
113
120
}
114
121
}
115
122
116
- fn get ( & self ) -> Option < & Tree > {
123
+ fn get ( & self ) -> Option < & Self :: Item > {
117
124
match self . advanced {
118
125
true => Some ( self ) ,
119
126
false => None ,
120
127
}
121
128
}
122
129
}
123
130
124
- impl streaming_iterator:: DoubleEndedStreamingIterator for Tree {
131
+ impl < ' ts > streaming_iterator:: DoubleEndedStreamingIterator for Tree < ' ts > {
125
132
fn advance_back ( & mut self ) {
126
133
let rv = if self . current_tree == 0 {
127
134
unsafe { ll_bindings:: tsk_tree_last ( self . as_mut_ptr ( ) ) }
@@ -334,6 +341,21 @@ impl TreeSequence {
334
341
/// }
335
342
/// ```
336
343
///
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
+ /// ```
337
359
/// # Warning
338
360
///
339
361
/// The following code results in an infinite loop.
0 commit comments