我的代码中的匹配表达式出现问题,当包含防护时会发出警告。我相信这个警告与借用检查器使用的非词汇生命周期有关。我的函数要么返回对集合中某个项目的可变引用,要么返回整个集合的克隆。
#[derive(Debug, Clone)]
enum Value {
Int(i32),
List(Vec<Value>),
}
#[derive(Debug)]
struct Error(&'static str, Value);
fn main() {
let mut value = Value::List(vec![
Value::Int(1),
Value::Int(2),
Value::Int(34),
Value::Int(12),
]);
let y = index_list(&mut value, 2);
let _ = dbg!(y);
}
fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
match *value {
Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
Value::List(_) => Err(Error("index out of range", value.clone())),
_ => Err(Error("tried to index int", value.clone())),
}
}
它编译并运行,但我收到一个非常不祥的警告:
warning[E0502]: cannot borrow `*value` as immutable because it is also borrowed as mutable
--> src/main.rs:25:59
|
22 | fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
| -- lifetime `'a` defined here
23 | match *value {
24 | Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
| ------------ ------------------ returning this value requires that `value.0` is borrowed for `'a`
| |
| mutable borrow occurs here
25 | Value::List(_) => Err(Error("index out of range", value.clone())),
| ^^^^^ immutable borrow occurs here
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
warning[E0502]: cannot borrow `*value` as immutable because it is also borrowed as mutable
--> src/main.rs:26:46
|
22 | fn index_list<'a>(value: &'a mut Value, idx: usize) -> Result<&'a mut Value, Error> {
| -- lifetime `'a` defined here
23 | match *value {
24 | Value::List(ref mut list) if idx < list.len() => Ok(&mut list[idx]),
| ------------ ------------------ returning this value requires that `value.0` is borrowed for `'a`
| |
| mutable borrow occurs here
25 | Value::List(_) => Err(Error("index out of range", value.clone())),
26 | _ => Err(Error("tried to index int", value.clone())),
| ^^^^^ immutable borrow occurs here
|
= warning: this error has been downgraded to a warning for backwards compatibility with previous releases
= warning: this represents potential undefined behavior in your code and this warning will become a hard error in the future
我不明白为什么 Err(value.clone())
行要求 Ok(&mut ...)
借用仍然处于事件状态,因为它们是互斥的,并且都会导致函数返回。如果我移除第一个火柴臂上的防护装置,此警告就会消失,但我需要该防护装置在那里。这是 NLL 系统中的错误吗?我对旧借克从来没有遇到过这个问题。我怎样才能让它变得更好?
最佳答案
这个错误对我来说看起来像是借用检查器的限制,类似于 Double mutable borrow error in a loop happens even with NLL on 。我看不出这会如何导致健全性漏洞,并相信代码是安全的。
当使用 if
语句而不是 match
时,可以避免警告,并且代码也变得更具可读性:
fn bar<'a>(
map: &'a mut HashMap<String, Vec<i32>>,
name: &str,
idx: usize,
) -> Result<&'a mut i32, Vec<i32>> {
let value = map.get_mut(name).unwrap();
if idx < value.len() {
Ok(&mut value[idx])
} else {
Err(value.clone())
}
}
关于rust - 使用匹配臂防护时出现 "this represents potential undefined behavior in your code"错误是编译器中的错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56499960/