1

I have a data structure consisting of 3 levels of collections which I want to flatten:

use std::collections::HashMap;

struct Model {
    fields: HashMap<String, Vec<Field>>,
}

struct Field {
    field_type: String,
    info: Vec<FieldInfo>,
}

struct FieldInfo {
    pub info: String,
    pub value: f64,
}

fn do_action(model: &Model) {
    let _flattened: Vec<&dyn std::marker::Sync> = (&model.fields)
        .into_iter()
        .flat_map(|fields| {
            let v: Vec<&dyn std::marker::Sync> = fields
                .1
                .iter()
                .flat_map(|field| {
                    let v: Vec<&dyn std::marker::Sync> = field
                        .info
                        .iter()
                        .flat_map(|field_info| {
                            let vec: Vec<&dyn std::marker::Sync> = vec![
                                &fields.0,
                                &field.field_type,
                                &field_info.info,
                                &field_info.value,
                            ];
                            vec
                        })
                        .collect();
                    v
                })
                .collect();
            v
        })
        .collect();
}

Playground

I got the following error message when trying to compile the code:

error[E0373]: closure may outlive the current function, but it borrows `fields`, which is owned by the current function
  --> src/lib.rs:24:27
   |
24 |                 .flat_map(|field| {
   |                           ^^^^^^^ may outlive borrowed value `fields`
...
30 |                                 &fields.0,
   |                                  ------ `fields` is borrowed here
   |
note: closure is returned here
  --> src/lib.rs:41:13
   |
41 |             v
   |             ^
help: to force the closure to take ownership of `fields` (and any other referenced variables), use the `move` keyword
   |
24 |                 .flat_map(move |field| {
   |                           ^^^^^^^^^^^^

The suggested solution with move closure does not work in my case. What would be a workaround?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
St.Antario
  • 26,175
  • 41
  • 130
  • 318
  • It looks like your question might be answered by the answers of [Why do I need to collect into a vector when using `flat_map`?](https://stackoverflow.com/q/57902478/155423); [Lifetime of variable in map/flat_map in Rust](https://stackoverflow.com/q/36967681/155423); [Rust error “cannot infer an appropriate lifetime for borrow expression” when attempting to mutate state inside a closure returning an Iterator](https://stackoverflow.com/q/59164687/155423); etc.. If not, please **[edit]** your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Aug 19 '20 at 15:24
  • 1
    `model.fields.iter().flat_map(|(name, fields)| ...` – Shepmaster Aug 19 '20 at 15:29
  • It's may be more a dupe of [How to use struct self in member method closure](https://stackoverflow.com/a/48722688/155423) – Shepmaster Aug 19 '20 at 15:31
  • @Shepmaster Following your hint I removed borrowing from the `&fields.0` and replaced it with `fields.0` and then it compiles without any error [Playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=77c5932d14fed9cf43ab8e045e875530). Can you give a hint why? – St.Antario Aug 19 '20 at 15:34

0 Answers0