相关疑难解决方法(0)

从HashMap或Vec返回引用会导致借用超出其所在的范围?

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

我有一些代码检查地图中的值,如果它存在,则返回它,否则它需要以各种方式改变地图.问题是我似乎无法找到让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
}
Run Code Online (Sandbox Code Playgroud)

这出错了:

error[E0502]: cannot borrow `*map` as mutable because it is also borrowed as immutable
  --> src/lib.rs:14:5
   |
3 …
Run Code Online (Sandbox Code Playgroud)

rust borrow-checker

16
推荐指数
1
解决办法
1836
查看次数

即使使用NLL,循环中也会发生双重可变借用错误

假设我有几个结构,如下例所示,在next()方法中我需要使用用户提供的缓冲区来拉下一个事件,但是如果这个事件是注释,并且忽略comments标志设置为true,我需要拉下一个事件:

struct Parser {
    ignore_comments: bool,
}

enum XmlEvent<'buf> {
    Comment(&'buf str),
    Other(&'buf str),
}

impl Parser {
    fn next<'buf>(&mut self, buffer: &'buf mut String) -> XmlEvent<'buf> {
        let result = loop {
            buffer.clear();

            let temp_event = self.parse_outside_tag(buffer);

            match temp_event {
                XmlEvent::Comment(_) if self.ignore_comments => {}
                _ => break temp_event,
            }
        };
        result
    }

    fn parse_outside_tag<'buf>(&mut self, _buffer: &'buf mut String) -> XmlEvent<'buf> {
        unimplemented!()
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,即使#![feature(nll)]启用了以下代码,此代码也会出现双重借用错误:

error[E0499]: cannot borrow `*buffer` as mutable more than …
Run Code Online (Sandbox Code Playgroud)

rust borrow-checker

9
推荐指数
2
解决办法
489
查看次数

如何在Vec上更新或插入?

我在Rust写一个数据结构.它包含一Vec对键值对.当插入到结构中时,我需要找到匹配的键并更新键和值(实际上是子指针).代码看起来有点像这样,其中pivots是一个ref mutto Vec<Pivot>,Pivot它只是一个包含两个字段的结构:

match pivots.iter_mut().find(|ref p| key <= p.min_key) { // first mutable borrow
    Some(ref mut pivot) => {
        // If there is one, insert into it and update the pivot key
        pivot.min_key = key;
        pivot.child.insert(key, value) // recursive call
    },
    // o/w, insert a new leaf at the end
    None => pivots.push(Pivot /* ... */) // second mutable borrow
}
Run Code Online (Sandbox Code Playgroud)

但是有一个问题.即使我没有在第二部分中使用可变迭代器match,借用检查器也会抱怨我"不能*pivots一次多次借用可变的迭代".

这对我来说是完全合理的,因为第一次借用仍然在范围内,即使它没有在那种情况下使用match.这有点不方便:一个聪明的检查员当然可以说借用是不重叠的.我见过有人在线建议使用早期返回以避免问题,如下所示:

match pivots.iter_mut().find(|ref …
Run Code Online (Sandbox Code Playgroud)

rust borrow-checker

5
推荐指数
1
解决办法
1154
查看次数

什么时候需要绕过 Rust 的借用检查器?

我正在实施康威的生活游戏来自学 Rust。思路是先实现单线程版本,尽量优化,然后多线程版本也一样。

我想实现一个我认为可能对缓存更友好的替代数据布局。这个想法是将板上每个点的两个单元的状态存储在一个向量中,一个单元用于读取当前一代的状态,另一个用于写入下一代状态,交替访问模式每一代的计算(可以在编译时确定)。

基本数据结构如下:

#[repr(u8)]
pub enum CellStatus {
    DEAD,
    ALIVE,
}

/** 2 bytes */
pub struct CellRW(CellStatus, CellStatus);

pub struct TupleBoard {
    width: usize,
    height: usize,
    cells: Vec<CellRW>,
}

/** used to keep track of current pos with iterator e.g. */
pub struct BoardPos {
    x_pos: usize,
    y_pos: usize,
    offset: usize,
}

pub struct BoardEvo {
    board: TupleBoard,
}
Run Code Online (Sandbox Code Playgroud)

给我带来麻烦的功能:

impl BoardEvo {
    fn evolve_step<T: RWSelector>(&mut self) {
        for (pos, cell) in self.board.iter_mut() {
            //pos: BoardPos, cell: &mut …
Run Code Online (Sandbox Code Playgroud)

rust

4
推荐指数
1
解决办法
731
查看次数

标签 统计

rust ×4

borrow-checker ×3