rust - 使用匹配臂防护时出现 "this represents potential undefined behavior in your code"错误是编译器中的错误吗?

标签 rust

我的代码中的匹配表达式出现问题,当包含防护时会发出警告。我相信这个警告与借用检查器使用的非词汇生命周期有关。我的函数要么返回对集合中某个项目的可变引用,要么返回整个集合的克隆。

#[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())),
    }
}

playground

它编译并运行,但我收到一个非常不祥的警告:

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/

相关文章:

initialization - 与结构同名的函数

sockets - 如何在 Rust 中将 SocketAddr 转换为字符串?

rust - 如果让表达式如何 "read"?

multithreading - Rust 中使用的 "await"是什么意思?

rust - 使用具有生命周期参数的关联类型特征的生命周期错误

rust - 为什么 Vec<&str> 在这里缺少生命周期说明符?

c++ - 如何在 VSCode 中可视化 ndarray Rust?

optimization - 我可以在 Rust 中按值有效地返回对象吗?

rust - 无法格式化为默认格式化

function - Rust 中的绝对值函数