2014-08-27 1 views
4

Вот минимальный пример для некоторого поведения я наткнулся на:Почему проверка кредита позволяет мне сделать два изменчивых заимствования?

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

И я понятия не имею, почему. Чтобы создать Iterator, необходимо сделать изменчивый заимствование engine, что должно помешать ему сделать изменяемый долг, необходимый для вызова is_prime. Это разрешено по какой-то причине? Или это ошибка?

ответ

4

Я похож на жука, мне удалось воспроизвести этот вопрос с простым кодом:

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

Edit (10 Sept 2014): Исправлена ​​ошибка теперь исправленный: https://github.com/rust-lang/rust/pull/17101

 Смежные вопросы

  • Нет связанных вопросов^_^