将可变引用与自身映射时冲突的生命周期要求
Conflicting lifetime requirements when mapping mutable references with self
我正在尝试编写一种方法,当给定 HashMap 的键数组时,将 return 包含键对应值的可变引用的 Vec。
代码如下:
struct Foo {
bar: HashMap<u32, String>,
}
impl Foo {
pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
keys.iter()
.filter(|&x| self.bar.contains_key(x))
.map(|x| self.bar.get_mut(x).unwrap())
.collect::<_>()
}
}
这会导致生命周期冲突错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:11:31
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 11:18...
--> src/main.rs:11:18
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
--> src/main.rs:11:22
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
--> src/main.rs:8:5
|
8 | / pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
9 | | keys.iter()
10 | | .filter(|&x| self.bar.contains_key(x))
11 | | .map(|x| self.bar.get_mut(x).unwrap())
12 | | .collect::<_>()
13 | | }
| |_____^
note: ...so that the expression is assignable
--> src/main.rs:9:9
|
9 | / keys.iter()
10 | | .filter(|&x| self.bar.contains_key(x))
11 | | .map(|x| self.bar.get_mut(x).unwrap())
12 | | .collect::<_>()
| |___________________________^
= note: expected `std::vec::Vec<&mut std::string::String>`
found `std::vec::Vec<&mut std::string::String>`
使该函数的不可变版本按预期工作,但我不明白为什么:
pub fn lookup(&self, keys: &[u32]) -> Vec<&String> {
keys.iter()
.filter(|&x| self.bar.contains_key(x))
.map(|x| self.bar.get(x).unwrap())
.collect::<_>()
}
我假设这是一个 "fighting the borrow checker" 问题,可能是由于 self.bar 被多次可变借用。我将如何解决这个问题?
下面的工作是使用提供的键过滤值,而不是将键映射到它们的值。正如 SCappella 正确指出的那样,如果提供了重复的有效密钥,问题中的代码将导致未定义的行为。
工作代码:
pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
self.bar.iter_mut().filter_map(|(k, v)| {
if keys.contains(k) {
Some(v)
} else {
None
}
}).collect::<_>()
}
我正在尝试编写一种方法,当给定 HashMap 的键数组时,将 return 包含键对应值的可变引用的 Vec。
代码如下:
struct Foo {
bar: HashMap<u32, String>,
}
impl Foo {
pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
keys.iter()
.filter(|&x| self.bar.contains_key(x))
.map(|x| self.bar.get_mut(x).unwrap())
.collect::<_>()
}
}
这会导致生命周期冲突错误:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:11:31
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'_` as defined on the body at 11:18...
--> src/main.rs:11:18
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that closure can access `self`
--> src/main.rs:11:22
|
11 | .map(|x| self.bar.get_mut(x).unwrap())
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the method body at 8:5...
--> src/main.rs:8:5
|
8 | / pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
9 | | keys.iter()
10 | | .filter(|&x| self.bar.contains_key(x))
11 | | .map(|x| self.bar.get_mut(x).unwrap())
12 | | .collect::<_>()
13 | | }
| |_____^
note: ...so that the expression is assignable
--> src/main.rs:9:9
|
9 | / keys.iter()
10 | | .filter(|&x| self.bar.contains_key(x))
11 | | .map(|x| self.bar.get_mut(x).unwrap())
12 | | .collect::<_>()
| |___________________________^
= note: expected `std::vec::Vec<&mut std::string::String>`
found `std::vec::Vec<&mut std::string::String>`
使该函数的不可变版本按预期工作,但我不明白为什么:
pub fn lookup(&self, keys: &[u32]) -> Vec<&String> {
keys.iter()
.filter(|&x| self.bar.contains_key(x))
.map(|x| self.bar.get(x).unwrap())
.collect::<_>()
}
我假设这是一个 "fighting the borrow checker" 问题,可能是由于 self.bar 被多次可变借用。我将如何解决这个问题?
下面的工作是使用提供的键过滤值,而不是将键映射到它们的值。正如 SCappella 正确指出的那样,如果提供了重复的有效密钥,问题中的代码将导致未定义的行为。
工作代码:
pub fn lookup(&mut self, keys: &[u32]) -> Vec<&mut String> {
self.bar.iter_mut().filter_map(|(k, v)| {
if keys.contains(k) {
Some(v)
} else {
None
}
}).collect::<_>()
}