我永远不明白为什么我收到Rust错误“无法摆脱借来的内容” .
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::vec::Vec;
pub struct user_type {
pub name: String,
pub ilist: Vec<i32>,
pub user_type_list: VecDeque<Option<Rc<RefCell<user_type>>>>,
pub parent: Option<Rc<RefCell<user_type>>>,
}
impl user_type {
pub fn new(name: String) -> Self {
user_type {
name: name.clone(),
ilist: Vec::new(),
user_type_list: VecDeque::new(),
parent: Option::None,
}
}
pub fn to_string(&self) -> String {
let mut result: String = String::new();
result += "name is ";
result += &self.name;
let n = self.user_type_list.len();
for iter in &self.user_type_list {
match iter {
Some(ref x) => {
let temp = x.into_inner();
let temp2 = temp.to_string();
result += &temp2[..];
}
None => panic!("to_string"),
}
result += "\n";
}
result
}
}
完整的错误消息是:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:34:32
|
34 | let temp = x.into_inner();
| ^ cannot move out of borrowed content
这种错误的起源是什么?
1 回答
仔细看看这段代码:
在这里,您正在迭代
&self.user_type_list
,因此iter
的类型实际上是对包含值的引用:&Option<Rc<RefCell<user_type>>>
. 这很好,因为您不想取得容器或其值的所有权 .然后你匹配
iter
到Some(ref x)
. 较旧的编译器版本将失败,因为您匹配对非引用的引用,但新的编译器将执行,如果您匹配Option<&T>
而不是&Option<T>
(如果需要) . 这很方便,意味着你只能写Some(x) =>
和x
将是&Rc<RefCell<user_type>>
而不是&&Rc<..>
(不是真的很重要,自动解除引用将使这些等效) .现在你用
&Rc<RefCell<..>>
调用x.into_inner()
,这将无法工作 . 看起来你想把RefCell
变成不需要的temp
,Rc
实现Deref
所以你可以免费获得 . 相反,编译器认为您正在调用RefCell::into_inner(self) -> T
,但此函数使用self
来获取包含的值 . 你不拥有它,你只是借用它 . 这就是错误消息的含义:您正在尝试使用(移出)和您不拥有的对象(借用) .你真正想要的只是借用
user_type
足以召唤to_string()
: