什么“不能借为不可变,因为它也可以借为可变的"?在嵌套数组索引中的意思? [英] What does "cannot borrow as immutable because it is also borrowed as mutable" mean in an nested array index?

查看:40
本文介绍了什么“不能借为不可变,因为它也可以借为可变的"?在嵌套数组索引中的意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这种情况下错误意味着什么:

What does the error mean in this case:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
    v[v[1]] = 999;
}

error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
 --> src/main.rs:3:7
  |
3 |     v[v[1]] = 999;
  |     --^----
  |     | |
  |     | immutable borrow occurs here
  |     mutable borrow occurs here
  |     mutable borrow later used here

我发现索引是通过 IndexIndexMut 特性实现的,而 v[1]* 的语法糖v.index(1).有了这些知识,我尝试运行以下代码:

I found that indexing is implemented via the Index and IndexMut traits and that v[1] is syntactic sugar for *v.index(1). Equipped with this knowledge, I tried to run the following code:

use std::ops::{Index, IndexMut};

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3, 4, 5];
    *v.index_mut(*v.index(1)) = 999;
}

令我惊讶的是,这完美无缺!为什么第一个片段不起作用,但第二个片段起作用?我理解文档的方式,它们应该是等效的,但显然不是这样.

To my surprise, this works flawlessly! Why doesn't the first snippet work, but the second one does? The way I understand the documentation, they should be equivalent, but this obviously isn't the case.

推荐答案

脱糖版本与您现有的略有不同.线

The desugared version is slightly different than what you have. The line

v[v[1]] = 999;

实际上是脱糖

*IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;

这会导致相同的错误消息,但注释会提示发生了什么:

This results in the same error message, but the annotations give a hint as to what's happening:

error[E0502]: cannot borrow `v` as immutable because it is also borrowed as mutable
 --> src/main.rs:7:48
  |
7 |     *IndexMut::index_mut(&mut v, *Index::index(&v, 1)) = 999;
  |      ------------------- ------                ^^ immutable borrow occurs here
  |      |                   |
  |      |                   mutable borrow occurs here
  |      mutable borrow later used by call

与脱糖版本的重要区别在于评估顺序.在实际进行函数调用之前,函数调用的参数按照列出的顺序从左到右求值.在这种情况下,这意味着首先评估 &mut v,可变地借用 v.接下来,应该对 Index::index(&v, 1) 求值,但这是不可能的 - v 已经被可变地借用了.最后,编译器显示对 index_mut() 的函数调用仍然需要可变引用,因此在尝试共享引用时可变引用仍然有效.

The important difference to your desugared version is the evaluation order. The arguments of a function call are evaluated left to right in the order listed, before actually making the function call. In this case this means that first &mut v is evaluated, mutably borrowing v. Next, Index::index(&v, 1) should be evaluated, but this is not possible – v is already mutably borrowed. Finally, the compiler shows that the mutable reference is still needed for the function call to index_mut(), so the mutable reference is still alive when the shared reference is attempted.

实际编译的版本的评估顺序略有不同.

The version that actually compiles has a slightly different evaluation order.

*v.index_mut(*v.index(1)) = 999;

首先,方法调用的函数参数从左到右求值,即 *v.index(1) 首先求值.这导致 usize,并且 v 的临时共享借用可以再次释放.然后,评估 index_mut() 的接收者,即 v 被可变地借用.这很好用,因为共享借用已经完成,并且整个表达式通过了借用检查器.

First, the function arguments to the method calls are evaluated left to right, i.e. *v.index(1) is evaluated first. This results in a usize, and the temporary shared borrow of v can be released again. Then, the receiver of index_mut() is evaluated, i.e. v is mutably borrowed. This works fine, since the shared borrow has already been finalised, and the whole expression passes the borrow checker.

请注意,自引入非词法生命周期"以来,编译版本才这样做.在 Rust 的早期版本中,共享借用会一直存在到表达式结束并导致类似的错误.

Note that the version that compiles only does so since the introduction of "non-lexical lifetimes". In earlier versions of Rust, the shared borrow would live until the end of the expression and result in a similar error.

我认为最干净的解决方案是使用临时变量:

The cleanest solution in my opinion is to use a temporary variable:

let i = v[1];
v[i] = 999;

这篇关于什么“不能借为不可变,因为它也可以借为可变的"?在嵌套数组索引中的意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆