1
votes

I'm trying to implement the Index trait for a struct with lifetimes and struggle. I want an internal vector to be indexable on a &str. I.e. myqstr["foo"].

Here is what I got:

pub struct QString<'a> {
    pub params: Vec<Param<'a>>
}

pub struct Param<'a> {
    pub name: &'a str,
    pub value: &'a str,
}

impl<'a, 'b> ::std::ops::Index<&'b str> for QString<'a> {
    type Output = Param<'a>;
    fn index(&self, index: &'b str) -> &Param<'a> {
        &self.params.iter()
            .rposition(|ref p| p.name == index)
            .map(|pos| self.params[pos])
            .unwrap()
    }
}

And the error is the classic.

   Compiling qstring v0.1.0 (file:///Users/martin/dev/qstring)
error[E0597]: borrowed value does not live long enough
   --> src/lib.rs:113:10
    |
113 |           &self.params.iter()
    |  __________^
114 | |             .rposition(|ref p| p.name == index)
115 | |             .map(|pos| self.params[pos])
116 | |             .unwrap()
    | |_____________________^ does not live long enough
117 |       }
    |       - temporary value only lives until here
    |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the method body at 112:5

I understand Index wants me to return a borrowed value of the indexed structure, and I know the lifetime of what I want to return is 'a, but is that even possible in this instance?

1

1 Answers

3
votes

You're taking the reference in the wrong place, you want to take the reference inside your .map function.

self.params.iter()
    .rposition(|ref p| p.name == index)
    .map(|pos| &self.params[pos])
    .unwrap()

because you want a reference to the param that is in the Vec itself.

It'd also be easier to do

self.params.iter()
    .rev()
    .find(|p| p.name == index)
    .unwrap()