У вас есть две Key
в вашей подписи, которые должны быть связаны, но вы не связываете их. Самое простое решение - дать им одинаковое время жизни:
fn get<'m, 'k>(map: &'m HashMap<Key<'k>, usize>, key: &Key<'k>) -> Option<&'m usize>
// ^^ ^^^^ ^^^^
Ваш оригинальный код ближе к этому после пожизненного отбора:
fn get<'m, 'k, 'kr, 'x>(map: &'m HashMap<Key<'x>, usize>, key: &'k Key<'kr>) -> Option<&'m usize>
Но я собираюсь использовать эту форму вместо:
fn get<'m, 'k1, 'k2>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize>
HashMap::get
имеет нетривиальную подпись:
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where
K: Borrow<Q>,
Q: Hash + Eq,
Например, это позволяет вам искать в HashMap<String, V>
с &String
или &str
.
Давайте перенесем это в наш код и выполним некоторую замену универсальных типов:
fn get<'m, 'k1, 'k2>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize> {
fake_get(map, key)
}
fn fake_get<'m, 'k1, 'k2>(_: &'m HashMap<Key<'k1>, usize>, k: &Key<'k2>) -> Option<&'m usize>
where
Key<'k1>: Borrow<Key<'k2>>,
Key<'k2>: Hash + Eq,
{
None
}
Мы можем удалить границу Hash + Eq
, потому что знаем, что это тривиально. Мы также можем удалить оболочку HashMap
:
fn get<'m, 'k1, 'k2>(map: &'m Key<'k1>, key: &Key<'k2>) -> Option<&'m usize> {
fake_get(map, key)
}
fn fake_get<'m, 'k1, 'k2>(_m: &'m Key<'k1>, _k: &Key<'k2>) -> Option<&'m usize>
where
Key<'k1>: Borrow<Key<'k2>>,
{
None
}
Ошибка сводится к границе Borrow
- можем ли мы позаимствовать Key
с произвольным временем жизни у другого Key
с другим произвольным временем жизни?
Единственный способ для этого быть правдой, если известно, что одна жизнь переживет другую. Это можно выразить:
fn get<'m, 'k1, 'k2: 'k1>(map: &'m HashMap<Key<'k1>, usize>, key: &Key<'k2>) -> Option<&'m usize>
but data from `key` is returned here
Не думаю, что в этом случае это большое сообщение об ошибке. Я думаю, что вполне вероятно, что это редкий случай, который не был исправлен с этим сообщением об ошибке. Хорошая новость в том, что теперь у вас есть небольшая копия, чтобы сообщить о проблеме:
use std::borrow::Borrow;
struct Key<'a>(&'a str);
fn get<'a, 'k1, 'k2>(k1: &'a Key<'k1>, k2: &Key<'k2>) -> &'a i32 {
fake_get(k1, k2)
}
fn fake_get<'a, 'k1, 'k2>(_k1: &'a Key<'k1>, _k2: &Key<'k2>) -> &'a i32
where
Key<'k1>: Borrow<Key<'k2>>,
{
&42
}
fn main() {}
Смотри также: