我在结构上有类似的方法:
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()
调用中的不可变借用如何干扰先前创建迭代器,即使迭代器确实改变了原始对象。
您能解释一下这里发生了什么以及如何解决这个问题吗?
答案 0 :(得分:2)
这可能是由当前for
的最小工作实现引起的错误#8372。它被实现为宏,以便
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()
),则{{1}将工作(使用手动解包的for循环)。
(FWIW,有一个特点是有一个特点是it.view_creator().test_something()
并在self
上实施,而不是&mut Thing
并在&mut self
直接实施;虽然有有时是的充分理由。)