Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 从HashMap或Vec返回引用会导致借用持续时间超出其作用域';她在吗?_Rust_Borrow Checker - Fatal编程技术网

Rust 从HashMap或Vec返回引用会导致借用持续时间超出其作用域';她在吗?

Rust 从HashMap或Vec返回引用会导致借用持续时间超出其作用域';她在吗?,rust,borrow-checker,Rust,Borrow Checker,我遇到了一个持久的编译错误,Rust抱怨我在尝试可变借用时有一个不可变的借用,但是不可变的借用来自另一个范围,我没有从中带来任何东西 我有一些代码检查映射中的值,如果它存在,则返回它,否则它需要以各种方式改变映射。问题是我似乎找不到一种方法来除锈,让我两者都做吧,即使这两个操作是完全分开的 下面是一些与我的代码结构相同的无意义代码,并显示了问题: use std::collections::BTreeMap; fn do_stuff(map: &mut BTreeMap<i32,

我遇到了一个持久的编译错误,Rust抱怨我在尝试可变借用时有一个不可变的借用,但是不可变的借用来自另一个范围,我没有从中带来任何东西

我有一些代码检查映射中的值,如果它存在,则返回它,否则它需要以各种方式改变映射。问题是我似乎找不到一种方法来除锈,让我两者都做吧,即使这两个操作是完全分开的

下面是一些与我的代码结构相同的无意义代码,并显示了问题:

use std::collections::BTreeMap;

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> {
    // extra scope in vain attempt to contain the borrow
    {
        // borrow immutably
        if let Some(key) = map.get(&key) {
            return Some(key);
        }
    }

    // now I'm DONE with the immutable borrow, but rustc still thinks it's borrowed

    map.insert(0, 0); // borrow mutably, which errors
    None
}
使用std::collections::BTreeMap;
fn do_stuff(映射:&mutbtreemap,键:i32)->选项{
//额外作用域徒劳地试图包含借用
{
//一成不变地借钱
如果let Some(key)=map.get(&key){
返回一些(键);
}
}
//现在我已经完成了不可变的借用,但rustc仍然认为它是借用的
map.insert(0,0);//可变借用,哪个错误
没有一个
}
此错误与以下内容有关:

error[E0502]:无法将“*map”作为可变项借用,因为它也是作为不可变项借用的
-->src/lib.rs:14:5
|
3 | fn do_stuff(映射:&mutbtreemap,键:i32)->选项{
|-我们将此引用的生存期称为“1”`
...
7 |如果让一些(键)=映射。获取(&key){
|---此处发生不可变借用
8 |返回一些(键);
|------返回此值需要为“%1”借用“*map”`
...
14 | map.insert(0,0);//可变借用,哪个错误
|^^^^^^^^^^^^^^^^^^^^^^^^^^^^此处发生可变借用
这对我来说没有任何意义。不可变的借词如何超过该范围?!该
match
的一个分支通过
return
退出函数,而另一个分支什么也不做并离开该范围

我以前见过这种情况,在其他变量中,我错误地将借来的数据带出了作用域,但这里的情况并非如此

的确,借用是通过
return
语句逃出作用域的,但在函数中阻止进一步借用是荒谬的——程序不可能返回并继续运行!如果我在那里返回其他内容,错误就会消失,因此我想这就是借用检查器遇到的问题。这感觉像是一个错误虫子对我来说

不幸的是,我一直无法找到任何方法来重写它而不出现相同的错误,因此如果是这样的话,这是一个特别严重的错误。

这是一个将在的未来迭代中解决的问题,但目前未在Rust 1.51中处理

如果您正在插入正在查找的同一个键,我建议您改为插入

你现在可以添加一点低效率来解决这个问题。如果低效率是不可接受的

HashMap
一般的想法是添加一个布尔值,告诉您是否存在值。此布尔值不挂起引用,因此不存在借用:

use std::collections::BTreeMap;

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> {
    if map.contains_key(&key) {
        return map.get(&key);
    }

    map.insert(0, 0);
    None
}

fn main() {
    let mut map = BTreeMap::new();
    do_stuff(&mut map, 42);
    println!("{:?}", map)
}
你可以写:

fn find_or_create_five<'a>(container: &'a mut Vec<u8>) -> &'a mut u8 {
    let idx = container.iter().position(|&e| e == 5).unwrap_or_else(|| {
        container.push(5);
        container.len() - 1    
    });
    &mut container[idx]
}
fn查找或创建五个(容器:&mut Vec)->&mut u8{
匹配container.iter_mut().find(| e |**e==5){
一些(元素)=>元素,
无=>{
容器。推(5);
container.last_mut().unwrap()
}
}
}
另见:

  • 这是同样的问题,但不返回引用,它与Rust 1.32中提供的NLL实现一起工作

  • 这是一个比较复杂的问题

  • 终极逃生舱

不幸的是,.entry()不适合这个函数需要做的事情。我知道非词法范围的问题,通常我可以解决它,但在这种情况下,我无法想出一些不做大量重复工作的方法,无论解决方法有多么丑陋……通常添加范围也能解决这个问题,但在这里它不能;even将一个借阅移动到另一个函数没有帮助。
fn find_or_create_five<'a>(container: &'a mut Vec<u8>) -> &'a mut u8 {
    let idx = container.iter().position(|&e| e == 5).unwrap_or_else(|| {
        container.push(5);
        container.len() - 1    
    });
    &mut container[idx]
}
use std::collections::BTreeMap;

fn do_stuff(map: &mut BTreeMap<i32, i32>, key: i32) -> Option<&i32> {
    if let Some(key) = map.get(&key) {
        return Some(key);
    }

    map.insert(0, 0);
    None
}
fn find_or_create_five(container: &mut Vec<u8>) -> &mut u8 {
    match container.iter_mut().find(|e| **e == 5) {
        Some(element) => element,
        None => {
            container.push(5);
            container.last_mut().unwrap()
        }
    }
}