Как добавить пожизненный аргумент к закрытию, не возвращая ссылку - PullRequest
0 голосов
/ 28 апреля 2019

Предположим, у вас есть функция, возвращающая замыкание, которое работает со ссылкой.Несомненно, объект за ссылкой должен жить как минимум до тех пор, пока вызывается замыкание.

Вот очень простой пример, демонстрирующий проблему.

fn get_cloned<'a>(obj: &'a MyStruct) -> impl Fn() -> MyStruct {
    || {obj.clone()}
}

Компилятор утверждает, что возвращаемое замыкание имеет время жизни static :

не может вывести соответствующее время жизни
... но это заимствование...rustc
main.rs (60, 56): этот тип возвращаемого значения оценивается как 'static время жизни ...
main.rs (61, 5): ... но это заимствование ...

Как мне сказать компилятору, что я использую только результат функции (замыкание), пока ссылка действительна?

Спасибо!

[Редактировать]

Вам нужна фиктивная структура, которая содержит ссылку и закрытие?

struct Dummy<'a>{
  reference: &'a MyStruct,
  closure: Fn() -> MyStruct
}

?

Предположим, что клонированиеочень дорого, и закрытие никогда не может быть названо.-> ленивая оценка обязательна.

1 Ответ

1 голос
/ 28 апреля 2019

Компилятор скажет вам, что делать:

error: cannot infer an appropriate lifetime
 --> src/lib.rs:2:9
  |
1 | fn get_cloned<'a>(obj: &'a MyStruct) -> impl Fn() -> MyStruct {
  |                                         --------------------- this return type evaluates to the `'static` lifetime...
2 |         || {obj.clone()}
  |         ^^^^^^^^^^^^^^^^ ...but this borrow...
  |
note: ...can't outlive the lifetime 'a as defined on the function body at 1:15
 --> src/lib.rs:1:15
  |
1 | fn get_cloned<'a>(obj: &'a MyStruct) -> impl Fn() -> MyStruct {
  |               ^^
help: you can add a constraint to the return type to make it last less than `'static` and match the lifetime 'a as defined on the function body at 1:15
  |
1 | fn get_cloned<'a>(obj: &'a MyStruct) -> impl Fn() -> MyStruct + 'a {
  |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^

Вам необходимо добавить + 'a в тип возврата. Затем компилятор сообщит вам, что вы пропустили move, но после исправления этого ваш код работает :

fn get_cloned<'a>(obj: &'a MyStruct) -> impl Fn() -> MyStruct + 'a {
    || {obj.clone()}
}
...