Noob в ржавчине здесь, пытается реализовать общую функцию повтора и пытается решить, как устранить ошибку времени жизни:
async fn retry<T, E, Fut, F>(mut f: F, client: &Client, max_retries: i32) -> Result<T, E>
where
Fut: Future<Output = Result<T, E>>,
F: FnMut(&Client) -> Fut,
{
let mut count = 0;
loop {
let result = f(client).await;
if result.is_ok() {
break result;
} else {
if count > max_retries {
break result;
}
count += 1;
}
}
}
и ошибка
| |_________________^ returning this value requires that `'1` must outlive `'2`
error[E0515]: cannot return value referencing temporary value
Как я вызываю метод:
let lambda = &mut move |client: &Client| {
client
.download_object(
&GetObjectRequest {
bucket: some_bucket,
object: some_object,
..Default::default()
},
&Range::default(),
)
};
retry(lambda, &self.client, 5).await
Я не могу понять, что возвращаемое значение f(client).await
должно пережить что именно?
Полная ошибка:
error[E0621]: explicit lifetime required in the type of `client`
--> src/main.rs:35:22
|
28 | async fn retry<'a, T, E, Fut, F>(mut f: F, client: &Client, max_retries: i32) -> Result<T, E>
| ------- help: add explicit lifetime `'a` to the type of `client`: `&'a Client`
...
35 | let result = f(client).await;
| ^^^^^^^^^ lifetime `'a` required
error: lifetime may not live long enough
--> src/main.rs:68:13
|
67 | let lambda = &mut move |client: &Client| {
| - - return type of closure `impl Future<Output = Result<Vec<u8>, google_cloud_storage::http::Error>>` contains a lifetime `'2`
| |
| let's call the lifetime of this reference `'1`
68 | / client
69 | | .download_object(
70 | | &GetObjectRequest {
71 | | bucket: some_bucket,
... |
75 | | &Range::default(),
76 | | )
| |_________________^ returning this value requires that `'1` must outlive `'2`
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:68:13
|
68 | / client
69 | | .download_object(
70 | | &GetObjectRequest {
| | ______________________-
71 | || bucket: some_bucket,
72 | || object: some_object,
73 | || ..Default::default()
74 | || },
| ||_____________________- temporary value created here
75 | | &Range::default(),
76 | | )
| |__________________^ returns a value referencing data owned by the current function
error[E0515]: cannot return value referencing temporary value
--> src/main.rs:68:13
|
68 | / client
69 | | .download_object(
70 | | &GetObjectRequest {
71 | | bucket: some_bucket,
... |
75 | | &Range::default(),
| | ---------------- temporary value created here
76 | | )
| |_________________^ returns a value referencing data owned by the current function
Где остальные ошибки? Пожалуйста, всегда публикуйте полное сообщение об ошибке с помощью cargo build
@cafce25 добавил полную ошибку в описание
Я не знаю, что такое Client
, поэтому я могу только догадываться, но мое обоснованное предположение состоит в том, что будущее download_object()
возвращает заимствование у клиента, но ваша сигнатура функции retry()
не позволяет этого.
Поскольку вы передаете Client
функции, самый простой способ — аннотировать время жизни:
async fn retry<'a, T, E, Fut, F>(mut f: F, client: &'a Client, max_retries: i32) -> Result<T, E>
where
Fut: Future<Output = Result<T, E>>,
F: FnMut(&'a Client) -> Fut,
{
// ...
}
Если бы client
генерировался внутри функции, это было бы сложнее. См. Вызов универсальной асинхронной функции с (изменяемым) заимствованным аргументом.
спасибо, попробовал аннотировать на всю жизнь, и проблема не устранена. Клиент - это клиент из этого crate
- docs.rs/google-cloud-storage/latest/google_cloud_storage/client/…
@akram Судя по ошибке в вопросе, вы не использовали &'a Client
.
правильно, поэтому &'a Client
решит одну пожизненную проблему, а их на одну больше, чем осталось: ``` &GetObjectRequest { | | ______________________- 71 | || ведро: some_bucket, 72 | || объект: некоторый_объект, 73 | || ..Default::default() 74 | || }, | ||_____________________- здесь создано временное значение ``` ошибка [E0515]: невозможно вернуть значение, ссылающееся на временное значение
мое понимание второй проблемы cannot return value referencing temporary value
таково, что если бы методы не были асинхронными, то второй ошибки не произошло бы, потому что она возвращает Future, возможно, что временные значения могут выйти из области действия до завершения Future, что приведет к оборванной ссылке и undefined поведение? любые подсказки, как решить второй тоже.
@akram Теперь это другой вопрос, и я также думаю, что у него нет решения.
спасибо за его ясный, более глупый вопрос, связанный с этим, если метод повторной попытки не принимал клиента в качестве аргумента, а только closure
/ mut f: FnMut() -> Fut
, как в этом случае будет решена проблема с продолжительностью жизни?
@akram На это есть ответ в вопросе, который я связал.
Я думаю, что это для сценария, когда клиент генерируется внутри функции, я имел в виду сценарий, когда клиент не генерируется внутри функции, вот пример, иллюстрирующий то же самое - play.rust-lang.org/…
@akram Ну, если он не создается внутри функции и не передается ей, то где он создается?
он создается вызываемым пользователем прямо перед созданием замыкания. пусть клиент = Клиент: новый(); пусть лямбда = двигаться || { client.download_object(&request, &range)};
@akram Я не верю, что это решаемо. Вам придется использовать пользовательский трейт, а не замыкание.
Что такое
Client
?