Конфликт времени жизни при использовании ссылки, возвращающей предикат (реализация «split at mut» с предикатом) - PullRequest
0 голосов
/ 21 апреля 2020

Есть ли способ назначить здесь времена жизни, чтобы такая функция могла быть реализована даже для предикатов, возвращающих ссылки?

fn group_by_into_slices_mut<'a, T, F, K>(data: &'a mut [T], key: F, res: &mut Vec<&'a mut [T]>)
where
    K: PartialEq,
    F: Fn(&T) -> K + 'static,
{
    let mut data = data;
    while !data.is_empty() {
        let j = find_j(&data, &key);
        let (s1, s2) = data.split_at_mut(j);
        res.push(s1);
        data = s2;
    }
}

fn find_j<'a, T, F, K>(data: &'a [T], key: &F) -> usize
where
    K: PartialEq,
    F: Fn(&T) -> K + 'static,
{
    let current_key = key(&data[0]);
    for i in 1..data.len() {
        if current_key != key(&data[i]) {
            return i;
        }
    }
    data.len()
}


struct Struct {
    key: String,
}

fn main() {
    let v = vec![Struct { key: "abc".to_string() }];
    let res = vec![];
    group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
}
  --> src/main.rs:37:42
   |
37 |     group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
   |                                          ^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 37:38...
  --> src/main.rs:37:38
   |
37 |     group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
   |                                      ^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:37:42
   |
37 |     group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
   |                                          ^^^^^^
note: but, the lifetime must be valid for the expression at 37:5...
  --> src/main.rs:37:5
   |
37 |     group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so type `for<'a, 'r> fn(&'a mut [Struct], [closure@src/main.rs:37:38: 37:48], &'r mut std::vec::Vec<&'a mut [Struct]>) {group_by_into_slices_mut::<Struct, [closure@src/main.rs:37:38: 37:48], &std::string::String>}` of expression is valid during the expression
  --> src/main.rs:37:5
   |
37 |     group_by_into_slices_mut(&mut v, |e| &e.key, &mut res);
   |     ^^^^^^^^^^^^^^^^^^^^^^^^

Я не уверен, почему это не работает. Я пытался явно добавить несколько жизней, в том числе границы черт высшего ранга, но безуспешно.

Детская площадка:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1663e12bf67838dd0d1440f759a72b4e

1 Ответ

0 голосов
/ 21 апреля 2020

Решение 1:

Я не думаю, что это возможно без сохранения "abc" как &'static str, как того требуют ваши текущие границы черт. Если вы можете изменить объект Struct на:

struct Struct<'a> {
    key: &'a str
}

fn main() {
    let _ = Struct { key: "abc" }; //never convert "abc" to an owned type
}

... и передать закрытие как |e| e.key вместо |e| &e.key, тогда ваш код скомпилируется нормально.

Реализация функции не меняется, и предикат по-прежнему возвращает ссылку, но теперь эта ссылка существует для 'static. |e| &e.key замыкание не будет работать, поскольку возвращаемая ссылка может существовать только для тела замыкания.

Решение 2:

Удалите границы 'static в обоих F черты и измените закрытие на |e| e.key.clone(), но я предполагаю, что это не то, что вы ищете, потому что вы больше не будете возвращать ссылку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...