#rust #lifetime #borrow-checker
Вопрос:
Этот простой фрагмент кода сводит меня с ума:
pub fn load_any<'a, T, K>(amp;self, key: K) -> Result<Option<T>, kv::Error> where
T: 'a Persistent Debug Serialize for<'de> Deserialize<'de>,
K: 'a kv::Key<'a>,
{
let bucket = self.store.bucket::<K,kv::Bincode<T>>(Some(T::bucket_name()))?;
bucket
.get(key)?.unwrap();
Ok(None)
}
ошибка в том, что:
--> src/persist.rs:47:9
|
42 | pub fn load_any<'a, T, K>(amp;self, key: K) -> Result<Option<T>, kv::Error> where
| -- lifetime `'a` defined here
...
47 | bucket
| -^^^^^
| |
| _________borrowed value does not live long enough
| |
48 | | .get(key)?.unwrap();
| |_____________________- argument requires that `bucket` is borrowed for `'a`
...
51 | }
| - `bucket` dropped here while still borrowed
Я перепробовал почти все (включая клонирование key
и путаницу с жизнями), но я не могу понять, как заставить это работать.
Реальный код был другим (я, очевидно, делаю что-то со значением, возвращаемым get), но ошибка та же.
Результат Get не возвращается, и ведро используется только для вызова get()
.
Компилятор Rust жалуется, что bucket
он отброшен, хотя все еще заимствован, но ничто его не заимствует.
Тот же код отлично работает, заменяя универсальный K
на типизированный var:
pub fn load_str<'a, T>(amp;self, key: amp;str) -> Result<Option<T>, kv::Error> where
T: 'a Persistent Debug Serialize for<'de> Deserialize<'de>,
{
let bucket = self.store.bucket::<amp;str,kv::Bincode<T>>(Some(T::bucket_name()))?;
bucket
.get(key)?.unwrap();
Ok(None)
// This code works perfectly
}
Код использует библиотеку kv.
Комментарии:
1. Можете ли вы превратить свое решение в ответ? Таким образом, он будет соответствовать структуре вопросов и ответов этого сайта и будет легче читать/голосовать/все
2.
Bucket::get
принимает толькоKey
s, привязанные к его сроку службы, но поскольку'a
производные вне функции viakey
всегда будут жить дольше, чемbucket
определено внутри функции, компилятор пытается отклониться назад, пытаясь заставить ее работать. У меня нет решения, так как обходной путь часто заключается вfor<'a>
синтаксисе.3. Точно:
for<'a>
это единственное решение. Проблема в самой библиотеке kv: я открыл PR (см. Мой ответ).
Ответ №1:
Я изменил код следующим образом:
pub fn load_any<T, K>(amp;self, key: K) -> Result<Option<T>, kv::Error> where
T: Persistent Debug Serialize for<'de> Deserialize<'de>,
K: for<'k> kv::Key<'k>,
{
let bucket = self.store.bucket::<K,kv::Bincode<T>>(Some(T::bucket_name()))?;
bucket
.get(key)?.unwrap();
Ok(None)
}
Я использовал выражение «на всю жизнь», используемое даже в T
определении.
Я предполагаю, что это заставляет компиляцию «игнорировать» время жизни Key
, которое не требуется, потому что оно не заимствовано.
Но проблема сейчас заключается в использовании метода:
error: implementation of `kv::types::Key` is not general enough
--> src/main.webapp.rs:146:30
|
146 | println!("{:?}", persist.load::<amp;str,DisyStat>("qqq"));
| ^^^^ implementation of `kv::types::Key` is not general enough
|
::: /opt/rust/registry/src/github.com-1ecc6299db9ec823/kv-0.22.0/src/types.rs:7:1
|
7 | / pub trait Key<'a>: Sized AsRef<[u8]> {
8 | | /// Convert from Raw
9 | | fn from_raw_key(r: amp;'a Raw) -> Result<Self, Error>;
10 | |
... |
14 | | }
15 | | }
| |_- trait `kv::types::Key` defined here
|
= note: `kv::types::Key<'0>` would have to be implemented for the type `amp;str`, for any lifetime `'0`...
= note: ...but `kv::types::Key<'1>` is actually implemented for the type `amp;'1 str`, for some specific lifetime `'1`
Оказалось, что проблема заключается в том, что библиотека kv применяет 'a
время жизни к себе для некоторых методов.
Я исправил это и открыл PR: Удалил всю жизнь из get() и содержит() методы