Rust lifetime in closure environment


#1

I want implement graph structure on Rust. For this goal, i write simple abstractions:

pub struct Graph <'a> {
    pub nodes: Vec<Node>,
    pub edges: Vec<Edge<'a>>
}
#[derive(Debug)]
pub struct Node {
    pub id: String,
    pub label: String
}
pub struct Edge<'a> {
    pub source: &'a Node,
    pub target: &'a Node
}

Graph contains vectors of Nodes and Edges. Every Edge have a ref on Node in same Graph. I’m new in Rust so I don’t know it’s a possible write something like this.
Anyway I tried write a static method, whos build new Graph instance from Json Graph representation:

impl <'a> Graph <'a> {
    pub fn from_json(json: & String) -> Graph {
        if let json::JsonValue::Object(deserialized) = json::parse(json.as_ref()).unwrap() {
            let nodes : Vec<Node> = deserialized.get("nodes").unwrap().members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        return Node {
                            id: val.get("id").unwrap().to_string(),
                            label: val.get("label").unwrap().to_string()
                        };
                    }
                    panic!("Invalid structure of json graph body.")
            }).collect::<Vec<Node>>();
            let edges : Vec<Edge> = deserialized.get("edges").unwrap().members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        let source = (*nodes).iter().find(|&v| v.id ==  val.get("source").unwrap().to_string()).unwrap();
                        let target = (*nodes).iter().find(|&v| v.id ==  val.get("target").unwrap().to_string()).unwrap();
                        return Edge {
                            source,
                            target
                        };
                    }
                    panic!("Invalid structure of json graph body.")
                }).collect::<Vec<Edge>>();
            return Graph {
                nodes,
                edges
            }
        }
        panic!("Incorrect struct of json contains!");
    }
}

Problem in this part:

let edges : Vec<Edge> = deserialized.get("edges").unwrap().members()
                .map(|v| {
                    if let json::JsonValue::Object(ref val) = *v {
                        let source = (*nodes).iter().find(|&v| v.id ==  val.get("source").unwrap().to_string()).unwrap();
                        let target = (*nodes).iter().find(|&v| v.id ==  val.get("target").unwrap().to_string()).unwrap();
                        return Edge {
                            source,
                            target
                        };
                    }
                    panic!("Invalid structure of json graph body.")
                }).collect::<Vec<Edge>>();

When i try compile, get this error:

error[E0373]: closure may outlive the current function, but it borrows `nodes`, which is owned by the current function
  --> src/graph.rs:30:22
   |
30 |                 .map(|v| {
   |                      ^^^ may outlive borrowed value `nodes`
31 |                     if let json::JsonValue::Object(ref val) = *v {
32 |                         let source = (*nodes).iter().find(|&v| v.id ==  val.get("source").unwrap().to_string()).unwrap();
   |                                        ----- `nodes` is borrowed here
   |
help: to force the closure to take ownership of `nodes` (and any other referenced variables), use the `move` keyword
   |
30 |                 .map(move |v| {
   |                      ^^^^^^^^

error: aborting due to previous error

Possible solution of this problem is add move before closure params. But I need nodes vector for build Graph instance. Can you please explain me what I do wrong?


#2

This was cross-posted to Stack Overflow.