Dolphin
Dolphin

Reputation: 39095

borrowed value does not live long enough when write an generic object mapping function in rust

I want to mapping object using this code snippnet in rust:

fn map_entity_vec<T: 'static,E>(sources:Vec<T>) -> Vec<E> where E: From<&'static T>, E: Clone {
    if sources.is_empty() {
        return Vec::new();
    }
    let mut responses= Vec::new();
    for source in sources {
        let template_response = E::from(&source);
        responses.push(template_response.clone());
    }
    return responses;
}

the compiler shows eror:

error[E0597]: `source` does not live long enough
  --> src/main.rs:13:41
   |
13 |         let template_response = E::from(&source);
   |                                 --------^^^^^^^-
   |                                 |       |
   |                                 |       borrowed value does not live long enough
   |                                 argument requires that `source` is borrowed for `'static`
14 |         responses.push(template_response.clone());
15 |     }
   |     - `source` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

what should I do to avoid this problem? I have tried to remove the lifetime static but the compiler tell me it should be added. I am still not figure out what should I do to make the object mapping function work.

Upvotes: 0

Views: 36

Answers (1)

Dogbert
Dogbert

Reputation: 222428

You need to use Higher Rank Trait Bounds here to satisfy the compiler, not make everything 'static:

fn map_entity_vec<T, E>(sources: Vec<T>) -> Vec<E>
where
    for<'a> E: From<&'a T>,
    E: Clone,
{
    if sources.is_empty() {
        return Vec::new();
    }
    let mut responses = Vec::new();
    for source in sources {
        let template_response = E::from(&source);
        responses.push(template_response.clone());
    }
    return responses;
}

This can also be simplified using the iterator functions to:

fn map_entity_vec_2<T, E>(sources: Vec<T>) -> Vec<E>
where
    for<'a> E: From<&'a T> + Clone,
{
    sources.iter().map(E::from).collect()
}

Playground

Edit: You also don't need E: Clone since E::from returns E not &E:

fn map_entity_vec_3<T, E>(sources: Vec<T>) -> Vec<E>
where
    for<'a> E: From<&'a T>,
{
    sources.iter().map(E::from).collect()
}

Upvotes: 1

Related Questions