我在结构上有类似以下方法:
impl<'a> SomeStructure<'a> {
// I need &'a mut because the iterator may mutate SomeStructure
fn iter<'a>(&'a mut self) -> SomeIterator<'a> {
SomeIterator { object: self }
}
fn test_something(&self) -> bool {
self.some_field < 0
}
}
然后我想像这样使用它们:
impl<'a> SomeTrait for &'a mut SomeStructure<'a> {
fn do_something(self) {
for e in self.iter() {
...
if self.test_something() {
break;
}
}
}
}
但是,Rust 不允许这样做(我已经修复了错误消息,因此它们引用了上面的示例代码):
io/convert_io.rs:119:17: 119:22 error: cannot borrow `*self` as immutable because it is also borrowed as mutable
io/convert_io.rs:119 if self.test_something() {
^~~~~
io/convert_io.rs:117:18: 117:23 note: previous borrow of `*self` occurs here
io/convert_io.rs:117 for e in self.iter() {
^~~~~
但我不明白 self.test_something()
调用中的不可变借用会如何干扰更早创建迭代器,即使迭代器确实会改变原始对象。
您能否解释一下这里发生了什么以及如何解决它?
最佳答案
这可能是错误 #8372由当前 for
的最低可行实现引起。它被实现为一个宏,使得
for pattern in iterator { body }
扩展为(您可以通过运行 rustc --pretty expanded foo.rs
看到它)
{
let it = &mut iterator;
loop {
match it.next() {
None => break,
Some(pattern) => { body }
}
}
}
问题是&mut iterator
借用,停止 iterator
it
时直接使用是在范围之内。您通常可以通过自己手动编写扩展来解决此问题:
impl<'a> SomeTrait for &'a mut SomeStructure<'a> {
fn do_something(self) {
let mut it = self.iter();
loop {
match it.next() {
None => break
Some(e) => {
if self.test_something() {
break;
}
}
}
}
}
}
也就是说...在这种情况下,如果self.iter()
,这实际上可能不起作用。借self
(特别是如果 test_something
采用 &mut self
,因为编译器必须禁止突变,否则迭代器可能会失效)。
如果您要添加 .view_creator()
方法返回self.iter()
(假设您在 self
类型中引用了 self.iter()
),则 it.view_creator().test_something()
可以工作(使用手动解包的 for 循环)。
(FWIW,有一个特征采用 self
并在 &mut Thing
上实现它,而不是采用 &mut self
并直接在 Thing
上实现它,这有点奇怪;尽管有有时有很好的理由。)
关于pointers - 在迭代器上的 `for` 循环内的结构上使用其他方法,这可以改变该结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20906378/