我遇到了一个简化为以下问题的问题:
struct MyIter {
vec: Vec<i8>,
}
fn fill_with_useful_data(v: &mut Vec<i8>) {
/* ... */
}
impl<'a> Iterator for MyIter {
type Item = &'a [i8];
fn next(&mut self) -> Option<&'a [i8]> {
fill_with_useful_data(&mut self.vec);
Some(&self.vec)
}
}
fn main() {
for slice in (MyIter { vec: Vec::new() }) {
println!("{}", slice);
}
}
Run Code Online (Sandbox Code Playgroud)
这会生成错误:
error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
--> src/main.rs:9:6
|
9 | impl<'a> Iterator for MyIter {
| ^^ unconstrained lifetime parameter
Run Code Online (Sandbox Code Playgroud)
我们的想法是,迭代器会在其字段中反映一系列工作,并且在每一步中,它都会向调用代码生成一个引用.在这种情况下,我可以将其建模为产生状态的副本而不是参考,但让我们假装不可能或者只是不方便的昂贵.
直观地说,这不应该是一个问题,因为借用检查器可以确保.next()不会再次调用,而仍然可以使用所产生的引用来检查迭代器的状态,但是这个Iterator特性似乎并没有直接提供那种东西.即使有一些排列,例如只是在迭代器本身中持有对向量的引用,或者使迭代器成为引用或某些东西,以便将生命周期加入到先前类型中,我无法通过借用检查器获得任何东西.
我阅读了" 迭代器产生可变引用 "的博客帖子,但我不确定它是否/如何适用于我的问题而不涉及可变引用.
huo*_*uon 12
这是不可能的.如果允许,可以next再次调用,从而修改通过&甚至完全无效的参考可见的数据.这是因为self对象本身和返回的引用之间没有连接:没有明确的生命周期链接它们.
对于编译器来说明这一点并允许返回self下一个需要签名的引用
fn next(&'a mut self) -> Option<&'a [i8]>
Run Code Online (Sandbox Code Playgroud)
然而,这与特征的签名不同,特征的签名不允许作为通用代码,只是T: Iterator<...>不能告诉对某些人使用返回值有不同的要求T; 所有都必须以相同的方式处理.
该Iterator特征是为独立于迭代器对象的返回值而设计的,这对于迭代器适配器来说.collect是正确和安全的.这对于许多用途(例如在for循环内的瞬态使用)来说比限制性更严格,但它正是它现在的样子.我认为我们现在没有正确推广这种特性/ for循环的工具(具体来说,我认为我们需要具有更高等级生命周期的相关类型),但可能在未来.