Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot infer appropriate lifetime for autoref when calling a method from an Iterator implementation

Tags:

rust

I am trying to implement the Iterator trait for a struct which acts as a borrower of an array of i32 values, but I keep running into the compiler complaining about not being able to infer a lifetime inside the next method.

I am aware of Need help understanding Iterator lifetimes, but since my struct just borrows a slice of the array anyway, I keep the memory of the actual elements separate from my IntegerArrayBag.

#[derive(Debug)]
struct IntegerArrayBag<'a> {
    arr: &'a [i32],
    idx: usize,
}

impl<'a> IntegerArrayBag<'a> {
    fn len(&self) -> usize {
        self.arr.len()
    }

    fn get(&self, idx: usize) -> Option<&i32> {
        if self.arr.len() > idx {
            Some(&self.arr[idx])
        } else {
            None
        }
    }
}

impl<'a> Iterator for IntegerArrayBag<'a> {
    type Item = &'a i32;

    fn next(&mut self) -> Option<&'a i32> {
        let idx = self.idx;
        self.idx += 1;
        self.get(idx)
    }
}

If I try to compile this code, the compiler complains with:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:27:14
   |
27 |         self.get(idx)
   |              ^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 24:5...
  --> src/main.rs:24:5
   |
24 | /     fn next(&mut self) -> Option<&'a i32> {
25 | |         let idx = self.idx;
26 | |         self.idx += 1;
27 | |         self.get(idx)
28 | |     }
   | |_____^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:27:9
   |
27 |         self.get(idx)
   |         ^^^^
note: but, the lifetime must be valid for the lifetime 'a as defined on the impl at 21:1...
  --> src/main.rs:21:1
   |
21 | / impl<'a> Iterator for IntegerArrayBag<'a> {
22 | |     type Item = &'a i32;
23 | |
24 | |     fn next(&mut self) -> Option<&'a i32> {
...  |
28 | |     }
29 | | }
   | |_^
note: ...so that expression is assignable (expected std::option::Option<&'a i32>, found std::option::Option<&i32>)
  --> src/main.rs:27:9
   |
27 |         self.get(idx)
   |         ^^^^^^^^^^^^^
like image 221
jtepe Avatar asked Jun 16 '15 13:06

jtepe


2 Answers

You need to update your get method to return a reference with longer life:

// Use 'a from impl<'a> IntegerArrayBag<'a>
fn get(&self, idx: usize) -> Option<&'a i32> {

and then it will compile.

like image 139
bluss Avatar answered Nov 16 '22 14:11

bluss


Changing get(…) to return Option<&'a i32> makes it compile.

Playground URL: https://play.rust-lang.org/?gist=10783e90287b7111c126&version=stable

Gist URL: https://gist.github.com/10783e90287b7111c126

like image 4
llogiq Avatar answered Nov 16 '22 14:11

llogiq