0

I want to keep an Holded instance, but I can't since it's in an array. How can I do to 'extract' this instance from the array and keep it in an Object instance ? (In my original code, I don't have array but iterators). Here is the equivalent code :

struct Holded {
    value: u8,
}

struct Holder;

impl Holder {
    pub fn get(&self) -> [Holded; 2] {
        [Holded { value: 0 }, Holded { value: 1 }]
    }
}

struct Object<'a> {
    holded: &'a Holded,
}

fn main() {
    let holder = Holder;

    let obj = work(&holder).unwrap();
    println!("{}", obj.holded.value);
}

fn work(holder: &Holder) -> Option<Object> {
    let mut obj: Object;
    let array = holder.get();

    for h in array.into_iter() {
        if h.value == 1u8 {
            obj = Object { holded: h };
            return Some(obj);
        }
    }

    None
}

The error message:

error: `array` does not live long enough
  --> src/main.rs:28:14
   |
28 |     for h in array.into_iter() {
   |              ^^^^^ does not live long enough
...
36 | }
   | - borrowed value only lives until here
   |
note: borrowed value must be valid for the anonymous lifetime #1 defined on the block at 24:43...
  --> src/main.rs:24:44
   |
24 | fn work(holder: &Holder) -> Option<Object> {
   |                                            ^
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 1
    There are [**87 questions** with the same error message](http://stackoverflow.com/search?q=is%3Aq+Cannot+infer+an+appropriate+lifetime+due+to+conflicting+requirements). Perhaps you could take the time to review some of them and explain why *this* question is special and different and hasn't already been answered? – Shepmaster Jan 27 '17 at 23:33
  • I already seen many of them, but the problem here is mostly I don't quiet understand _why_ I have this error, and seeing the other post doesn't help me on this. – Nils 'Linkpy' Reid Jan 27 '17 at 23:35
  • I've also seen many of them, and the problem is explained in one. — See how useful it is when you don't point out what is *wrong* with *any* of the existing questions? If you don't tell us what is wrong, we will just repeat the same answer you already don't understand, you won't be helped, and, even worse, there will be one more answer that the next person won't read and instead ignore and ask to have their code fixed. – Shepmaster Jan 27 '17 at 23:40
  • 2
    I compiled your code and placed the **entire error message** into the question. Did you read what the compiler said? Did you try it? – Shepmaster Jan 27 '17 at 23:43
  • Additionally, I highly recommend that you learn to create a [MCVE]. Doing so will help you as you learn and grow as a programmer. It also greatly helps as you can focus on just the problem at hand and not be distracted by any extra junk. This is [one example of how to reduce your code while maintaining the same error message](http://play.integer32.com/?gist=832bb6a62bd74a07331e3731d968a410&version=stable). This will probably be a duplicate of http://stackoverflow.com/q/32300132/155423. – Shepmaster Jan 28 '17 at 01:23
  • @Shepmaster: interesting, the `help: consider..` message only appears when running on stable, on nightly this is not shown – hansaplast Jan 28 '17 at 10:15
  • I started to understand why I'm getting this error, now I just need to know how to extract a value from an iterator and it will be good for me. I done a minimal, complete and verifiable example. – Nils 'Linkpy' Reid Jan 28 '17 at 10:22
  • @hansaplast that's disappointing. Looks like [the messages were not frequently useful](https://github.com/rust-lang/rust/commit/a2735c02493d816835a19249dd258e0c678530d0). – Shepmaster Jan 28 '17 at 15:35

1 Answers1

0

In the MCVE you have posted, the struct Object contains a reference to Holded:

struct Object<'a> {
    holded: &'a Holded,
}

In the function work() you return an Object (optionally):

fn work(holder: &Holder) -> Option<Object> {

You acquire Holded from a function which returns it by value:

impl Holder {
    pub fn get( &self ) -> [Holded; 2] {
        [Holded { value: 0 }, Holded { value: 1 }]
    }
}

Now this will never work. If you return a reference to Holded, the Holded you reference to, must be stored somewhere. This means either as an input, or as an output of the function work().

I rewrote your example to include Holded inside Holder. That is one way to solve this. But I am not sure this would apply to your original problem.

struct Holded {
    value: u8,
}

struct Holder{
    value: [Holded; 2],
}

impl Holder {
    pub fn new() -> Holder {
        Holder {value: [Holded { value: 0 }, Holded { value: 1 }] } 
    }

    pub fn get( &self ) -> &[Holded; 2] {
        &self.value
    }
}

struct Object<'a> {
    holded: &'a Holded,
}

fn main() {
    let holder = Holder::new();

    let obj = work(&holder).unwrap();
    println!("{}", obj.holded.value);

    let obj = work2(&holder).unwrap();
    println!("{}", obj.holded.value);
}

fn work(holder: &Holder) -> Option<Object> {
    let obj: Object;
    let array = holder.get();

    for h in array.into_iter() {
        if h.value == 1u8 {
            obj = Object { holded: h };
            return Some(obj);
        }
    }

    None
}

fn work2(holder: &Holder) -> Option<Object> {
    holder.get()
        .iter()
        .filter(|h| h.value == 1u8)
        .map(|h| Object { holded: h })
        .next()
}

You notice I also added a different way to implement the work() function (work2()).

wimh
  • 15,072
  • 6
  • 47
  • 98