修复策略
作者首先提供了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);