1

I need to create a vector of references, but it seems like this is incredibly difficult in Rust. This is a simplified version of my current implementation:

struct Object {
    // stuff
}

fn f(o: Object) -> Object {
    // do stuff
    o
}

fn main() {
    let vector = vec![Object {}, Object {}];
    let mut objects: Vec<Object> = vec![];
    let mut object_refs: Vec<&Object> = vec![]; // <-- this is what I need

    for object in vector {
        objects.push(f(object));
    }
    for i in 0..objects.len() {
        object_refs.push(&objects[i]);
    }
}

Is there a better way to do this?

Here is a link to a rust playground: https://play.rust-lang.org/?gist=2755aa64d96e0632e47488ab10908979&version=stable&backtrace=0

UPDATE

Thank you for pointing me to that question. I had actually already consulted that post, and found that it did not exactly solve my problem.

Here is how I adapted each 'version' proposed in the top answer for that question:

let v2: Vec<&Object> = v.iter().map(|s| &f(s)).collect();
let v3: Vec<&Object> = v.iter().map(|s| f(s)).map(std::ops::Deref::deref).collect();
let v4: Vec<&Object> = v.iter().map(|s| f(s) as &Object).collect();
let v5: Vec<&Object> = v.iter().map(|s| &f(s)[..]).collect();
let v6: Vec<&Object> = v.iter().map(|s| { let s: &Object = &f(s); s }).collect();
let v7: Vec<&Object> = v.iter().map(|s| f(s).as_ref()).collect();
let v8: Vec<&str> = v.iter().map(|s| f(s)).map(AsRef::as_ref).collect();

Some of these versions are clearly intended exclusively for &String types but I've included them for the sake of completeness. You can run them in this rust playground, and verify that they all throw errors: https://play.rust-lang.org/?gist=cc3c8fb1f774f230ad07cdd708aed044&version=stable&backtrace=0

It may also be worth mentioning that the Object struct is actually a type imported from an external crate, so I cannot modify it in any way.

The fundamental problem is that the scope of f(s) is inside the iterator. If you use the closure |s| &f(s), then f(s) gets freed too soon:

error: borrowed value does not live long enough
  --> <anon>:22:49
   |
22 |     let v2: Vec<&Object> = v.iter().map(|s| &f(s)).collect();
   |                                              ---^
   |                                              |  |
   |                                              |  temporary value dropped here while still borrowed
   |                                              temporary value created here
 ...
29 | }
   | - temporary value needs to live until here

My original attempt involved storing the actual f(s) values at the top level in one array and then creating a second array with references to the first. It works, but it is very verbose and awkward. If you can point out a better way, I would appreciate it.

ethanabrooks
  • 747
  • 8
  • 19

0 Answers0