修复策略
作者首先提供了LendingIterator,这个接口如下:
pub trait LendingIterator {
/// The type of each item.
type Item<'a>
where
Self: 'a;
/// skip some code
}
可以看到,这边声明关联类型 Item 的时候,强制指定其要与Trait对象一致。换句话说,这里描述的trait要求实现当前接口的对象要和Item对象包含的结构成员生命周期保持一致。这其实是一个Rust提供的新特性(作者在README提到)连接在这
概括来说,这个特性能够实现以下的效果:
- 定义一个特征,并且在接口中声明一种关联类型的时候,声明生命周期,并且指定其和Self一致
- 当某个特定的结构体实现特征的时候,这个结构体使用关联类型参与的特征函数时,结构体与特征生命周期保持一致
最典型的就是我们上述提到的这个场景:我们需要迭代器与迭代器其中的类型生命周期保持一致。修复主要是通过这个特性实现的
其次,这里的Row也进行了一定的修改
/// A collection of column values. Read-only, so thread-safe. - pub struct Row<'a>(*const _Row, PhantomData<&'a CassResult>); + // + // Borrowed immutably. + pub struct Row<'a>(*const _Row, PhantomData<&'a _Row>);
这里的幽灵数据指向了Row自己(这个_Row就是来自C++的Row的指针)。
结合上述修改,此时Row指针的生命周期就和ResultIterator绑定了。如果此时我们尝试在ResultIterator生命周期使用取出来的Row,此时则会提示其中一方生命周期超出另一方,最终造成问题:
error[E0597]: `iter` does not live long enough
--> example.rs
|
21 | let mut iter = result.iter();
| -------- binding `iter` declared here
22 | while let Some(row) = iter.next() {
| ^^^^ borrowed value does not live long enough
...
28 | }
| - `iter` dropped here while still borrowed
29 |
30 | println!("here will cause problem {:?}", tmp_row);