gpt4 book ai didi

rust - 混淆了这个参数和返回类型声明了不同的生命周期但是这里返回了 `key`的数据

转载 作者:行者123 更新时间:2023-11-29 08:06:01 25 4
gpt4 key购买 nike

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 的生命周期与返回类型的生命周期不同,但我不明白“data from key 是怎样的返回此处”...我看到 来自 map 的数据使用 key 返回,以及......好吧,只是在返回值后不再需要的 key 。

IMO,get 应该只对传入的任何 'k'kr 有效。返回值生命周期应该与 map 的生命周期。这就是我想表达的意思,但显然我的想法在某处是错误的..

最佳答案

你有两个 Key s 在您的签名中应该是相关的,但您没有将它们相关联。最简单的解决方案是为它们提供相同的生命周期:

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绑定(bind),因为我们知道这是微不足道的。我们还可以删除 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 trait bound——我们可以借一个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() {}

另见:

关于rust - 混淆了这个参数和返回类型声明了不同的生命周期但是这里返回了 `key`的数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51048144/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com