Why does checking a check allow me to make two volatile borrowings?

Here is a minimal example for some behavior that I came across:

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])
    }
}

The following code does not compile because it tries to make two mutable roles engine, once when creating a closure and again when creating an iterator:

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

This code, however, compiles:

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

And I have no idea why. To create, Iteratoryou need to create a mutable borrow engine, which should prevent him from making a mutable borrow, necessary for the call is_prime. Is this allowed for some reason? Or is this a mistake?

+4
source share
1 answer

I look like an error, I was able to reproduce this problem with simpler code:

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()).

, 0,11 - .

: https://github.com/rust-lang/rust/issues/16820

(10 sept 2014): ​​: https://github.com/rust-lang/rust/pull/17101

+4

All Articles