Конфликт требований времени жизни при сопоставлении изменяемых ссылок с self - PullRequest
0 голосов
/ 30 марта 2020

Я пытаюсь написать метод, который при получении массива ключей для HashMap вернет Ve c, содержащий изменяемые ссылки соответствующих значений ключей.

Вот код:

struct Foo {
    bar: HashMap<u32, String>,
}

impl Foo {
    pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
        keys.iter()
            .filter(|&x| self.bar.contains_key(x))
            .map(|x| self.bar.get_mut(x).unwrap())
            .collect::<_>()
    }
}

Это приводит к конфликтной ошибке времени жизни:

error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
  --> src/main.rs:11:31
   |
11 |             .map(|x| self.bar.get_mut(x).unwrap())
   |                               ^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 11:18...
  --> src/main.rs:11:18
   |
11 |             .map(|x| self.bar.get_mut(x).unwrap())
   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
  --> src/main.rs:11:22
   |
11 |             .map(|x| self.bar.get_mut(x).unwrap())
   |                      ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
  --> src/main.rs:8:5
   |
8  | /     pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
9  | |         keys.iter()
10 | |             .filter(|&x| self.bar.contains_key(x))
11 | |             .map(|x| self.bar.get_mut(x).unwrap())
12 | |             .collect::<_>()
13 | |     }
   | |_____^
note: ...so that the expression is assignable
  --> src/main.rs:9:9
   |
9  | /         keys.iter()
10 | |             .filter(|&x| self.bar.contains_key(x))
11 | |             .map(|x| self.bar.get_mut(x).unwrap())
12 | |             .collect::<_>()
   | |___________________________^
   = note: expected  `std::vec::Vec<&mut std::string::String>`
              found  `std::vec::Vec<&mut std::string::String>`

Создание неизменяемой версии функции работает, как задумано, хотя я не понимаю, почему:

pub fn lookup(&self, keys: &[u32]) -> Vec<&String> {
    keys.iter()
        .filter(|&x| self.bar.contains_key(x))
        .map(|x| self.bar.get(x).unwrap())
        .collect::<_>()
}

Я предполагаю, что это проблема "борьбы с заемщиком", возможно, из-за того, что self.bar заимствован несколько раз. Как мне go исправить это?

1 Ответ

1 голос
/ 30 марта 2020

Следующее работает путем фильтрации значений с использованием предоставленных ключей, а не путем сопоставления ключей с их значениями. Код в вопросе, как правильно сказал SCappella, привел бы к неопределенному поведению, если бы были предоставлены дубликаты действительных ключей.

Рабочий код:

pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
   self.bar.iter_mut().filter_map(|(k, v)| {
         if keys.contains(k) {
             Some(v)
         } else {
             None
         }
   }).collect::<_>()
}
...