对此参数感到困惑,返回类型声明了不同的生存期,但此处返回了来自"key"的数据


use std::collections::HashMap;
#[derive(Eq, Hash, PartialEq)]
struct Key<'a> {
key: &'a str,
}
fn get<'m, 'k, 'kr>(map: &'m HashMap<Key, usize>, key: &'k Key<'kr>) -> Option<&'m usize> {
map.get(key)
}
fn main() {
let map: HashMap<Key, usize> = HashMap::new();
get(&map, &Key { key: "foo" });
}

给我以下错误:

error[E0623]: lifetime mismatch
--> src/main.rs:9:5
|
8 | fn get<'m, 'k, 'kr>(map: &'m HashMap<Key, usize>, key: &'k Key<'kr>) -> Option<&'m usize> {
|                                                            --------     -----------------
|                                                            |
|                                                            this parameter and the return type are declared with different lifetimes...
9 |     map.get(key)
|     ^^^^^^^^^^^^ ...but data from `key` is returned here

是的,key的生存期与返回类型的生存期不同,但我看不到"此处返回来自key的数据"......我看到使用密钥返回map的数据为..好吧,只是一个返回值后不再需要的键。

IMO,get应该适用于任何'k'kr传入。返回值生存期应与map生存期相同。这就是我试图表达的,但显然我的想法在某处是错误的。

您的签名中有两个应该相关的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, 

例如,这允许您在具有&String&strHashMap<String, V>中查找。

让我们将其移植到我们的代码中,并对泛型类型进行一些替换:

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() {}

另请参阅:

  • 如何使用两个键实现哈希图?

最新更新