Constrain Iterator::next return value validity until next call to Iterator::next


#1

I have an FFI library that wraps a database that supports iteration. The underlying database returns pointers to buffers that are only valid until the next iteration. My wrapper previously copied the results into a Box, but this is undesirable for performance. Can I leverage the type system to constrain results of Iterator::next to be valid only up until the next call of my iterator?

Thanks for your time!


#2

You can create a type on which you can repeatedly call next and have it return references which are only valid until the next iteration, because you’ll need to mutably borrow it again.

However, it is not currently possible to write a trait which abstracts over multiple such types, and you cannot implement the std::iter::Iterator trait for such a type. Rust’s type system is not powerful enough (yet) to write such an abstraction.

To express this type of thing in Rust’s type system we would need higher kinded lifetimes, which is a feature Rust currently doesn’t have. There has been a lot of talk recently about adding such a feature, but the implications of that are very complicated and it will likely take quite a long time to get there.

Here’s an example: https://is.gd/36wzil

EDIT: here’s a link to the relevant discussion on “internals”. https://internals.rust-lang.org/t/blog-post-series-alternative-type-constructors-and-hkt/4300


#3

Thanks for the info! I’ll be watching out for HKL in the future :slight_smile:


#4

You lose out on iterator adapters, but by just making a method that returns Option<&'a Value> you can support looping with while let loops. Something like

struct Data {
    x: i32
}

impl Data {
    fn next<'a>(&'a mut self) -> Option<&'a i32> {
        self.x += 1;
        if self.x > 10 {
            None
        } else {
            Some(&mut self.x)
        }
    }
}

fn main() {
    let mut x = Data { x: -2 };
    while let Some(val) = x.next() {
        println!("{}", val);
    }
}