【问题标题】:Cannot borrow immutable borrowed content as mutable不能将不可变的借用内容借用为可变的
【发布时间】:2016-05-02 12:51:38
【问题描述】:

我正在尝试开发一个消息路由应用程序。我阅读了 Rust 官方文档和一些文章,并认为我了解了指针、拥有和借用东西的工作原理,但意识到我没有。

use std::collections::HashMap;
use std::vec::Vec;

struct Component {
    address: &'static str,
    available_workers: i32,
    lang: i32
}

struct Components {
    data: HashMap<i32, Vec<Component>>
}

impl Components {
    fn new() -> Components {
        Components {data: HashMap::new() }
    }

    fn addOrUpdate(&mut self, component: Component) -> &Components {
        if !self.data.contains_key(&component.lang) {

            self.data.insert(component.lang, vec![component]);
        } else {
            let mut q = self.data.get(&component.lang); // this extra line is required because of the error: borrowed value does not live long enough
            let mut queue = q.as_mut().unwrap();
            queue.remove(0);
            queue.push(component);
        }
        self
    }

}

(也可通过playground 获得)

产生错误:

error: cannot borrow immutable borrowed content `**queue` as mutable
  --> src/main.rs:26:13
   |
26 |             queue.remove(0);
   |             ^^^^^ cannot borrow as mutable

error: cannot borrow immutable borrowed content `**queue` as mutable
  --> src/main.rs:27:13
   |
27 |             queue.push(component);
   |             ^^^^^ cannot borrow as mutable

您能否解释一下错误,如果您能给我正确的实现,那就太好了。

【问题讨论】:

    标签: rust


    【解决方案1】:

    这是您的问题的MCVE

    use std::collections::HashMap;
    
    struct Components {
        data: HashMap<u8, Vec<u8>>,
    }
    
    impl Components {
        fn add_or_update(&mut self, component: u8) {
            let mut q = self.data.get(&component);
            let mut queue = q.as_mut().unwrap();
            queue.remove(0);
        }
    }
    

    在 NLL 之前

    error[E0596]: cannot borrow immutable borrowed content `**queue` as mutable
      --> src/lib.rs:11:9
       |
    11 |         queue.remove(0);
       |         ^^^^^ cannot borrow as mutable
    

    NLL之后

    error[E0596]: cannot borrow `**queue` as mutable, as it is behind a `&` reference
      --> src/lib.rs:11:9
       |
    11 |         queue.remove(0);
       |         ^^^^^ cannot borrow as mutable
    

    很多时候,当事情看起来像这样令人惊讶时,print out the types involved 很有用。我们打印出queue的类型:

    let mut queue: () = q.as_mut().unwrap();
    
    error[E0308]: mismatched types
      --> src/lib.rs:10:29
       |
    10 |         let mut queue: () = q.as_mut().unwrap();
       |                             ^^^^^^^^^^^^^^^^^^^ expected (), found mutable reference
       |
       = note: expected type `()`
                  found type `&mut &std::vec::Vec<u8>`
    

    我们有一个 可变 引用到一个 不可变 引用到 Vec&lt;u8&gt;。因为我们有一个对Vec 的不可变引用,所以我们不能修改它!将 self.data.get 更改为 self.data.get_mut 会将类型更改为 &amp;mut &amp;mut collections::vec::Vec&lt;u8&gt; 并且代码编译。


    如果你想实现“插入或更新”的概念,你应该签入entry API,这样更高效简洁。

    除此之外,Rust 使用 snake_case 来命名方法,而不是 camelCase

    【讨论】:

    • 谢谢。现在我更好地理解它了。感谢您提供有关打印类型的建议,它对故障排除非常有帮助
    • 打印出所涉及的类型下的链接是否仍然可用?有一个 SO 问题,但我认为该链接指向了一些答案。
    • @stej 链接指向问题。这样可以提供更好的答案,或者如果情况不同,实施者可以选择不同的答案。在这种情况下,我使用了“分配给空元组”的版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 2018-07-05
    • 2015-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多