When the last copy of an `@mut` value is overwritten or goes out of scope,
the runtime is free to deallocate the value it points to. When you take an
`&'r mut` to a value in an `@mut`, the compiler has to ensure that at least
one copy of the `@mut` exists for the lifetime 'r, since the `&'r mut`
isn't involved in memory management and risks becoming a dangling pointer
if the memory it points to gets deallocated. It does this by "rooting" the
borrow, which means that it implicitly stores a copy of the `@mut` pointer
on the stack for the lifetime 'r. The problem is that the lifetime 'r
escapes the stack frame (via the return value), so there's nowhere to store
a copy of the `@mut` that will outlive the borrow.

Also, even if the compiler realized that, since the pointer passed to the
function has to be frozen for the lifetime of the borrow, any `@mut` it
references will outlive the borrow, it would still have to dynamically
freeze the `@mut` for the lifetime 'r, and there's no way for the compiler
to know to dynamically *unfreeze* the `@mut` when the borrow ends, again
since the lifetime outlives the stack frame where the borrow happens.

One solution, since your function already relies on the `Node`s being
managed (they're stored via `@mut` pointers) is to pass around `@mut Node`s
rather than `&'r mut Node`s. There's no loss of generality, since your code
already requires that the pointers be managed.


On Mon, Apr 29, 2013 at 9:08 AM, Ryan Hyun Choi <ryan.c...@samsung.com>wrote:

> Dear all,
>
> I come across an error message that I do not know how to fix it. I have a
> tree, and I would like to have a function that returns
> a node in a tree. Here's the data structure:
>
> struct Node {
>     name: ~str,
>     children: ~[@mut Node]
> }
>
> This is a simplified search function. I would like to find a node whose
> name is the same as tag.
>
> fn findTreeNode<'r>(node: &'r mut Node, tag: &~str) -> Option<&'r mut
> Node> {
>     if node.name == *tag {
>         return Some(node);
>     }
>     else {
>             let childNode = node.children[0];
>             let candNode = findTreeNode(childNode, tag);
>             return candNode;
>     }
> }
>
> The error message that I got is
>
> error: illegal borrow: cannot root managed value long enough
> succinct.rs:777             let candNode = findTreeNode(childNode, tag);
>                                                         ^~~~~~~~~
> succinct.rs:768:76: 792:1 note: managed value would have to be rooted for
> the lifetime &'r  as defined on the block at 768:76...
> succinct.rs:768:76: 792:1 note: ...but can only be rooted for the block
> at 768:76
>
>
> 1. Could you kindly explain to me what the error message mean, and how to
> fix it?
>
>
> Addionally, I would like to have the follow code in the else statement.
>
> for uint::range(0, vec::len(node.children)) |i| {
>     let childNode = node.children[i];
>     // check whether the node in the Option() struct is valid
>     // if valid, wrap the node in Option(), and return it
>     // else continue the for loop
> }
>
> Here's my attempt:
>
>         for uint::range(0, vec::len(node.children)) |i| {
>             let childNode = node.children[0];
>             let candNode = findTreeNode(childNode, tag);
>
>             let mut found = match candNode {
>                 Some(c) => {
>                     true
>                 }
>                 None => {
>                     false
>                 }
>             };
>             if found {
>                 return candNode;
>             }
>         }
>         return None;
>
> And the error message that I get is:
>
> succinct.rs:788:23: 788:31 error: use of moved value: `candNode`
> succinct.rs:788                 return candNode;
>                                        ^~~~~~~~
> succinct.rs:779:34: 779:42 note: `candNode` moved here because it has
> type core::option::Option<&'r mut Node>, which is moved by default (use
> `copy` to override)
> succinct.rs:779             let mut found = match candNode {
>
>
> 2. Could you kindly explain to me how to fix this error?
> Any help would be much appreciated. Thank you a lot.
>
> Best regards,
> Ryan
>
> ---------
> appendix: this is how the tree is built. Tree is built using a stack.
>
> fn build(tag: &str, stack: &mut ~[@mut Node]) {
>     let node = @mut Node{name: str::from_slice(tag), children: ~[]};
>     if stack.is_empty() {
>         stack.push(node);
>     }
>     else {
>         let mut parent = stack.pop();
>         parent.children.push(node);
>         stack.push(parent);
>         stack.push(node);
>     }
> }
>
> Tree is built successfully.
>
> ----
> 최현 / Ryan Hyun Choi
> Senior Engineer
> Web Platform Lab.
> Software R&D Center
> Samsung Electronics Co., Ltd
> email: ryan.c...@samsung.com
> _______________________________________________
> Rust-dev mailing list
> Rust-dev@mozilla.org
> https://mail.mozilla.org/listinfo/rust-dev
>
_______________________________________________
Rust-dev mailing list
Rust-dev@mozilla.org
https://mail.mozilla.org/listinfo/rust-dev

Reply via email to