tree_building/
tree_building.rs

1use loaned::{take, LoanedMut};
2
3#[derive(Debug, Default, Clone, PartialEq, Eq)]
4enum Tree {
5  #[default]
6  Null,
7  Leaf(i32),
8  Node(Box<Tree>, Box<Tree>),
9}
10
11#[cfg_attr(test, test)]
12fn main() {
13  // First, we create a single node `a`, which has two holes, `b` and `c`.
14  // ```text
15  //    a
16  //   / \
17  // ?b   ?c
18  // ```
19  // `a` is a `LoanedMut<Tree>`, whilst `b` and `c` are `&mut Tree`s.
20  let (a, b, c) = new_node();
21
22  // Next, we fill one of those holes, `b`, with a leaf:
23  // ```text
24  //    a
25  //   / \
26  //  1   ?c
27  // ```
28  *b = Tree::Leaf(1);
29
30  // Now, we create another node, `x`, with holes `y` and `z`:
31  // ```text
32  //   a        x
33  //  / \      / \
34  // 1   ?c  ?y   ?z
35  // ```
36  let (x, y, z) = new_node();
37
38  // We fill `y` with another leaf:
39  // ```text
40  //   a        x
41  //  / \      / \
42  // 1   ?c   2   ?z
43  // ```
44  *y = Tree::Leaf(2);
45
46  // Now, we fill the hole `c` with the node `x`.
47  // ```text
48  //   a
49  //  / \
50  // 1  / \
51  //   2   ?z
52  // ```
53  // We still have a mutable reference to the hole `z`, even though we just
54  // moved ownership of `x` – this is the key power of `Loaned` values.
55  x.place(c); // this is like `*c = x`, except it accepts `Loaned` values.
56
57  // Finally, we can fill the hole `z` (which is a mutable reference to data now owned by `a`):
58  // ```text
59  //   a
60  //  / \
61  // 1  / \
62  //   2   3
63  // ```
64  *z = Tree::Leaf(3);
65
66  // All of the borrows have expired, so we can now take the tree out of `a`:
67  let a = take!(a);
68
69  println!("{a:?}");
70  assert_eq!(format!("{a:?}"), "Node(Leaf(1), Node(Leaf(2), Leaf(3)))");
71
72  // If we tried to use one of the borrows now, we would get an error from the borrow checker.
73  // *z = Tree::Leaf(0xBAD);
74}
75
76fn new_node<'t>() -> (LoanedMut<'t, Tree>, &'t mut Tree, &'t mut Tree) {
77  let ((left, right), root) = LoanedMut::loan_with(
78    Tree::Node(Default::default(), Default::default()),
79    |tree, l| {
80      let Tree::Node(left, right) = tree else {
81        unreachable!()
82      };
83      (l.loan_mut(left), l.loan_mut(right))
84    },
85  );
86  (root, left, right)
87}