1

I would like to be able to pass mutable objects by reference to a function to have it 'work on them' but am struggling. I tried all most feasible combinations of lifetimes in the function definition and this seemed to be the only one to compile (but missed the correct one pointed out below). I suspect I need to use a Rust 'wrapper' but can't find any examples of what I would think was a very standard thing to do.

fn add<'a>(vec: &'a mut Vec<&'a str>, txt: &'a str) {
    vec.push(txt);
    for t in vec.iter() {
        print!("{} ", t);
    }
}

fn main() {
    let mut st = vec!["hello"];
    let words = vec!["world", "again", "!"];
    //for txt in words.iter() { // what I wanted to do
    //  add(&mut st, txt);
    //}
    st.push(","); // experiment works
    st.push("cruel");
    {
        add(&mut st, words[0]); // but this borrows to the end of main(){}
    } // instead of here
      // add(&mut st, words[1]); // so, for instance, this is a second borrow and not allowed
}

EDIT - answered as below in comments.

Thank you so much @Shepmaster and @trentcl, I had been singing the praises of the explicit and helpful rust debugger messages but failed to read

error[E0623]: lifetime mismatch
 --> src/main.rs:3:12
  |
2 | fn add(vec: &mut Vec<&str>, txt: &str) {
  |                      ----        ---- these two types are declared with different lifetimes...
3 |   vec.push(txt);
  |            ^^^ ...but data from `txt` flows into `vec` here

When I first added the lifetime specs. I put them in initially for the two main arguments and only added the <&str> when I got a further error. As you say it should be done like this:

fn add<'a>(vec: &mut Vec<&'a str>, txt: &'a str) {
  vec.push(txt);
}

fn main() {
  let mut st = vec!["hello"];
  let words = vec!["world", "again", "!"];
  for txt in words.iter() { // what I wanted to do
    add(&mut st, txt);
  }
  for txt in st.iter() {
    print!("{} ", txt);
  }
}
paddyg
  • 2,153
  • 20
  • 24
  • 5
    `arg: &'a Foo<'a>` is often (usually?) a mistake. Try `vec: &mut Vec<&'a str>` – trent Nov 20 '17 at 20:08
  • 5
    As trentcl says, by saying `vec: &'a mut Vec<&'a str>, txt: &'a str` you are requiring that all three references have a unified lifetime. In addition, since `vec` is mutable, you might be storing a reference *to itself* in the `Vec`. The most conservative approach means that the `Vec` can no longer be changed because doing so might cause a reallocation which would make the potentially self-saved reference invalid. – Shepmaster Nov 20 '17 at 20:16

0 Answers0