【问题标题】:What is the origin of the error "cannot move out of borrowed content"?“无法移出借来的内容”错误的根源是什么?
【发布时间】:2018-12-16 05:14:40
【问题描述】:

我一直不明白为什么我会收到 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

这种错误的根源是什么?

【问题讨论】:

  • Idiomatic Rust 使用snake_case 表示变量、方法、宏和字段; UpperCamelCase 用于类型; SCREAMING_SNAKE_CASE 用于静态和常量。请改用UserType

标签: rust


【解决方案1】:

仔细看这段代码:

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

在这里,您正在迭代 &amp;self.user_type_list,因此 iter 的类型实际上是对包含值的引用:&amp;Option&lt;Rc&lt;RefCell&lt;user_type&gt;&gt;&gt;。这很好,因为您不想拥有容器或其值的所有权。

然后你将iter 匹配到Some(ref x)。较旧的编译器版本会失败,因为您正在匹配对非引用的引用,但如果需要,新编译器会像匹配 Option&lt;&amp;T&gt; 而不是 &amp;Option&lt;T&gt; 一样。这很方便,意味着你可以只写Some(x) =&gt;x 类型将是&amp;Rc&lt;RefCell&lt;user_type&gt;&gt; 而不是&amp;&amp;Rc&lt;..&gt;(这并不重要,自动取消引用将使它们等效)。

现在你用&amp;Rc&lt;RefCell&lt;..&gt;&gt; 打电话给x.into_inner(),这永远不会奏效。看起来您想将不需要的 RefCell 转换为 tempRc 实现了 Deref,因此您可以免费获得它。相反,编译器认为您正在调用RefCell::into_inner(self) -&gt; T,但此函数使用self 来获取包含的值。你不拥有它,你只是借来的。这就是错误消息的意思:您正在尝试消费(移出)和您不拥有的对象(借用)。

你真正想要的只是借user_type足以调用to_string()

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

【讨论】:

    猜你喜欢
    • 2017-10-15
    • 1970-01-01
    • 1970-01-01
    • 2018-04-04
    • 2019-08-29
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-15
    相关资源
    最近更新 更多