gpt4 book ai didi

rust - 使用 filter_map 的生命周期错误

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

我试图在 Rust 中将 Iterator 的 filter_map 函数与 HashMap 一起使用,但我无法编译它。假设我有一个 HashMap 和一个键列表。对于每个键,如果映射包含键,我会改变映射中的相应值。例如,假设值是 i32 类型,我想增加适当的值。

use std::collections::HashMap;

fn increment(map: &mut HashMap<i32, i32>, keys: &[i32]) {
for value in keys.iter().filter_map(|index| map.get_mut(index)) {
*value += 1;
}
}

fn main() {
let mut map = HashMap::new();
map.insert(1,2);
map.insert(4,5);
increment(&mut map, &[0, 1, 2]);
assert!(*map.get(&1).unwrap() == 3);
assert!(*map.get(&4).unwrap() == 5);
}

这段代码给我一个与生命周期相关的错误:

<anon>:4:57: 4:71 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements
<anon>:4 for value in keys.iter().filter_map(|index| map.get_mut(index)) {
^~~~~~~~~~~~~~
<anon>:4:9: 6:10 note: in this expansion of for loop expansion
<anon>:4:9: 6:10 note: first, the lifetime cannot outlive the call at 4:8...
<anon>:4 for value in keys.iter().filter_map(|index| map.get_mut(index)) {
<anon>:5 *value += 1;
<anon>:6 }
<anon>:4:9: 6:10 note: in this expansion of for loop expansion
<anon>:4:9: 6:10 note: ...so that argument is valid for the call
<anon>:4 for value in keys.iter().filter_map(|index| map.get_mut(index)) {
<anon>:5 *value += 1;
<anon>:6 }
<anon>:4:9: 6:10 note: in this expansion of for loop expansion
<anon>:4:53: 4:71 note: but, the lifetime must be valid for the method call at 4:52...
<anon>:4 for value in keys.iter().filter_map(|index| map.get_mut(index)) {
^~~~~~~~~~~~~~~~~~
<anon>:4:9: 6:10 note: in this expansion of for loop expansion
<anon>:4:53: 4:56 note: ...so that method receiver is valid for the method call
<anon>:4 for value in keys.iter().filter_map(|index| map.get_mut(index)) {
^~~
<anon>:4:9: 6:10 note: in this expansion of for loop expansion
error: aborting due to previous error

为什么我会收到此错误,使用惯用 Rust 处理这种情况的最佳方法是什么?

最佳答案

I've desugared your original code 以获得更精确的错误。我最终在以下方法中遇到错误:

impl<'a, 'b> FnMut<(&'b i32,)> for MyClosure<'a> {
extern "rust-call"
fn call_mut(&mut self, (index,): (&'b i32,)) -> Option<&'a mut i32> {
self.map.get_mut(index)
}
}

错误是:

<anon>:21:18: 21:32 error: cannot infer an appropriate lifetime for autoref due to conflicting requirements [E0495]
<anon>:21 self.map.get_mut(index)
^~~~~~~~~~~~~~

通常,当您从函数返回可变引用时,它会绑定(bind)到参数的生命周期。返回的引用导致作为参数传递给函数的值仍然被认为是借用的,并且根据 Rust 的规则,在第一次借用超出范围之前,您不能对该值进行另一次借用。因此,该程序无法编译:

struct Foo {
x: i32
}

impl Foo {
fn x_mut(&mut self) -> &mut i32 { &mut self.x }
}

fn main() {
let mut foo = Foo { x: 0 };
let a = foo.x_mut();
foo.x_mut(); // error: cannot borrow `foo` as mutable more than once at a time
}

问题是您试图返回一个生命周期为 'a 的可变引用,但是那个生命周期并没有恰本地表达你实际上是从 MyClosure 借来的事实。 .因此,编译器不会考虑 MyClosure在调用之后借用并允许您再次调用闭包,这可能会返回一个与之前返回的相同的可变引用,从而导致可变引用的别名,这在安全 Rust 中是被禁止的。

为此,FnMut实现必须这样写:

impl<'a, 'b> FnMut<(&'b i32,)> for MyClosure<'a> {
extern "rust-call"
fn call_mut<'c>(&'c mut self, (index,): (&'b i32,)) -> Option<&'c mut i32> {
self.map.get_mut(index)
}
}

但这是无效的:

<anon>:19:5: 22:6 error: method `call_mut` has an incompatible type for trait:
expected bound lifetime parameter ,
found concrete lifetime [E0053]
<anon>:19 extern "rust-call"
<anon>:20 fn call_mut<'c>(&'c mut self, (index,): (&'b i32,)) -> Option<&'c mut i32> {
<anon>:21 self.map.get_mut(index)
<anon>:22 }

这与尝试编写流式迭代器时生成的错误相同。


† 实际上,这段脱糖代码对应于闭包 move |index| map.get_mut(index) .您的原始闭包将包含 &mut &mut HashMap<i32, i32>字段,而不是 &mut HashMap<i32, i32>字段。

关于rust - 使用 filter_map 的生命周期错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33727808/

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