简体   繁体   中英

Cannot infer an appropriate lifetime when returning a slice from an iterator

I have a Vec<Point> with a simple struct Point {x: f32, y: f32, z: f32} . My vector represents hundreds of thousands of lines in 3D (it could be a Vec<Vec<Point>> in fact), so I keep track of the start/end of all lines.

pub struct Streamlines {
    lengths: Vec<usize>,
    offsets: Vec<usize>,  // cumulative sum of lengths
    data: Vec<Point>,
}

I want to create a non-consuming iterator for it, usable like:

for streamline in &streamlines {
    for point in &streamline {
        println!("{} {} {}", point.x, point.y, point.z);
    }
    println!("")
}

I found How to implement Iterator and IntoIterator for a simple struct? and started copyi-err, adapting :)

impl IntoIterator for Streamlines {
    type Item = &[Point];
    type IntoIter = StreamlinesIterator;

    fn into_iter(self) -> Self::IntoIter {
        StreamlinesIterator {
            streamlines: self,
            it_idx: 0
        }
    }
}

struct StreamlinesIterator {
    streamlines: &Streamlines,
    it_idx: usize
}

impl Iterator for StreamlinesIterator {
    type Item = &[Point];

    fn next(&mut self) -> Option<&[Point]> {
        if self.it_idx < self.streamlines.lengths.len() {
            let start = self.streamlines.offsets[self.it_idx];
            self.it_idx += 1;
            let end = self.streamlines.offsets[self.it_idx];

            Some(self.streamlines.data[start..end])
        }
        else {
            None
        }
    }
}

I used slices because I only want to return parts of the vector, then I added lifetimes because it's required, but now I have this error cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements

In fact, I don't actually know what I'm doing with the damn <'a> .

cannot infer an appropriate lifetime for lifetime parameter in generic type due to conflicting requirements

That's because you aren't correctly implementing Iterator and have something like this:

impl<'a> Iterator for StreamlinesIterator<'a> {
    type Item = &'a [Point];

    fn next(&mut self) -> Option<&[Point]> { /* ... */ }

    // ...
}

Due to lifetime inference, this is equivalent to:

impl<'a> Iterator for StreamlinesIterator<'a> {
    type Item = &'a [Point];

    fn next<'b>(&'b mut self) -> Option<&'b [Point]> { /* ... */ }

    // ...
}

This is attempting to return a reference that lives as long as the iterator, which you cannot do .

If you correctly implement Iterator , it works:

impl<'a> Iterator for StreamlinesIterator<'a> {
    type Item = &'a [Point];

    fn next(&mut self) -> Option<&'a [Point]> { /* ... */ }

    // Even better:   
    fn next(&mut self) -> Option<Self::Item> { /* ... */ }

    // ...
}

I don't actually know what I'm doing with the damn <'a> .

You should go back and re-read The Rust Programming Language , second edition . When you have specific questions, Stack Overflow, IRC, the User's Forum will all be waiting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM