以下是我偶然发现的一些行为的最小示例:
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
所需的可变借位。这是允许的吗?或者这是一个错误?
答案 0 :(得分: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()
)。
它看起来像是最近的一次变化,由于双重借用而无法在Rust 0.11上编译。
我在这里打开了一个问题:https://github.com/rust-lang/rust/issues/16820
编辑(2014年9月10日):此错误现已更正:https://github.com/rust-lang/rust/pull/17101