I'm working on a project to make a datastore that is backed by SQLite. Before I work on it, though, I wanted to read prior projects that do something similar, and found Mozilla's abandoned mentat
project. The last commit was back in september 2018, which does not seem like that long ago, so I thought I would try to pull it down and see if I could get it to build and run its tests, then begin to read how they structure their work.
Right away, the project doesn't build for a lot of reasons I can't immediately figure out. I suspect they must have been using a much older version of Rust, or something, and have decided to try to see if I can get it working with rustc 1.36.0
.
The first culprit I'm working on is upgrading their very out-of-date SQLite dependency, the rusqlite
crate. While I think I have managed to get the majority of compiler errors taken care of, this one completely stumps me.
I apologize for not knowing how to cut this down to a simple RustPlayground example, but if you'd like to follow along locally:
git clone git@github.com:cpdean/mentat.git
git checkout cd/upgrade_rusqulite_0.19
# rustc --version
# rustc 1.36.0 (a53f9df32 2019-07-03)
cargo build
There should be two compiler errors, both regarding a type not implementing Iterator
.
error[E0599]: no method named `next` found for type `rusqlite::MappedRows<'conn, F>` in the current scope
--> db/src/cache.rs:223:14
|
223 | .next()
| ^^^^
|
= note: the method `next` exists but the following trait bounds were not satisfied:
`rusqlite::MappedRows<'conn, F> : std::iter::Iterator`
error[E0599]: no method named `peekable` found for type `cache::AevRows<'_, [closure@db/src/cache.rs:1078:47: 1078:84 aev_factory:_]>` in the current scope
--> db/src/cache.rs:1083:18
|
210 | pub struct AevRows<'conn, F> {
| ---------------------------- method `peekable` not found for this
...
1083 | aevs.peekable(),
| ^^^^^^^^
|
= note: the method `peekable` exists but the following trait bounds were not satisfied:
`&mut cache::AevRows<'_, [closure@db/src/cache.rs:1078:47: 1078:84 aev_factory:_]> : std::iter::Iterator`
`cache::AevRows<'_, [closure@db/src/cache.rs:1078:47: 1078:84 aev_factory:_]> : std::iter::Iterator`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following traits define an item `peekable`, perhaps you need to implement one of them:
candidate #1: `std::iter::Iterator`
candidate #2: `fallible_iterator::FallibleIterator`
error: aborting due to 2 previous errors
However, the type that AevRows
uses internally to implement Iterator, rusqlite::MappedRows
, actually DOES implement Iterator
. On the crate version of rusqlite specified by the Cargo.toml's, it is implemented right here:
impl<T, F> Iterator for MappedRows<'_, F>
where
F: FnMut(&Row<'_>) -> Result<T>,
{
type Item = Result<T>;
fn next(&mut self) -> Option<Result<T>> {
let map = &mut self.map;
self.rows
.next()
.transpose()
.map(|row_result| row_result.and_then(|row| (map)(&row)))
}
}
The second compiler error is similar to the first, in that there is an explicit implementation of Iterator
but the compiler claims it's not being implemented, however I suspect since impl Iterator for AevRows
is dependant on MappedRows
's implementation, fixing the issue with MappedRows
may fix it for both. Here is the Iterator
impl for AevRows
:
impl<'conn, F> Iterator for AevRows<'conn, F>
where
F: FnMut(&rusqlite::Row) -> Result<Aev>,
{
type Item = Aev;
fn next(&mut self) -> Option<Aev> {
self.rows
.next()
.map(|row_result| row_result.expect("All database contents should be representable"))
}
}
How do I make sure these traits are implemented for these structs?