与Rust中的RefCell<T>和Ref相关的问题

huangapple go评论68阅读模式
英文:

questions related to rust RefCell<T> and Ref

问题

The code you provided has a few HTML entities (e.g., &amp;) in it that are not standard in Rust code. I will provide you with a corrected and translated version of your code without these entities:

use std::cell::RefCell;
use std::rc::{Rc, Weak};

struct Node {
    val: i32,
    parent: RefCell<Option<Weak<Node>>>,
    child: RefCell<Option<Rc<Node>>>,
}

fn main() {
    let child_node = Node {
        val: 1,
        parent: RefCell::new(None),
        child: RefCell::new(None),
    };
    let child_node_ptr = Rc::new(child_node);

    let parent_node = Node {
        val: 2,
        parent: RefCell::new(None),
        child: RefCell::new(Some(Rc::clone(&child_node_ptr))),
    };
    let parent_node_ptr = Rc::new(parent_node);

    *child_node_ptr.parent.borrow_mut() = Some(Rc::downgrade(&parent_node_ptr));

    // The following line fails to compile
    match *child_node_ptr.parent.borrow() {
        None => {},
        Some(parent_weak_ptr) => {
            match parent_weak_ptr.upgrade() {
                None => {},
                Some(parent_rc_ptr) => {
                    println!("parent node value is {}", parent_rc_ptr.val);
                },
            };
        },
    };
}

I have removed the HTML entities (&amp;) and made the code more readable. The issue you were facing is related to the type of *child_node_ptr.parent.borrow(), which is indeed Option<Weak<Node>>, not &Option<Weak<Node>> as you initially expected. The Rust documentation you mentioned is correct, but in this context, the Deref implementation is not used because you are pattern matching directly on the Option<Weak<Node>> value.

英文:

I'm grappling with why the code below fails to compile. I'm trying to create a doubly linked list with two nodes. Then access the parent node's value from child node pointer.

use std::cell::RefCell;
use std::rc::{Rc, Weak};

struct Node {
    val : i32,
    parent : RefCell&lt;Option&lt;Weak&lt;Node&gt;&gt;&gt;,
    child : RefCell&lt;Option&lt;Rc&lt;Node&gt;&gt;&gt;,
}

fn main() {
    let child_node = Node {
        val : 1,
        parent : RefCell::new(None),
        child : RefCell::new(None),
    };
    let child_node_ptr = Rc::new(child_node);
    
    let parent_node = Node {
        val : 2,
        parent : RefCell::new(None),
        child : RefCell::new(Some(Rc::clone(&amp;child_node_ptr))),
    };
    let parent_node_ptr = Rc::new(parent_node);
    
    *child_node_ptr.parent.borrow_mut() = Some(Rc::downgrade(&amp;parent_node_ptr));
    
    // this line fails to compile
    match *child_node_ptr.parent.borrow() {
        None =&gt; {},
        Some(parent_weak_ptr) =&gt; {
            match parent_weak_ptr.upgrade() {
                None =&gt; {},
                Some(parent_rc_ptr) =&gt; {
                    println!(&quot;parent node value is {}&quot;, parent_rc_ptr.val);
                },
            };
        },
    };
}

The commented like filed to compile, the error message is:

error[E0507]: cannot move out of dereference of `Ref&lt;&#39;_, Option&lt;std::rc::Weak&lt;Node&gt;&gt;&gt;`
  --&gt; src/main.rs:30:11
   |
30 |     match *child_node_ptr.parent.borrow() {
   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31 |         None =&gt; {},
32 |         Some(parent_weak_ptr) =&gt; {
   |              ---------------
   |              |
   |              data moved here
   |              move occurs because `parent_weak_ptr` has type `std::rc::Weak&lt;Node&gt;`, which does not implement the `Copy` trait

My first questions is why this is the case? The way I'm looking at it, the type deduction is like follows:

child_node_ptr : Rc&lt;Node&gt;
child_node_ptr.parent : RefCell&lt;Option&lt;Weak&lt;Node&gt;&gt;&gt;
child_node_ptr.parent.borrow() : Ref&lt;&#39;_, T&gt;  where T is Option&lt;Weak&lt;Node&gt;&gt;

Now since std::cell::Ref also implemented Deref trait based on Rust doc, dereferencing should give &T,

*child_node_ptr.parent.borrow() : &amp;Option&lt;Weak&lt;Node&gt;&gt;

But in reality, when I print out the type, it is actually

*child_node_ptr.parent.borrow() : Option&lt;Weak&lt;Node&gt;&gt;

So this seems to be contradictory to what rust doc says about its Deref implementation.

fn deref(&amp;self) -&gt; &amp;T

答案1

得分: 2

我明白答案是Deref coercion在与我们作对而不是帮助我们。

*child_node_ptr.parent.borrow()

变成

*(child_node_ptr.parent.borrow().deref())

由于Deref coercion,然后变成

*(&amp;Option&lt;Weak&lt;Node&gt;&gt;)

最终变成

Option&lt;Weak&lt;Node&gt;&gt;
英文:

I figured out the answer is that Deref coercion is fighting us instead of helping us.

*child_node_ptr.parent.borrow()

becomes

*(child_node_ptr.parent.borrow().deref())

due to Deref coercion, then it becomes

*(&amp;Option&lt;Weak&lt;Node&gt;&gt;)

and becomes

Option&lt;Weak&lt;Node&gt;&gt;

huangapple
  • 本文由 发表于 2023年8月4日 03:15:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76831024.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定