英文:
questions related to rust RefCell<T> and Ref
问题
The code you provided has a few HTML entities (e.g., &
) 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 (&
) 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<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));
// this 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);
},
};
},
};
}
The commented like filed to compile, the error message is:
error[E0507]: cannot move out of dereference of `Ref<'_, Option<std::rc::Weak<Node>>>`
--> src/main.rs:30:11
|
30 | match *child_node_ptr.parent.borrow() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31 | None => {},
32 | Some(parent_weak_ptr) => {
| ---------------
| |
| data moved here
| move occurs because `parent_weak_ptr` has type `std::rc::Weak<Node>`, 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<Node>
child_node_ptr.parent : RefCell<Option<Weak<Node>>>
child_node_ptr.parent.borrow() : Ref<'_, T> where T is Option<Weak<Node>>
Now since std::cell::Ref also implemented Deref
trait based on Rust doc, dereferencing should give &T,
*child_node_ptr.parent.borrow() : &Option<Weak<Node>>
But in reality, when I print out the type, it is actually
*child_node_ptr.parent.borrow() : Option<Weak<Node>>
So this seems to be contradictory to what rust doc says about its Deref implementation.
fn deref(&self) -> &T
答案1
得分: 2
我明白答案是Deref coercion
在与我们作对而不是帮助我们。
*child_node_ptr.parent.borrow()
变成
*(child_node_ptr.parent.borrow().deref())
由于Deref coercion
,然后变成
*(&Option<Weak<Node>>)
最终变成
Option<Weak<Node>>
英文:
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
*(&Option<Weak<Node>>)
and becomes
Option<Weak<Node>>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论