【问题标题】:Why does the borrow checker let me make two mutable borrows?为什么借用检查器让我进行两次可变借用?
【发布时间】:2014-08-27 13:19:06
【问题描述】:

这是我偶然发现的一些行为的一个最小示例:

pub struct PrimeEngine {
    primes: Vec<uint>,
}

pub struct PrimeIterator<'a> {
    engine: &'a mut PrimeEngine,
    index: uint
}

impl PrimeEngine {
    pub fn new() -> PrimeEngine {
        PrimeEngine { primes: vec![] }
    }

    // Needs a &mut so it can call more_primes if needed
    pub fn is_prime(&mut self, x: uint) -> bool {
        true
    }

    pub fn iter<'a>(&'a mut self) -> PrimeIterator<'a> { // '
        PrimeIterator { engine: self, index: 0 }
    }

    fn more_primes(&mut self) {
        // Adds more primes to self.primes
    }
}

impl<'a> Iterator<uint> for PrimeIterator<'a> {
    fn next(&mut self) -> Option<uint> {
        if self.engine.primes.len() <= self.index {
            self.engine.more_primes();
        }
        let i = self.index;
        self.index += 1;
        Some(self.engine.primes[i])
    }
}

以下代码无法编译,因为它尝试对 engine 进行两次可变借用,一次是在创建闭包时,另一次是在创建迭代器时:

#[test]
fn test1() {
    let mut engine = PrimeEngine::new();
    engine.iter().take(5).inspect(|x| {
        assert!(engine.is_prime(*x))
    });
}

然而,这段代码确实可以编译:

#[test]
fn test2() {
    let mut engine = PrimeEngine::new();
    for x in engine.iter().take(5) {
        assert!(engine.is_prime(x))
    }
}

我也不知道为什么。它需要对engine 进行可变借用以创建Iterator,这应该可以防止它进行调用is_prime 所需的可变借用。出于某种原因允许这样做吗?还是bug?

【问题讨论】:

    标签: rust


    【解决方案1】:

    我看起来像一个错误,我设法用更简单的代码重现了这个问题:

    fn main() {
        let mut vector = vec!(1u, 2u);
        for &x in vector.iter() {
            let cap = vector.capacity();
            println!("Capacity was: {}", cap);
            vector.grow(cap, &0u); // be sure to cause reallocation
            *vector.get_mut(1u) = 5u;
            println!("Value: {}", x);
        }
    }
    

    它输出:

    Capacity was: 4
    Value: 1
    Capacity was: 8
    Value: 2
    

    我正在修改向量内容并重新分配,导致底层切片引用未分配的内存(vector.iter() 实际上是vector.as_slice().iter())。

    看起来像是最近的更改,由于双重借用,它无法在 rust 0.11 上编译。

    我在这里打开了一个问题:https://github.com/rust-lang/rust/issues/16820

    编辑(2014 年 9 月 10 日):该错误现已更正:https://github.com/rust-lang/rust/pull/17101

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-30
      • 1970-01-01
      • 2015-08-05
      相关资源
      最近更新 更多