Pointer to Self


#1

Hi,

I’m new here and I have a compiler error without description (rustc --explain flag doesn’t work for it)…
here is a short way to get it:

impl Test {
fn dosome(&mut self)
{
// error: cannot move out of borrowed content [E0507]
let a = Rc::new(*self);
}
}

can someone explain this error?

Generally, I’m trying to save a pointer to parent object inside child recursively…
here is a full code - see line 19.
how can I do that with Rust?

Thanks!


#2

You can’t have something inside of an Rc and also not inside of an Rc. Every reference to the data has to be reference counted, or else the reference count will be incorrect.

Trees with parent pointers are very verbose in safe Rust, and its not one of the language’s strong points. Cyclic data structures are just very hard when you don’t have garbage collections. You can’t implement methods on Rc<Item> directly, so you’ll need a wrapper struct like RefItem(Rc<Item>) to implement methods on.

You also can’t mutate a reference counted item unless you store it in an interior-mutability struct like a Cell or a RefCell, see the cell module for more information.

Then you need to worry about managing those parent pointers - either the parent or the child pointers need to be downgraded to Weak pointers or you’ll have cyclic references, and this struct will never be deallocated.


#3

This FAQ entry has some more suggestions on how to deal with cycles: https://www.rust-lang.org/faq.html#how-can-i-implement-a-data-structure-that-contains-cycles.

In similar situations I usually try hard to avoid cycles altogether, and if I fail, I resort to vector + indices trick.

In your particular snippet you need to change the signature of dosome to fix the error:

fn dosome(self) { // takes ownership over self
    let a = Rc::new(self); // handles ownership to `Rc`
}

PS: you can use triple backtick syntax for code on this forum:

```
fn main() {
    println!("Hello, W0rld!")
}
```

#4

Rust moves by default. In programming languages like C++, copy is the default and there this would of worked.
I think the compiler error is spot on.

Here the code takes a mutable reference. When somebody takes a mutable reference, the compiler will ensure that no one else can take at the same time another mutable reference, this way it ensures that a good amount of bugs are avoided(read on scopes and lifetimes).
Also, when you take a reference, be it a shared reference or a mutable reference, the compiler will make sure that the data is not moved, this way it can make sure that you don’t make mistakes like creating a dangling pointer bug(which could of happened in this code example if it would of allowed you to move and somewhere else you used that reference).

So, this: [quote=“ApelsetZ, post:1, topic:4719”]
let a = Rc::new(*self);
[/quote]
moves self into the Rc, the compiler throws the error because in the same scope, previously, you took it by reference fn dosome(&mut self). If you would of clone()d it, it would of worked but of course you would of had 2 copies now.

In short, you probably want to go with @matklad’s suggestion.