“无法移出借用的内容”错误的根源是什么?

时间:2018-07-08 08:03:35

标签: rust

我从不理解为什么我收到Rust错误“无法移出借用的内容”。

let objFromLocalStorage = 
localStorage.getItem('coordinates');

完整的错误消息是:

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
    }
}

这种错误的起因是什么?

1 个答案:

答案 0 :(得分:0)

仔细查看以下代码:

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";
}

在这里,您要迭代&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<..>(这并不重要,自动取消引用将使等效)。

现在,您正在使用x.into_inner()来呼叫&Rc<RefCell<..>>,这将永远无法进行。似乎您想将RefCell放入不需要的temp中,Rc实现了Deref,因此您可以免费获得它。相反,编译器认为您正在调用RefCell::into_inner(self) -> T,但是此函数使用self来获取所包含的值。而且您不拥有它,只是借用了它。这就是错误消息的含义:您正在尝试消耗(移出)和不拥有的对象(借入)。

您真正想要的只是借用user_type足以打电话给to_string()

Some(x) => { 
    let temp = x.borrow().to_string();
    result += &temp;
}